lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251025160905.3857885-167-sashal@kernel.org>
Date: Sat, 25 Oct 2025 11:56:38 -0400
From: Sasha Levin <sashal@...nel.org>
To: patches@...ts.linux.dev,
	stable@...r.kernel.org
Cc: Xion Wang <xion.wang@...iatek.com>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Sasha Levin <sashal@...nel.org>,
	matthias.bgg@...il.com,
	angelogioacchino.delregno@...labora.com,
	linux-kernel@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org,
	linux-mediatek@...ts.infradead.org
Subject: [PATCH AUTOSEL 6.17-6.6] char: Use list_del_init() in misc_deregister() to reinitialize list pointer

From: Xion Wang <xion.wang@...iatek.com>

[ 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@...iatek.com>
Link: https://lore.kernel.org/r/20250904063714.28925-2-xion.wang@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---

LLM Generated explanations, may be completely bogus:

YES

- What changed: In drivers/char/misc.c, misc_deregister() replaces
  list_del(&misc->list) with list_del_init(&misc->list)
  (drivers/char/misc.c: list_del → list_del_init).
- Bug addressed: After list_del(), the entry’s next/prev are poisoned,
  so list_empty(&misc->list) is false and a second misc_deregister() can
  call list_del() on poisoned pointers, causing undefined behavior. With
  list_del_init(), the list node is reinitialized to point to itself, so
  list_empty(&misc->list) returns true after deregistration and a second
  call cleanly becomes a no-op for the list operation.
- Scope and impact: The fix is a one-line, localized change confined to
  the misc core. It doesn’t alter the normal registration/deregistration
  flow. The surrounding teardown remains unchanged and safe on repeated
  calls: device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor)) and
  misc_minor_free(misc->minor) are tolerant when the device is already
  gone, and the code resets the minor to MISC_DYNAMIC_MINOR afterward
  (drivers/char/misc.c: the nearby if (misc->minor > MISC_DYNAMIC_MINOR)
  misc->minor = MISC_DYNAMIC_MINOR;), further reducing risk on
  subsequent calls.
- Risk assessment: Minimal. The only behavior change is reinitializing
  the list node instead of poisoning it, which improves idempotency and
  enables correct membership checks via list_empty() after
  deregistration. Concurrency is guarded by misc_mtx as before. The main
  trade-off is slightly less aggressive poisoning for this node, but it
  materially reduces the chance of crashes from double deregistration
  paths.
- Stable criteria: This is a defensive bug fix that prevents potential
  crashes/oopses when drivers—particularly in error paths or out-of-tree
  modules—call misc_deregister() more than once. It is small, contained,
  and non-architectural, with no new features or API changes. The commit
  message explicitly notes the robustness improvement against double
  deregistration and has maintainer sign-off.

Conclusion: This is a low-risk, robustness-improving bug fix suitable
for stable backporting.

 drivers/char/misc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4c276b8066ff8..ea5b4975347a0 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -281,7 +281,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)
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