






















The Orca Security Research Pod discovered a use-after-free race condition in the Linux kernel’s ksmbd SMB3 server. When two connections share a session over SMB3 multichannel, the kernel can read a freed channel struct – exposing the per-channel AES-128-CMAC signing key and causing a kernel panic. An attacker needs valid SMB credentials and network access to port 445. No exotic prerequisites. The fix is merged (commit e4a8a96a93d) – update your kernel.
| Attribute | Details |
|---|---|
| CVE | CVE-2026-23226 |
| Researcher CVSS | 7.5 High – AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H |
| NVD CVSS | 7.8 High – AV:L/AC:H (under dispute – see scoring note) |
| CWE | CWE-416 (Use After Free), CWE-362 (Race Condition) |
| Affected Component | Linux kernel ksmbd SMB3 server – ksmbd_chann_list XArray |
| Bug Introduced | commit 1d9c4172110e (Dec 2023) – channel list converted to XArray without synchronization |
| Confirmed Affected | Linux kernels containing commit `1d9c4172110e` without `e4a8a96a93d` (approx. 5.15.145+, 6.1.x select builds, 6.7 through 6.19.0) |
| Attack Vector | Network – SMB3 port 445 |
| Authentication | Low – valid SMB user credentials required |
| Exploit Complexity | High – race condition, ~1 hit per 750 attempts |
| Active Exploitation | None confirmed |
| PoC Available | Yes – developed and confirmed by Orca Security Research Pod |
| Fix | Merged – commit e4a8a96a93d (stable), upstream 4f3a06cc579 |
| Discovered By | Orca Security Research Pod |
| Patch Author | Namjae Jeon, ksmbd maintainer |
| Coordination | Greg KH, Steve French, kernel security team |
Most Linux administrators know Samba – the long-standing userspace daemon that lets Linux servers share files with Windows clients over SMB. ksmbd is its younger, kernel-native counterpart. Merged into mainline Linux in kernel 5.15 (November 2021), it implements the SMB2/3 protocol entirely inside the kernel for better performance – no context switches to userspace for every request.
That architectural choice has a direct security consequence: a vulnerability in ksmbd is a kernel vulnerability. It doesn’t compromise a process running as root. It compromises the kernel itself – full machine takeover territory.
ksmbd has accumulated a notable list of serious bugs since its merge. The pattern is consistent: complex concurrent state management introduced without adequate locking. Before CVE-2026-23226, notable examples include CVE-2022-47939 (unauthenticated out-of-bounds write leading to RCE), CVE-2023-32254 (TOCTOU race in session setup), CVE-2023-32257 (use-after-free), and, directly related to this finding, CVE-2025-40039. That last one is worth understanding, because CVE-2026-23226 is essentially the same mistake made twice.
CVE-2025-40039 involved the rpc_handle_list XArray inside struct ksmbd_session – another sparse array used to track shared mutable state across threads. It had no lock. The fix added rpc_lock (a read-write semaphore). That fix was applied in 2025. But ksmbd_session has three XArrays. Only one was fixed. The ksmbd_chann_list XArray – used to track multichannel connections – was left unprotected. CVE-2026-23226 is that oversight.
To understand the vulnerability, you need to understand what multichannel is and why it creates concurrent access to the channel list.
ksmbd_session object must track all active TCP connections as “channels,” stored in the ksmbd_chann_list XArray.The setup requires two distinct phases. First, the client authenticates over a primary TCP connection using full NTLM authentication – this is standard SMB3. Then, for each additional connection (channel), the client sends a special SESSION_SETUP request with a flag set: SESSION_FLAG_BINDING = 0x01. This binding request references the already-authenticated session ID and must be signed with the session’s AES-128-CMAC key.
When ksmbd sees that binding flag, it takes a completely different code path – the binding_session label in smb2_sess_setup(). This is the path where the race lives.

The binding path has a strict set of requirements ksmbd validates before proceeding:
SMB2_FLAGS_SIGNED)ClientGUID must match the primary sessionSMB2_SESSION_VALID stateAll of these are checked correctly. The bug isn’t in the validation. It’s in what happens after, when ksmbd looks up the channel list to register the new connection.
struct ksmbd_session tracks three types of shared mutable state, each in its own XArray. Here’s the problem in plain sight:

Two out of three XArrays got locks. The channel list was left bare.
ksmbd_chann_list to map TCP connection pointers to struct channel objects. The key operations are xa_load() (read an entry) and xa_erase() (atomically remove and return an entry). These two operations are not safe to call simultaneously from different threads without external locking, the XArray’s internal lock only protects modifications against other modifications, not a reader against a concurrent erase.The read path – called from the channel binding handler, performs a bare xa_load() with no lock held:

The delete path – triggered during session logoff, calls xa_erase() then immediately kfree(), also with no lock:

Note the use of kfree() rather than kfree_rcu(). RCU (Read-Copy-Update) is the standard kernel mechanism for safely freeing objects that concurrent readers might still hold. Not using it means the memory is freed immediately, with no grace period for in-flight readers to finish. Combined with no lock on the read side, this is a textbook use-after-free setup.
struct channel is a 24-byte object (kmalloc-32 slab):

Three call sites in smb2pdu.c dereference the returned channel pointer to read the signing key, without any synchronization:

The signing key is the AES-128-CMAC key used to verify every SMB3 packet on this channel. Reading it from freed memory means either reading garbage (signature verification will fail with corrupted data) or reading the original key if the allocator hasn’t reused the slot yet (signing key exposure).
The critical enabling factor is ksmbd_conn_wait_idle(). During connection teardown, ksmbd calls this function to drain in-flight work before freeing the connection’s resources. But it only drains the work queue of the specific connection being torn down – not all connections that share the same session.
This means: when conn2 tears down and calls ksmbd_chann_del() to free conn1’s channel struct, conn1’s worker threads may still be processing signed requests that call lookup_chann_list(). There is no session-level barrier. The teardown of one connection races freely against the ongoing work of another connection in the same session.

On a 4-core machine with ksmbd’s concurrent ksmbd-io worker thread pool, this window is wide enough to hit reliably – our PoC fires 8–11 times per 500-iteration run with the first hit typically within 60–120 seconds.
The race produces three possible outcomes, depending on timing and allocator state:
Signing key leak. If the kmalloc-32 slab slot hasn’t been overwritten by the time lookup_chann_list() reads it, the UAF returns the original 16-byte smb3signingkey. This is the per-channel AES-128-CMAC key used to sign all SMB3 traffic on that channel. An attacker who recovers this key can forge signatures, impersonate the server, or bypass signature verification entirely for the duration of the session.
Signature bypass via garbage key. Even if the slot has been partially overwritten, ksmbd will use whatever garbage bytes it reads as the signing key. Server-side signature verification will silently accept or reject packets based on corrupted state – undermining the integrity guarantees that SMB3 signing is supposed to provide.
Kernel panic (DoS). The struct channel contains chann->conn at offset 16 – a pointer to the connection object. If the freed slot gets reallocated and partially overwritten, dereferencing this pointer causes a kernel panic. This is the most reliably observable outcome and what our PoC consistently triggers on KASAN builds.
The current PoC does not achieve kernel code execution. It proves the UAF reliably and triggers a kernel crash. Converting a race-based UAF to full RCE requires additional work: confirming a write UAF path, heap grooming in kmalloc-32, building a KASLR bypass from the information leak, and constructing a full exploit chain. That is a realistic multi-month research effort – and a separate project. We’re disclosing at UAF confirmation because that’s the honest and correct point to disclose. The vulnerability is real, the impact is significant, and the fix is available.
| Environment | Risk |
|---|---|
| Linux kernel since Dec 2023 + ksmbd + multichannel enabled | Affected |
| Linux kernel before commit 1d9c4172110e (Dec 2023) | Not affected – bug not yet introduced |
| ksmbd running but multichannel not configured | Significantly reduced – binding code path unreachable |
| Samba (smbd, not ksmbd) | Not affected – separate implementation |
| No SMB server running | Not affected |
Our researcher assessed score is 7.5 High with Attack Vector: Network (AV:N). The attack requires sending SMB3 packets to port 445 from a remote machine – no local access. NVD currently scores it 7.8 High with AV:L (Local), which we believe is incorrect. Notably, correcting the vector to AV:N actually lowers the score from 7.8 to 7.5 – this is a technical accuracy dispute, not an attempt to inflate severity. A formal CVSS dispute has been filed referencing this post.
Namjae Jeon (ksmbd maintainer) sent the patch the morning after our disclosure. We reviewed it, confirmed it covered all five access points, and it was committed by Greg KH on February 16, 2026.
e4a8a96a93d08570e0405cfd989a8a07e5b6ff334f3a06cc57976cafa8c6f716646be6c79a99e485Cc: stable@vger.kernel.org)The fix adds one field to struct ksmbd_session:

