]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
char: Use list_del_init() in misc_deregister() to reinitialize list pointer
authorXion Wang <xion.wang@mediatek.com>
Thu, 4 Sep 2025 06:37:04 +0000 (14:37 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:20 +0000 (15:34 -0500)
[ Upstream commit e28022873c0d051e980c4145f1965cab5504b498 ]

Currently, misc_deregister() uses list_del() to remove the device
from the list. After list_del(), the list pointers are set to
LIST_POISON1 and LIST_POISON2, which may help catch use-after-free bugs,
but does not reset the list head.
If misc_deregister() is called more than once on the same device,
list_empty() will not return true, and list_del() may be called again,
leading to undefined behavior.

Replace list_del() with list_del_init() to reinitialize the list head
after deletion. This makes the code more robust against double
deregistration and allows safe usage of list_empty() on the miscdevice
after deregistration.

[ Note, this seems to keep broken out-of-tree drivers from doing foolish
  things.  While this does not matter for any in-kernel drivers,
  external drivers could use a bit of help to show them they shouldn't
  be doing stuff like re-registering misc devices - gregkh ]

Signed-off-by: Xion Wang <xion.wang@mediatek.com>
Link: https://lore.kernel.org/r/20250904063714.28925-2-xion.wang@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/char/misc.c

index 6f9ce6b3cc5a655f11ddf78db446d936b9967a47..792a1412faffefb8cc147f3c384d29a34d8ace9c 100644 (file)
@@ -299,7 +299,7 @@ void misc_deregister(struct miscdevice *misc)
                return;
 
        mutex_lock(&misc_mtx);
-       list_del(&misc->list);
+       list_del_init(&misc->list);
        device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor));
        misc_minor_free(misc->minor);
        if (misc->minor > MISC_DYNAMIC_MINOR)