[PATCH] sysfs: return -ENOENT from move/rename when kobj->sd is NULL

Conor Kotwasinski
2026-04-16T15:06:03Z

sysfs_move_dir_ns() and sysfs_rename_dir_ns() pass kobj->sd to
kernfs_rename_ns() unconditionally. If sysfs_remove_dir() has already
cleared kobj->sd, the NULL flows through and kernfs_rename_ns()
dereferences it via rcu_access_pointer(kn->__parent), which KASAN
surfaces as a stack-segment fault on the shadow lookup:

Oops: stack segment: 0000 [#1] SMP KASAN PTI
RIP: 0010:kernfs_rename_ns+0x3a/0x7a0 fs/kernfs/dir.c:1752
Call Trace:
kobject_move+0x525/0x6e0 lib/kobject.c:569
device_move+0xe0/0x730 drivers/base/core.c:4606
hci_conn_del_sysfs+0xb8/0x1a0 net/bluetooth/hci_sysfs.c:75
hci_conn_cleanup net/bluetooth/hci_conn.c:173 [inline]
hci_conn_del+0xc36/0x1240 net/bluetooth/hci_conn.c:1234
hci_conn_hash_flush+0x191/0x260 net/bluetooth/hci_conn.c:2638
hci_dev_close_sync+0x821/0x1100 net/bluetooth/hci_sync.c:5327
hci_dev_do_close net/bluetooth/hci_core.c:501 [inline]
hci_unregister_dev+0x21a/0x5b0 net/bluetooth/hci_core.c:2715

syzbot has reported 35 hits with this signature across net, net-next
and linux-next between July 2025 and January 2026, via both vhci
release and HCIDEVRESET ioctl.

Return -ENOENT in that case, consistent with sysfs_create_dir_ns().
The underlying ordering problem in bluetooth -- device_move() called
after the target's sysfs has been torn down -- is a separate issue.

Reported-by: syzbot+d1db96f72a452dc9cbd2@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/687c6966.a70a0220.693ce.00a5.GAE@google.com/
Reported-by: syzbot+faeac5b54ba997a96278@syzkaller.appspotmail.com

Signed-off-by: Conor Kotwasinski <conorkotwasinski2024@u.northwestern.edu>
---
fs/sysfs/dir.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index ffdcd4153c58..6664fae288c9 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -108,6 +108,9 @@ int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
struct kernfs_node *parent;
int ret;

+ if (!kobj->sd)
+ return -ENOENT;
+
parent = kernfs_get_parent(kobj->sd);
ret = kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
kernfs_put(parent);
@@ -120,6 +123,9 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
struct kernfs_node *kn = kobj->sd;
struct kernfs_node *new_parent;

+ if (!kn)
+ return -ENOENT;
+
new_parent = new_parent_kobj && new_parent_kobj->sd ?
new_parent_kobj->sd : sysfs_root_kn;

--
2.53.0