And protects all five access points. The key subtlety in ksmbd_chann_del() – the write lock wraps only the xa_erase(), then releases before kfree(). This is intentional: the lock guards the XArray from concurrent access. Once the pointer is removed from the array and no other holder exists, the free needs no lock.

free_channel_list() and both xa_store() call sites in the session binding path are also wrapped with down_write/up_write in the patch.

When we initially disclosed to the kernel security team, we noted that no KASAN-triggering PoC existed. The problem: triggering the race requires a custom SMB3 client that implements channel binding with SESSION_FLAG_BINDING = 0x01, correct AES-128-CMAC signing, and matching dialect negotiation. No existing tool – smbclient, Impacket, or otherwise – does this out of the box.
Building the PoC took five iterations:
login() twice. Never reached the binding path because Impacket always sends Flags = 0. No UAF.SESSION_FLAG_BINDING = 0x01. Got STATUS_INVALID_PARAMETER. Root cause: secondary connection negotiated SMB 3.0 while primary used SMB 3.1.1 – ksmbd checks dialect match and rejects.STATUS_INVALID_PARAMETER. Root cause: Capabilities field packed as 2 bytes (<H) instead of 4 (<I), corrupting the entire packet body.STATUS_USER_SESSION_DELETED. Root cause: signed with HMAC-SHA256 instead of AES-128-CMAC. SMB 3.0 uses AES-128-CMAC for signing – wrong algorithm means signature verification fails.The final insight: don’t fight the protocol stack, patch the one missing feature.

Setting smb3._binding = True on a connection object causes its next SESSION_SETUP to send SESSION_FLAG_BINDING = 0x01. All signing, NTLM, and dialect handling stay in Impacket’s existing implementation – unchanged.



The PoC was confirmed on Linux 6.12.0 in a KASAN-enabled QEMU/KVM VM on bare metal Ubuntu 24.04:
CONFIG_KASAN_GENERIC=y – makes the UAF visible as a clean crash reportCONFIG_RANDOMIZE_BASE=n – KASLR disabled for lab convenience only, doesn’t affect UAF triggeringkasan_multi_shot=1 boot parameter – KASAN keeps reporting after the first hit rather than going silent, essential for measuring hit rate
The PoC runs on the attacker machine (right) and sends SMB3 packets over the network to the VM running ksmbd (left). Within ~2 minutes, the race fires and KASAN reports the UAF in real time
Split-screen: VM terminal (left) showing BUG: KASAN: slab-use-after-free in smb2_sess_setup+0x4300/0x5f80 appearing. Host terminal (right) showing [*] Round 100/500. Both visible simultaneously – network attack on the right, kernel crash on the left.
The KASAN splat from our run:

Reading the splat: Thread 38687 allocated the object during session login. Thread 28565 freed it during logoff. The same thread 28565 then attempts to read it in the binding path – KASAN catches the access to the freed kmalloc slab.
The race fires across all four CPUs in our VM:

Hits on CPUs 1, 2, and 3 independently – this is a genuine SMP race across ksmbd’s worker thread pool, not a single-threaded timing artifact.

A note on the KASAN object size: Our KASAN output shows a kmalloc-64 object allocated by ksmbd_alloc_user. The original vulnerability report describes the UAF on the 24-byte struct channel (kmalloc-32) via smb3_check_sign_req(). Both paths involve the same missing lock on ksmbd_chann_list – our PoC happened to trigger a related object free in the same logoff path. The struct channel / smb3signingkey path described in the original report is the most security-sensitive impact (signing key exposure), the kmalloc-64 hit confirms the broader locking gap.
Update to a kernel containing commit e4a8a96a93d08570e0405cfd989a8a07e5b6ff33. The patch has been officially released – check your distribution’s kernel security advisories for when it lands in your specific branch.
| Deployment | Action |
|---|---|
| ksmbd + multichannel enabled | Disable multichannel if not required: remove ksmbd: smb3 multichannel = yes from smb.conf, restart ksmbd |
| ksmbd + multichannel not configured | Lower risk – the binding code path is unreachable. Verify with grep -r multichannel /etc/ksmbd/ |
| Samba (smbd, not ksmbd) | Not affected |
| No SMB server running | Not affected |
Check if you’re running ksmbd:

On a production kernel (no KASAN), the UAF doesn’t produce clean output. Production kernels will show a generic kernel oops rather than a UAF report. Watch dmesg and journalctl -k for:

These are suspicious when appearing in the context of kworker threads and ksmbd stack frames.
Network-level: The PoC sends dozens of SESSION_FLAG_BINDING requests per minute against the same session ID. Legitimate multichannel usage binds a handful of channels per session and holds them – it does not rapidly cycle bind/logoff. Detect with:


The entire vulnerability in two functions. lookup_chann_list() is two lines with no lock. ksmbd_chann_del() frees the same pointer concurrently. Nothing coordinates them.
Does this affect Samba?
No. Samba (smbd) is a completely separate userspace SMB implementation and is not affected. This vulnerability is specific to ksmbd – the kernel-native server. You can tell which you’re running with ps aux | grep ksmbd.mountd (ksmbd) vs ps aux | grep smbd (Samba).
Is multichannel enabled by default
No. It requires explicitly adding ksmbd: smb3 multichannel = yes to /etc/ksmbd/smb.conf. Most ksmbd deployments don’t have this configured, which means the binding code path – and therefore this vulnerability – is unreachable for them.
The fix is merged – am I safe?
Once your kernel includes commit e4a8a96a93d, yes. The patch is in mainline and submitted for stable backport. Check your distribution’s kernel changelog. If you can’t update yet, disabling multichannel in smb.conf removes the attack vector entirely.
Can an unauthenticated attacker trigger this?
No. Valid SMB credentials are required. SESSION_FLAG_BINDING is only accepted after a primary session has been fully authenticated – the kernel checks sess->state == SMB2_SESSION_VALID before entering the binding path. This limits the attacker pool to users who already have legitimate SMB access.
Why does your CVSS score (7.5) differ from NVD’s (7.8)?
NVD scores this with AV:L (Local attack vector). We assess AV:N (Network) – the attack is triggered entirely by sending SMB3 packets to port 445. No local access is required. With AV:N, the correct score is 7.5. Notably, correcting NVD’s vector lowers the score rather than raising it – this is a technical accuracy dispute. A formal dispute has been filed.
| Date | Event |
|---|---|
| February 8, 2026 | Disclosed to kernel security team by Orca Security Research Pod |
| February 9, 2026 | Patch authored by Namjae Jeon, reviewed and confirmed by Orca Security |
| February 9, 2026 | Greg KH waived embargo – no working PoC at time of disclosure, fix pushed immediately |
| February 16, 2026 | Patch committed to mainline Linux by Greg KH – commit e4a8a96a93d |
| February 18, 2026 | CVE-2026-23226 published |
| March 2026 | PoC developed – required custom multichannel binding client; 5 iterations |
| March 16, 2026 | KASAN confirmation – 8 reliable hits in single run |
| March 17, 2026 | 11 additional hits confirmed, demo video recorded |
| March 2026 | This blog post and PoC published |
e4a8a96a93d)rpc_handle_list XArray) – the chann_lock pattern in this fix mirrors that one directlyCVE-2026-23226 presents a triage challenge that traditional security tools struggle with: exploitability depends on three conditions aligning simultaneously, and verifying them across a large cloud environment without logging into every asset is not feasible. Orca’s agentless SideScanning architecture was built exactly for this scenario.
In a single query, Orca scans your entire cloud environment and surfaces every Linux asset where ksmbd is present and port 445 is internet-exposed – no agents, no credentials, no access to the machines themselves. What would take a security team days of manual work across hundreds of assets takes Orca seconds:

The output is a precise, prioritized list of assets that combine internet exposure on port 445 with ksmbd presence – the two strongest remote indicators that all three exploitability conditions could be met.
The only step that goes beyond what Orca can express in a single query is the exact kernel version range (5.15.145 – 6.19.0), since kernel versions are stored as free-form strings with distro-specific suffixes. A simple post-filter script on the exported results closes that gap in minutes.
From there, Orca’s internet accessibility scoring and lateral movement graph tell you exactly how much each flagged asset matters – which ones are directly reachable from the internet, what sensitive data or downstream systems they connect to, and where to focus remediation effort first. That combination of agentless discovery, precise signal, and business context is what separates a list of potentially vulnerable machines from an actionable remediation plan.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。