Linux CIFS filesystem development
 help / color / mirror / Atom feed
* ksmbd: unlocked iface_list free during server reset vs FSCTL_QUERY_NETWORK_INTERFACE_INFO traversal -> use-after-free (kernel oops)
@ 2026-09-23  8:47 朱浩
  2026-09-23  9:22 ` Greg KH
  0 siblings, 1 reply; 3+ messages in thread
From: 朱浩 @ 2026-09-23  8:47 UTC (permalink / raw)
  To: security; +Cc: linkinjeon, linkinjeon, smfrench, sfrench, linux-cifs


[-- Attachment #1.1: Type: text/plain, Size: 7150 bytes --]

Hello,
I would like to privately report a use-after-free vulnerability in the Linux kernel SMB
server (ksmbd) that leads to a kernel oops (denial of service). The bug is present in the
current upstream master as of this writing.
-------------------------------------------------------------------
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 and Unipat AI
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: 11086 bytes --]

[-- Attachment #2: vuln_n1_iface_list_uaf.tar.gz --]
[-- Type: application/x-gzip, Size: 13728 bytes --]

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

* Re: ksmbd: unlocked iface_list free during server reset vs FSCTL_QUERY_NETWORK_INTERFACE_INFO traversal -> use-after-free (kernel oops)
  2026-09-23  8:47 ksmbd: unlocked iface_list free during server reset vs FSCTL_QUERY_NETWORK_INTERFACE_INFO traversal -> use-after-free (kernel oops) 朱浩
@ 2026-09-23  9:22 ` Greg KH
       [not found]   ` <AK2AhgCLKwK9zwB7Ti6KtqpK.3.1790166059428.Hmail.2401112100@stu.pku.edu.cn>
  0 siblings, 1 reply; 3+ messages in thread
From: Greg KH @ 2026-09-23  9:22 UTC (permalink / raw)
  To: 朱浩
  Cc: security, linkinjeon, linkinjeon, smfrench, sfrench, linux-cifs

On Wed, Sep 23, 2026 at 04:47:44PM +0800, 朱浩 wrote:
> Hello,
> I would like to privately report a use-after-free vulnerability in the Linux kernel SMB
> server (ksmbd) that leads to a kernel oops (denial of service). The bug is present in the
> current upstream master as of this writing.
> -------------------------------------------------------------------
> 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.

That is very very very old and obsolete and known broken and buggy.
Please always test on the latest kernel version, hundreds, if not
thousands, of changes to the ksmbd code have happened since then.

>   - 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.

Please test to verify.

> 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.

Please create a patch that can be applied to resolve the issue so that
you get full credit for this.

thanks,

greg k-h

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

* Re: ksmbd: unlocked iface_list free during server reset vs FSCTL_QUERY_NETWORK_INTERFACE_INFO traversal -> use-after-free (kernel oops)
       [not found]   ` <AK2AhgCLKwK9zwB7Ti6KtqpK.3.1790166059428.Hmail.2401112100@stu.pku.edu.cn>
@ 2026-09-23 12:35     ` Greg KH
  0 siblings, 0 replies; 3+ messages in thread
From: Greg KH @ 2026-09-23 12:35 UTC (permalink / raw)
  To: 朱浩
  Cc: security, linkinjeon, linkinjeon, smfrench, sfrench, linux-cifs

On Wed, Sep 23, 2026 at 08:20:59PM +0800, 朱浩 wrote:
> Thank you for your feedback. I'm sending the patch and test report below. Is replying to this email the appropriate way to submit them, or would you prefer another submission channel?

Please submit it in a format that it can be applied in (please read the
submitting patches documentation).  This was sent in html format and all
of the whitespace totally corrupted.

thanks,

greg k-h

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

end of thread, other threads:[~2026-09-23 12:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23  8:47 ksmbd: unlocked iface_list free during server reset vs FSCTL_QUERY_NETWORK_INTERFACE_INFO traversal -> use-after-free (kernel oops) 朱浩
2026-09-23  9:22 ` Greg KH
     [not found]   ` <AK2AhgCLKwK9zwB7Ti6KtqpK.3.1790166059428.Hmail.2401112100@stu.pku.edu.cn>
2026-09-23 12:35     ` Greg KH

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