Skip to content

Commit 8c717b7

Browse files
committed
Merge branch 'core-debugobjects-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'core-debugobjects-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: timer: Use debugobjects to catch deletion of uninitialized timers timer: Setup uninitialized timer with a stub callback debugobjects: Extend to assert that an object is initialized debugobjects: Be smarter about static objects
2 parents 07d106d + dc4218b commit 8c717b7

4 files changed

Lines changed: 162 additions & 10 deletions

File tree

Documentation/DocBook/debugobjects.tmpl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
<listitem><para>debug_object_deactivate</para></listitem>
9797
<listitem><para>debug_object_destroy</para></listitem>
9898
<listitem><para>debug_object_free</para></listitem>
99+
<listitem><para>debug_object_assert_init</para></listitem>
99100
</itemizedlist>
100101
Each of these functions takes the address of the real object and
101102
a pointer to the object type specific debug description
@@ -273,6 +274,26 @@
273274
debug checks.
274275
</para>
275276
</sect1>
277+
278+
<sect1 id="debug_object_assert_init">
279+
<title>debug_object_assert_init</title>
280+
<para>
281+
This function is called to assert that an object has been
282+
initialized.
283+
</para>
284+
<para>
285+
When the real object is not tracked by debugobjects, it calls
286+
fixup_assert_init of the object type description structure
287+
provided by the caller, with the hardcoded object state
288+
ODEBUG_NOT_AVAILABLE. The fixup function can correct the problem
289+
by calling debug_object_init and other specific initializing
290+
functions.
291+
</para>
292+
<para>
293+
When the real object is already tracked by debugobjects it is
294+
ignored.
295+
</para>
296+
</sect1>
276297
</chapter>
277298
<chapter id="fixupfunctions">
278299
<title>Fixup functions</title>
@@ -381,6 +402,35 @@
381402
statistics.
382403
</para>
383404
</sect1>
405+
<sect1 id="fixup_assert_init">
406+
<title>fixup_assert_init</title>
407+
<para>
408+
This function is called from the debug code whenever a problem
409+
in debug_object_assert_init is detected.
410+
</para>
411+
<para>
412+
Called from debug_object_assert_init() with a hardcoded state
413+
ODEBUG_STATE_NOTAVAILABLE when the object is not found in the
414+
debug bucket.
415+
</para>
416+
<para>
417+
The function returns 1 when the fixup was successful,
418+
otherwise 0. The return value is used to update the
419+
statistics.
420+
</para>
421+
<para>
422+
Note, this function should make sure debug_object_init() is
423+
called before returning.
424+
</para>
425+
<para>
426+
The handling of statically initialized objects is a special
427+
case. The fixup function should check if this is a legitimate
428+
case of a statically initialized object or not. In this case only
429+
debug_object_init() should be called to make the object known to
430+
the tracker. Then the function should return 0 because this is not
431+
a real fixup.
432+
</para>
433+
</sect1>
384434
</chapter>
385435
<chapter id="bugs">
386436
<title>Known Bugs And Assumptions</title>

include/linux/debugobjects.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ struct debug_obj {
4646
* fails
4747
* @fixup_free: fixup function, which is called when the free check
4848
* fails
49+
* @fixup_assert_init: fixup function, which is called when the assert_init
50+
* check fails
4951
*/
5052
struct debug_obj_descr {
5153
const char *name;
@@ -54,6 +56,7 @@ struct debug_obj_descr {
5456
int (*fixup_activate) (void *addr, enum debug_obj_state state);
5557
int (*fixup_destroy) (void *addr, enum debug_obj_state state);
5658
int (*fixup_free) (void *addr, enum debug_obj_state state);
59+
int (*fixup_assert_init)(void *addr, enum debug_obj_state state);
5760
};
5861

5962
#ifdef CONFIG_DEBUG_OBJECTS
@@ -64,6 +67,7 @@ extern void debug_object_activate (void *addr, struct debug_obj_descr *descr);
6467
extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
6568
extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr);
6669
extern void debug_object_free (void *addr, struct debug_obj_descr *descr);
70+
extern void debug_object_assert_init(void *addr, struct debug_obj_descr *descr);
6771

6872
/*
6973
* Active state:
@@ -89,6 +93,8 @@ static inline void
8993
debug_object_destroy (void *addr, struct debug_obj_descr *descr) { }
9094
static inline void
9195
debug_object_free (void *addr, struct debug_obj_descr *descr) { }
96+
static inline void
97+
debug_object_assert_init(void *addr, struct debug_obj_descr *descr) { }
9298

9399
static inline void debug_objects_early_init(void) { }
94100
static inline void debug_objects_mem_init(void) { }

kernel/timer.c

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,12 @@ static int timer_fixup_init(void *addr, enum debug_obj_state state)
427427
}
428428
}
429429

430+
/* Stub timer callback for improperly used timers. */
431+
static void stub_timer(unsigned long data)
432+
{
433+
WARN_ON(1);
434+
}
435+
430436
/*
431437
* fixup_activate is called when:
432438
* - an active object is activated
@@ -450,7 +456,8 @@ static int timer_fixup_activate(void *addr, enum debug_obj_state state)
450456
debug_object_activate(timer, &timer_debug_descr);
451457
return 0;
452458
} else {
453-
WARN_ON_ONCE(1);
459+
setup_timer(timer, stub_timer, 0);
460+
return 1;
454461
}
455462
return 0;
456463

@@ -480,12 +487,40 @@ static int timer_fixup_free(void *addr, enum debug_obj_state state)
480487
}
481488
}
482489

490+
/*
491+
* fixup_assert_init is called when:
492+
* - an untracked/uninit-ed object is found
493+
*/
494+
static int timer_fixup_assert_init(void *addr, enum debug_obj_state state)
495+
{
496+
struct timer_list *timer = addr;
497+
498+
switch (state) {
499+
case ODEBUG_STATE_NOTAVAILABLE:
500+
if (timer->entry.prev == TIMER_ENTRY_STATIC) {
501+
/*
502+
* This is not really a fixup. The timer was
503+
* statically initialized. We just make sure that it
504+
* is tracked in the object tracker.
505+
*/
506+
debug_object_init(timer, &timer_debug_descr);
507+
return 0;
508+
} else {
509+
setup_timer(timer, stub_timer, 0);
510+
return 1;
511+
}
512+
default:
513+
return 0;
514+
}
515+
}
516+
483517
static struct debug_obj_descr timer_debug_descr = {
484-
.name = "timer_list",
485-
.debug_hint = timer_debug_hint,
486-
.fixup_init = timer_fixup_init,
487-
.fixup_activate = timer_fixup_activate,
488-
.fixup_free = timer_fixup_free,
518+
.name = "timer_list",
519+
.debug_hint = timer_debug_hint,
520+
.fixup_init = timer_fixup_init,
521+
.fixup_activate = timer_fixup_activate,
522+
.fixup_free = timer_fixup_free,
523+
.fixup_assert_init = timer_fixup_assert_init,
489524
};
490525

491526
static inline void debug_timer_init(struct timer_list *timer)
@@ -508,6 +543,11 @@ static inline void debug_timer_free(struct timer_list *timer)
508543
debug_object_free(timer, &timer_debug_descr);
509544
}
510545

546+
static inline void debug_timer_assert_init(struct timer_list *timer)
547+
{
548+
debug_object_assert_init(timer, &timer_debug_descr);
549+
}
550+
511551
static void __init_timer(struct timer_list *timer,
512552
const char *name,
513553
struct lock_class_key *key);
@@ -531,6 +571,7 @@ EXPORT_SYMBOL_GPL(destroy_timer_on_stack);
531571
static inline void debug_timer_init(struct timer_list *timer) { }
532572
static inline void debug_timer_activate(struct timer_list *timer) { }
533573
static inline void debug_timer_deactivate(struct timer_list *timer) { }
574+
static inline void debug_timer_assert_init(struct timer_list *timer) { }
534575
#endif
535576

536577
static inline void debug_init(struct timer_list *timer)
@@ -552,6 +593,11 @@ static inline void debug_deactivate(struct timer_list *timer)
552593
trace_timer_cancel(timer);
553594
}
554595

596+
static inline void debug_assert_init(struct timer_list *timer)
597+
{
598+
debug_timer_assert_init(timer);
599+
}
600+
555601
static void __init_timer(struct timer_list *timer,
556602
const char *name,
557603
struct lock_class_key *key)
@@ -902,6 +948,8 @@ int del_timer(struct timer_list *timer)
902948
unsigned long flags;
903949
int ret = 0;
904950

951+
debug_assert_init(timer);
952+
905953
timer_stats_timer_clear_start_info(timer);
906954
if (timer_pending(timer)) {
907955
base = lock_timer_base(timer, &flags);
@@ -932,6 +980,8 @@ int try_to_del_timer_sync(struct timer_list *timer)
932980
unsigned long flags;
933981
int ret = -1;
934982

983+
debug_assert_init(timer);
984+
935985
base = lock_timer_base(timer, &flags);
936986

937987
if (base->running_timer == timer)

lib/debugobjects.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,16 @@ static void debug_print_object(struct debug_obj *obj, char *msg)
268268
* Try to repair the damage, so we have a better chance to get useful
269269
* debug output.
270270
*/
271-
static void
271+
static int
272272
debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
273273
void * addr, enum debug_obj_state state)
274274
{
275+
int fixed = 0;
276+
275277
if (fixup)
276-
debug_objects_fixups += fixup(addr, state);
278+
fixed = fixup(addr, state);
279+
debug_objects_fixups += fixed;
280+
return fixed;
277281
}
278282

279283
static void debug_object_is_on_stack(void *addr, int onstack)
@@ -386,6 +390,9 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
386390
struct debug_bucket *db;
387391
struct debug_obj *obj;
388392
unsigned long flags;
393+
struct debug_obj o = { .object = addr,
394+
.state = ODEBUG_STATE_NOTAVAILABLE,
395+
.descr = descr };
389396

390397
if (!debug_objects_enabled)
391398
return;
@@ -425,8 +432,9 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr)
425432
* let the type specific code decide whether this is
426433
* true or not.
427434
*/
428-
debug_object_fixup(descr->fixup_activate, addr,
429-
ODEBUG_STATE_NOTAVAILABLE);
435+
if (debug_object_fixup(descr->fixup_activate, addr,
436+
ODEBUG_STATE_NOTAVAILABLE))
437+
debug_print_object(&o, "activate");
430438
}
431439

432440
/**
@@ -562,6 +570,44 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr)
562570
raw_spin_unlock_irqrestore(&db->lock, flags);
563571
}
564572

573+
/**
574+
* debug_object_assert_init - debug checks when object should be init-ed
575+
* @addr: address of the object
576+
* @descr: pointer to an object specific debug description structure
577+
*/
578+
void debug_object_assert_init(void *addr, struct debug_obj_descr *descr)
579+
{
580+
struct debug_bucket *db;
581+
struct debug_obj *obj;
582+
unsigned long flags;
583+
584+
if (!debug_objects_enabled)
585+
return;
586+
587+
db = get_bucket((unsigned long) addr);
588+
589+
raw_spin_lock_irqsave(&db->lock, flags);
590+
591+
obj = lookup_object(addr, db);
592+
if (!obj) {
593+
struct debug_obj o = { .object = addr,
594+
.state = ODEBUG_STATE_NOTAVAILABLE,
595+
.descr = descr };
596+
597+
raw_spin_unlock_irqrestore(&db->lock, flags);
598+
/*
599+
* Maybe the object is static. Let the type specific
600+
* code decide what to do.
601+
*/
602+
if (debug_object_fixup(descr->fixup_assert_init, addr,
603+
ODEBUG_STATE_NOTAVAILABLE))
604+
debug_print_object(&o, "assert_init");
605+
return;
606+
}
607+
608+
raw_spin_unlock_irqrestore(&db->lock, flags);
609+
}
610+
565611
/**
566612
* debug_object_active_state - debug checks object usage state machine
567613
* @addr: address of the object

0 commit comments

Comments
 (0)