Skip to content

Commit 29e95a4

Browse files
committed
Merge tag 'core-debugobjects-2023-04-24' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core debugobjects update from Thomas Gleixner: "A single update to debugobjects: Prevent a race vs statically initialized objects. Such objects are usually not initialized via an init() function. They are special cased and detected on first use under the assumption that they are already correctly initialized via the static initializer. This works correctly unless there are two concurrent debug object operations on such an object. The first one detects that the object is not yet tracked and tries to establish a tracking object after dropping the debug objects hash bucket lock. The concurrent operation does the same. The one which wins the race ends up modifying the state of the object which makes the other one fail resulting in a bogus debug objects warning. Prevent this by making the detection of a static object and the allocation of a tracking object atomic under the hash bucket lock. So the first one to acquire the hash bucket lock will succeed and the second one will observe the correct tracking state. This race existed forever but was only exposed when the timer wheel code added a debug_object_assert_init() call outside of the timer base locked region. This replaced the previous warning about timer::function being NULL which had to be removed when the timer_shutdown() mechanics were added" * tag 'core-debugobjects-2023-04-24' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: debugobject: Prevent init race with static objects
2 parents bc1bb2a + 63a7596 commit 29e95a4

File tree

1 file changed

+66
-59
lines changed

1 file changed

+66
-59
lines changed

lib/debugobjects.c

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,6 @@ static struct debug_obj *__alloc_object(struct hlist_head *list)
216216
return obj;
217217
}
218218

219-
/*
220-
* Allocate a new object. If the pool is empty, switch off the debugger.
221-
* Must be called with interrupts disabled.
222-
*/
223219
static struct debug_obj *
224220
alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr)
225221
{
@@ -552,11 +548,49 @@ static void debug_object_is_on_stack(void *addr, int onstack)
552548
WARN_ON(1);
553549
}
554550

551+
static struct debug_obj *lookup_object_or_alloc(void *addr, struct debug_bucket *b,
552+
const struct debug_obj_descr *descr,
553+
bool onstack, bool alloc_ifstatic)
554+
{
555+
struct debug_obj *obj = lookup_object(addr, b);
556+
enum debug_obj_state state = ODEBUG_STATE_NONE;
557+
558+
if (likely(obj))
559+
return obj;
560+
561+
/*
562+
* debug_object_init() unconditionally allocates untracked
563+
* objects. It does not matter whether it is a static object or
564+
* not.
565+
*
566+
* debug_object_assert_init() and debug_object_activate() allow
567+
* allocation only if the descriptor callback confirms that the
568+
* object is static and considered initialized. For non-static
569+
* objects the allocation needs to be done from the fixup callback.
570+
*/
571+
if (unlikely(alloc_ifstatic)) {
572+
if (!descr->is_static_object || !descr->is_static_object(addr))
573+
return ERR_PTR(-ENOENT);
574+
/* Statically allocated objects are considered initialized */
575+
state = ODEBUG_STATE_INIT;
576+
}
577+
578+
obj = alloc_object(addr, b, descr);
579+
if (likely(obj)) {
580+
obj->state = state;
581+
debug_object_is_on_stack(addr, onstack);
582+
return obj;
583+
}
584+
585+
/* Out of memory. Do the cleanup outside of the locked region */
586+
debug_objects_enabled = 0;
587+
return NULL;
588+
}
589+
555590
static void
556591
__debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack)
557592
{
558593
enum debug_obj_state state;
559-
bool check_stack = false;
560594
struct debug_bucket *db;
561595
struct debug_obj *obj;
562596
unsigned long flags;
@@ -572,16 +606,11 @@ __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack
572606

573607
raw_spin_lock_irqsave(&db->lock, flags);
574608

575-
obj = lookup_object(addr, db);
576-
if (!obj) {
577-
obj = alloc_object(addr, db, descr);
578-
if (!obj) {
579-
debug_objects_enabled = 0;
580-
raw_spin_unlock_irqrestore(&db->lock, flags);
581-
debug_objects_oom();
582-
return;
583-
}
584-
check_stack = true;
609+
obj = lookup_object_or_alloc(addr, db, descr, onstack, false);
610+
if (unlikely(!obj)) {
611+
raw_spin_unlock_irqrestore(&db->lock, flags);
612+
debug_objects_oom();
613+
return;
585614
}
586615

587616
switch (obj->state) {
@@ -607,8 +636,6 @@ __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack
607636
}
608637

609638
raw_spin_unlock_irqrestore(&db->lock, flags);
610-
if (check_stack)
611-
debug_object_is_on_stack(addr, onstack);
612639
}
613640

614641
/**
@@ -648,14 +675,12 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack);
648675
*/
649676
int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
650677
{
678+
struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr };
651679
enum debug_obj_state state;
652680
struct debug_bucket *db;
653681
struct debug_obj *obj;
654682
unsigned long flags;
655683
int ret;
656-
struct debug_obj o = { .object = addr,
657-
.state = ODEBUG_STATE_NOTAVAILABLE,
658-
.descr = descr };
659684

660685
if (!debug_objects_enabled)
661686
return 0;
@@ -664,8 +689,8 @@ int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
664689

665690
raw_spin_lock_irqsave(&db->lock, flags);
666691

667-
obj = lookup_object(addr, db);
668-
if (obj) {
692+
obj = lookup_object_or_alloc(addr, db, descr, false, true);
693+
if (likely(!IS_ERR_OR_NULL(obj))) {
669694
bool print_object = false;
670695

671696
switch (obj->state) {
@@ -698,24 +723,16 @@ int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
698723

699724
raw_spin_unlock_irqrestore(&db->lock, flags);
700725

701-
/*
702-
* We are here when a static object is activated. We
703-
* let the type specific code confirm whether this is
704-
* true or not. if true, we just make sure that the
705-
* static object is tracked in the object tracker. If
706-
* not, this must be a bug, so we try to fix it up.
707-
*/
708-
if (descr->is_static_object && descr->is_static_object(addr)) {
709-
/* track this static object */
710-
debug_object_init(addr, descr);
711-
debug_object_activate(addr, descr);
712-
} else {
713-
debug_print_object(&o, "activate");
714-
ret = debug_object_fixup(descr->fixup_activate, addr,
715-
ODEBUG_STATE_NOTAVAILABLE);
716-
return ret ? 0 : -EINVAL;
726+
/* If NULL the allocation has hit OOM */
727+
if (!obj) {
728+
debug_objects_oom();
729+
return 0;
717730
}
718-
return 0;
731+
732+
/* Object is neither static nor tracked. It's not initialized */
733+
debug_print_object(&o, "activate");
734+
ret = debug_object_fixup(descr->fixup_activate, addr, ODEBUG_STATE_NOTAVAILABLE);
735+
return ret ? 0 : -EINVAL;
719736
}
720737
EXPORT_SYMBOL_GPL(debug_object_activate);
721738

@@ -869,6 +886,7 @@ EXPORT_SYMBOL_GPL(debug_object_free);
869886
*/
870887
void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
871888
{
889+
struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr };
872890
struct debug_bucket *db;
873891
struct debug_obj *obj;
874892
unsigned long flags;
@@ -879,31 +897,20 @@ void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
879897
db = get_bucket((unsigned long) addr);
880898

881899
raw_spin_lock_irqsave(&db->lock, flags);
900+
obj = lookup_object_or_alloc(addr, db, descr, false, true);
901+
raw_spin_unlock_irqrestore(&db->lock, flags);
902+
if (likely(!IS_ERR_OR_NULL(obj)))
903+
return;
882904

883-
obj = lookup_object(addr, db);
905+
/* If NULL the allocation has hit OOM */
884906
if (!obj) {
885-
struct debug_obj o = { .object = addr,
886-
.state = ODEBUG_STATE_NOTAVAILABLE,
887-
.descr = descr };
888-
889-
raw_spin_unlock_irqrestore(&db->lock, flags);
890-
/*
891-
* Maybe the object is static, and we let the type specific
892-
* code confirm. Track this static object if true, else invoke
893-
* fixup.
894-
*/
895-
if (descr->is_static_object && descr->is_static_object(addr)) {
896-
/* Track this static object */
897-
debug_object_init(addr, descr);
898-
} else {
899-
debug_print_object(&o, "assert_init");
900-
debug_object_fixup(descr->fixup_assert_init, addr,
901-
ODEBUG_STATE_NOTAVAILABLE);
902-
}
907+
debug_objects_oom();
903908
return;
904909
}
905910

906-
raw_spin_unlock_irqrestore(&db->lock, flags);
911+
/* Object is neither tracked nor static. It's not initialized. */
912+
debug_print_object(&o, "assert_init");
913+
debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE);
907914
}
908915
EXPORT_SYMBOL_GPL(debug_object_assert_init);
909916

0 commit comments

Comments
 (0)