* Subject: [RESEND][PATCH] ksmbd: add rwsem locking for iface_list to fix UAF during server reset
@ 2026-09-23 13:19 朱浩
2026-09-23 13:22 ` Greg KH
0 siblings, 1 reply; 2+ messages in thread
From: 朱浩 @ 2026-09-23 13:19 UTC (permalink / raw)
To: Greg KH
Cc: 朱浩, security, linkinjeon, linkinjeon, smfrench,
sfrench, linux-cifs
[-- Attachment #1.1: Type: text/plain, Size: 7333 bytes --]
Hi,
Thank you for the feedback on formatting. I have repackaged the fix as a proper git format-patch patch (plain text, no HTML), so it applies cleanly.
-------------------------------------------------------------------
Fix
-------------------------------------------------------------------
You can find it in ksmbd_iface_list_uaf_fix/patches/0001-ksmbd-add-rwsem-locking-for-iface_list.patch in my uploading tar file.
-------------------------------------------------------------------
Summary
-------------------------------------------------------------------
ksmbd frees the global interface list (iface_list) without any lock during server
reset / hard-kill, *before* stop_sessions() is invoked. Meanwhile the
FSCTL_QUERY_NETWORK_INTERFACE_INFO ioctl handler traverses that same list while holding
only rtnl_lock (a lock the free path does not take), dereferencing freed iface nodes.
A remote authenticated SMB client that floods FSCTL_QUERY_NETWORK_INTERFACE_INFO while the
server is being reset can trigger a use-after-free read, producing a KASAN
slab-use-after-free report and a general protection fault (kernel oops / DoS).
-------------------------------------------------------------------
Affected component and versions
-------------------------------------------------------------------
Component: Linux kernel, fs/smb/server (ksmbd)
Confirmed present:
- Snapshot at commit af5226abb4 (6.15.0-rc3 era), where I reproduced it with KASAN.
- Current upstream master (checked 2026-09): ksmbd_tcp_destroy() still frees iface_list
without any lock, and ksmbd_find_netdev_name_iface_list() still traverses it holding
only rtnl_lock. No fix is present upstream as far as I can tell.
-------------------------------------------------------------------
Root cause (code references)
-------------------------------------------------------------------
1) The shared object:
fs/smb/server/transport_tcp.c
static LIST_HEAD(iface_list); // plain LIST_HEAD, no lock, no refcount
2) Freeing side (no lock):
fs/smb/server/transport_tcp.c : ksmbd_tcp_destroy()
unregister_netdevice_notifier(&ksmbd_netdev_notifier); // rtnl taken+released internally
list_for_each_entry_safe(iface, tmp, &iface_list, entry) {
list_del(&iface->entry); // entry->next becomes LIST_POISON under DEBUG_LIST
kfree(iface->name);
kfree(iface);
}
Call ordering (fs/smb/server/connection.c : ksmbd_conn_transport_destroy):
mutex_lock(&init_lock);
ksmbd_tcp_destroy(); // (A) frees iface_list
stop_sessions(); // (B) only afterwards stops the connection worker threads
mutex_unlock(&init_lock);
Because (A) runs before (B), the ksmbd-io workqueue workers that service in-flight SMB
requests are still active while iface_list is being freed.
3) Use side (unlocked traversal, holds only rtnl_lock):
fs/smb/server/smb2pdu.c : fsctl_query_iface_info_ioctl()
rtnl_lock();
for_each_netdev(&init_net, netdev) {
if (!ksmbd_find_netdev_name_iface_list(netdev->name)) // boolean gate
continue;
...
}
rtnl_unlock();
fs/smb/server/transport_tcp.c : ksmbd_find_netdev_name_iface_list()
list_for_each_entry(iface, &iface_list, entry)
if (!strcmp(iface->name, netdev_name)) // dereferences iface->name / walks iface->entry.next
return iface;
The traversal holds rtnl_lock; the free path does not take rtnl_lock. They are different
lock domains, so the free can proceed concurrently with the traversal.
-------------------------------------------------------------------
Trigger / reachability
-------------------------------------------------------------------
- Read side (attacker-controlled): any authenticated SMB session can issue
FSCTL_QUERY_NETWORK_INTERFACE_INFO (no_fileid_ioctl, FID = SMB2_NO_FID). No admin, no
open file, and (if the server allows guest) even weaker credentials suffice. Flooding this
ioctl from multiple connections keeps workers traversing iface_list.
- Free side (trigger): the server reset path runs when
(a) root writes "hard" to /sys/class/ksmbd-control/kill_server (kill_server_store), or
(b) the ksmbd userspace daemon heartbeat times out (server_queue_ctrl_reset_work).
These correspond to an administrator restarting / hard-killing the service.
- The race: a worker iterating iface_list (or mid-strcmp on a node) while the reset frees
that node -> use-after-free read of iface->name, or walking the list into LIST_POISON.
-------------------------------------------------------------------
Impact
-------------------------------------------------------------------
- KASAN reports "slab-use-after-free in ksmbd_find_netdev_name_iface_list".
- A subsequent general protection fault (non-canonical LIST_POISON dereference) -> kernel oops.
- Denial of service: with panic_on_oops the machine panics; otherwise the worker is killed.
The list_del + kfree of the name and the node can also leave a dangling name pointer.
- This is a read-only UAF (no write primitive, no function-pointer in struct interface),
so the practical impact is kernel DoS rather than privilege escalation.
-------------------------------------------------------------------
Evidence
-------------------------------------------------------------------
Reproduced on the vulnerable kernel (6.15.0-rc3, KASAN enabled) with:
- a userspace SMB client flooding FSCTL_QUERY_NETWORK_INTERFACE_INFO (12 threads,
authenticated session, no open file), and
- a VM-side root writing "hard" to /sys/class/ksmbd-control/kill_server (reset loop).
KASAN report (abridged):
BUG: KASAN: slab-use-after-free in ksmbd_find_netdev_name_iface_list+0x64/0x90
Read of size 8 ... by task kworker/...
Call Trace:
fsctl_query_iface_info_ioctl.isra.0
smb2_ioctl
handle_ksmbd_work
Freed by task 1:
kfree
ksmbd_tcp_destroy
ksmbd_conn_transport_destroy
server_ctrl_handle_reset
kill_server_store <- the sysfs write that triggers the reset
The buggy address belongs to the object at ffff... which belongs to the cache kmalloc-96
...
Oops: general protection fault, probably for non-canonical address 0xdead...:
RIP: ksmbd_find_netdev_name_iface_list+0x48
I also have a self-contained userspace reproducer (python, SMB2 client) and the full KASAN
splat available; happy to share them on request.
-------------------------------------------------------------------
Suggested fix
-------------------------------------------------------------------
Any of:
1. Protect iface_list with a dedicated lock shared by ksmbd_tcp_destroy() and
ksmbd_find_netdev_name_iface_list() (and all other traversers);
2. Free the nodes via RCU and traverse under rcu_read_lock();
3. Reorder ksmbd_conn_transport_destroy() to run stop_sessions() before freeing iface_list.
-------------------------------------------------------------------
Credit
-------------------------------------------------------------------
Discovered and reported by:
Hao Zhu
Peking University
Thank you for maintaining ksmbd. Please let me know if you need any additional detail or the reproducer. I am happy to follow your embargo/disclosure timeline.
Best regards,
Hao Zhu
朱浩
2401112100@stu.pku.edu.cn
[-- Attachment #1.2: Type: text/html, Size: 20065 bytes --]
[-- Attachment #2: ksmbd_iface_list_uaf_fix.tar-zhuhao.gz --]
[-- Type: application/x-gzip, Size: 12922 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: Subject: [RESEND][PATCH] ksmbd: add rwsem locking for iface_list to fix UAF during server reset
2026-09-23 13:19 Subject: [RESEND][PATCH] ksmbd: add rwsem locking for iface_list to fix UAF during server reset 朱浩
@ 2026-09-23 13:22 ` Greg KH
0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2026-09-23 13:22 UTC (permalink / raw)
To: 朱浩
Cc: security, linkinjeon, linkinjeon, smfrench, sfrench, linux-cifs
On Wed, Sep 23, 2026 at 09:19:41PM +0800, 朱浩 wrote:
> Hi,
> Thank you for the feedback on formatting. I have repackaged the fix as a proper git format-patch patch (plain text, no HTML), so it applies cleanly.
You sent an html email and a binary, compressed attachment :(
Please read the documentation again, specifically the email clients
file, for how to do this properly. Perhaps point your LLM at it?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-23 13:35 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23 13:19 Subject: [RESEND][PATCH] ksmbd: add rwsem locking for iface_list to fix UAF during server reset 朱浩
2026-09-23 13:22 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox