Linux driver-core infrastructure
 help / color / mirror / Atom feed
* [PATCH] sysfs: fix use-after-free in sysfs_create_dir_ns
@ 2026-07-01 13:16 l1za0.sec
  2026-07-01 13:42 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: l1za0.sec @ 2026-07-01 13:16 UTC (permalink / raw)
  To: gregkh; +Cc: rafael, dakr, driver-core, linux-kernel

From: Haocheng Yu <l1za0.sec@gmail.com>

A KASAN: slab-use-after-free Read in kernfs_next_descendant_post is
reported by a modified Syzkaller-based kernel fuzzing tool we
developed.

This problem is caused by a race condition between sysfs directory
creation for a child kobject and removal of the parent kobject. In this
case, the ueagle-atm driver starts an async firmware request for a
pre-firmware USB device. The firmware work falls back to the sysfs
firmware loader and tries to add a firmware class device under the USB
device while usb_disconnect() is removing the USB device from sysfs.

sysfs_create_dir_ns() reads kobj->parent->sd without taking a reference
to the parent kernfs_node. sysfs_remove_dir() may concurrently detach the
same parent from sysfs and drop the last kernfs reference. The following
kernfs_create_dir_ns() then uses a freed parent kernfs_node and
kernfs_activate() can dereference it, triggering a use-after-free.

To fix this vulnerability, take a kernfs reference to the parent while
holding sysfs_symlink_target_lock, the same lock that serializes
sysfs_remove_dir() against kobj->sd detachment. If the parent has already
been detached, fail the creation with -ENOENT. Drop the temporary
reference after the child directory creation attempt completes.

Signed-off-by: Haocheng Yu <l1za0.sec@gmail.com>
---
 fs/sysfs/dir.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index ffdcd4153c58..1883a4380250 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -46,10 +46,16 @@ int sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns)
 	if (WARN_ON(!kobj))
 		return -EINVAL;
 
-	if (kobj->parent)
+	if (kobj->parent) {
+		spin_lock(&sysfs_symlink_target_lock);
 		parent = kobj->parent->sd;
-	else
+		if (parent)
+			kernfs_get(parent);
+		spin_unlock(&sysfs_symlink_target_lock);
+	} else {
 		parent = sysfs_root_kn;
+		kernfs_get(parent);
+	}
 
 	if (!parent)
 		return -ENOENT;
@@ -61,10 +67,12 @@ int sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns)
 	if (IS_ERR(kn)) {
 		if (PTR_ERR(kn) == -EEXIST)
 			sysfs_warn_dup(parent, kobject_name(kobj));
+		kernfs_put(parent);
 		return PTR_ERR(kn);
 	}
 
 	kobj->sd = kn;
+	kernfs_put(parent);
 	return 0;
 }
 

base-commit: 665159e246749578d4e4bfe106ee3b74edcdab18
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-01 13:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 13:16 [PATCH] sysfs: fix use-after-free in sysfs_create_dir_ns l1za0.sec
2026-07-01 13:42 ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox