The patch titled Subject: kmemleak: do not corrupt the object_list during clean-up has been added to the -mm tree. Its filename is kmemleak-do-not-corrupt-the-object_list-during-clean-up.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/kmemleak-do-not-corrupt-the-object_list-during-clean-up.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/kmemleak-do-not-corrupt-the-object_list-during-clean-up.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Catalin Marinas <catalin.marinas@xxxxxxx> Subject: kmemleak: do not corrupt the object_list during clean-up In case of an error (e.g. memory pool too small), kmemleak disables itself and cleans up the already allocated metadata objects. However, if this happens early before the RCU callback mechanism is available, put_object() skips call_rcu() and frees the object directly. This is not safe with the RCU list traversal in __kmemleak_do_cleanup(). Change the list traversal in __kmemleak_do_cleanup() to list_for_each_entry_safe() and remove the rcu_read_{lock,unlock} since the kmemleak is already disabled at this point. In addition, avoid an unnecessary metadata object rb-tree look-up since it already has the struct kmemleak_object pointer. Link: http://lkml.kernel.org/r/20191004134624.46216-1-catalin.marinas@xxxxxxx Fixes: c5665868183f ("mm: kmemleak: use the memory pool for early allocations") Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx> Reported-by: Alexey Kardashevskiy <aik@xxxxxxxxx> Reported-by: Marc Dionne <marc.c.dionne@xxxxxxxxx> Tested-by: Alexey Kardashevskiy <aik@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/kmemleak.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) --- a/mm/kmemleak.c~kmemleak-do-not-corrupt-the-object_list-during-clean-up +++ a/mm/kmemleak.c @@ -527,6 +527,16 @@ static struct kmemleak_object *find_and_ } /* + * Remove an object from the object_tree_root and object_list. Must be called + * with the kmemleak_lock held _if_ kmemleak is still enabled. + */ +static void __remove_object(struct kmemleak_object *object) +{ + rb_erase(&object->rb_node, &object_tree_root); + list_del_rcu(&object->object_list); +} + +/* * Look up an object in the object search tree and remove it from both * object_tree_root and object_list. The returned object's use_count should be * at least 1, as initially set by create_object(). @@ -538,10 +548,8 @@ static struct kmemleak_object *find_and_ write_lock_irqsave(&kmemleak_lock, flags); object = lookup_object(ptr, alias); - if (object) { - rb_erase(&object->rb_node, &object_tree_root); - list_del_rcu(&object->object_list); - } + if (object) + __remove_object(object); write_unlock_irqrestore(&kmemleak_lock, flags); return object; @@ -1834,12 +1842,16 @@ static const struct file_operations kmem static void __kmemleak_do_cleanup(void) { - struct kmemleak_object *object; + struct kmemleak_object *object, *tmp; - rcu_read_lock(); - list_for_each_entry_rcu(object, &object_list, object_list) - delete_object_full(object->pointer); - rcu_read_unlock(); + /* + * Kmemleak has already been disabled, no need for RCU list traversal + * or kmemleak_lock held. + */ + list_for_each_entry_safe(object, tmp, &object_list, object_list) { + __remove_object(object); + __delete_object(object); + } } /* _ Patches currently in -mm which might be from catalin.marinas@xxxxxxx are kmemleak-do-not-corrupt-the-object_list-during-clean-up.patch