Re: [BUG] Linux Kernel CIFS Client SMB2_open_free KFENCE Double-Free

From: Steve French

Date: Fri Apr 03 2026 - 18:08:19 EST


This doesn't make sense - the suggested solution is:

Alternatively, add `memset(open_iov, 0, sizeof(open_iov))` at the
`again` label in `smb2_unlink()`.

But it is already there. Am I missing something? This doesn't look
real. See line 1219 inside smb2_unlink() function in smb2inode.c

1211 again:
1212 oplock = SMB2_OPLOCK_LEVEL_NONE;
1213 server = cifs_pick_channel(tcon->ses);
1214
1215 memset(rqst, 0, sizeof(rqst));
1216 memset(resp_buftype, 0, sizeof(resp_buftype));
1217 memset(rsp_iov, 0, sizeof(rsp_iov));
1218
1219 memset(open_iov, 0, sizeof(open_iov));

On Thu, Apr 2, 2026 at 6:14 AM ven0mfuzzer <ven0mkernelfuzzer@xxxxxxxxx> wrote:
>
> Linux Kernel CIFS Client SMB2_open_free KFENCE Double-Free
>
> 1. Vulnerability Title
>
> Linux Kernel CIFS Client SMB2 Compound Request KFENCE-Confirmed Double-Free Vulnerability (ksmbd)
>
> 2. High-Level Overview
>
> This report describes the same double-free vulnerability in the Linux kernel CIFS client as crash_001 (KASAN detection), now independently confirmed by KFENCE (Kernel Electric-Fence). When the CIFS client sends a compound `CREATE + CLOSE` request (e.g., via `smb2_unlink()`), a malicious server or MITM can return `STATUS_IO_TIMEOUT` in the CREATE response, causing a retry loop. On the error-path of the retry, `SMB2_open_free()` is called a second time on an already-freed `cifs_small_rq` mempool object (448 bytes), producing a double-free.
>
> The KFENCE detection provides additional forensic detail over the KASAN report in crash_001: precise timestamps, exact object lifetime (27.5 seconds), exact slab cache name (`cifs_small_rq`), and confirmation that both frees are issued by the same task — ruling out any race condition. This is a deterministic, single-threaded double-free.
>
> This vulnerability was discovered using ven0mfuzzer, our custom-designed MITM-based network filesystem fuzzer developed by our team. Following the common syzkaller practice, we submit the kernel crash trace as the primary reproduction artifact.
>
> 3. Affected Product and Version Information
>
> Product: Linux Kernel (upstream mainline)
> Affected Component: `fs/smb/client/smb2inode.c` — `smb2_unlink()` (line 1186)
> Supporting Components:
> - `fs/smb/client/smb2pdu.c` — `SMB2_open_free()` does not null freed pointer (line 3244)
>
> Tested Versions (confirmed vulnerable)
> - Linux kernel 6.19.0 (mainline, commit `44331bd6a610`, gcc 11.4.0, built 2026-02-13)
> - Linux kernel 6.12.74 (LTS, used in Google kernelCTF COS target)
>
> Affected Version Range
> All kernels from approximately 6.0 through 6.19 (current mainline at time of report) with SMB2 compound replay support are believed affected.
>
> Affected Distributions and Products
>
> | Vendor / Product | Notes |
> | --- | --- |
> | Red Hat Enterprise Linux (RHEL 9.x) | Ships kernels >= 5.14 with backported SMB2 compound replay |
> | Ubuntu (22.04 LTS, 24.04 LTS) | HWE kernels 6.x include vulnerable code |
> | SUSE Linux Enterprise Server (SLES 15 SP5+) | Kernel 6.x based |
> | Debian (Bookworm, Trixie) | Kernels 6.1+ |
> | Fedora (39+) | Kernels 6.5+ |
> | Amazon Linux 2023 | Kernel 6.1 LTS based |
> | Google ChromeOS / COS | kernelCTF target, confirmed vulnerable on 6.12.74 |
>
> 4. Root Cause Analysis
>
> 4.a. Detailed Description
>
> This is the same root cause as crash_001: `smb2_unlink()` calls `SMB2_open_free()` twice on the same stack-local `open_iov` array pointer. The first free occurs during normal cleanup after `compound_send_recv()` returns `-EAGAIN` (due to `STATUS_IO_TIMEOUT`). The retry loop (`goto again`) reuses the same `open_iov` array without clearing it. If `SMB2_open_init()` fails on the second iteration (due to reconnect state), the `err_free` label calls `SMB2_open_free()` again on the stale pointer.
>
> The KFENCE report captures all three critical events:
>
> 1. Allocation at `smb2_unlink+0x470` — `SMB2_open_init` allocates the CREATE request buffer
> 2. First free at `smb2_unlink+0x5db` — normal cleanup after `compound_send_recv` (line 1263)
> 3. Invalid second free at `smb2_unlink+0x81c` — `err_free` label (line 1289)
>
> 4.b. Code Flow
>
> ---
> smb2_unlink() [fs/smb/client/smb2inode.c:1186]
> again:
> SMB2_open_init() ← allocates cifs_small_rq object (448B)
> compound_send_recv() ← server returns STATUS_IO_TIMEOUT → -EAGAIN
> SMB2_open_free(&rqst[0]) ← FIRST FREE (line 1263), does NOT null open_iov[0]
> goto again
> again:
> memset(rqst, 0, ...) ← clears rqst[] but NOT open_iov[] (stale pointer!)
> SMB2_open_init() ← fails (connection being reconnected) → rc != 0
> goto err_free
> err_free:
> SMB2_open_free(&rqst[0]) ← SECOND FREE of already-freed buffer!
> ---
>
> 4.c. KFENCE Crash Trace
>
> This vulnerability was discovered by ven0mfuzzer. The following kernel trace is submitted following syzkaller's common practice of providing the raw crash trace as the primary reproduction evidence:
>
> ---
> : VFS: Signing Key d8 d6 c0 c2 b7 56 41 83 e9 d7 b5 fd 2c df 47 62
> [ 1087.254230] CIFS: VFS: ServerIn Key 5b 78 90 2a f0 90 67 84 da 43 e8 f1 a8 43 eb 91
> [ 1087.254673] CIFS: VFS: ServerOut Key 93 3a 5d ae db 4a 4b fb 24 4b c5 b8 f9 e3 47 29
> [ 1087.258673] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -22
> [ 1087.259195] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1087.259715] ==================================================================
> [ 1087.260125] BUG: KFENCE: invalid free in mempool_free+0xde/0x130
> [ 1087.260125]
> [ 1087.260556] Invalid free of 0xffff8881f5cc4e40 (in kfence-#97):
> [ 1087.260893] mempool_free+0xde/0x130
> [ 1087.261124] cifs_small_buf_release+0x41/0x70
> [ 1087.261392] SMB2_open_free+0x78/0x1b0
> [ 1087.261631] smb2_unlink+0x81c/0x8d0
> [ 1087.261870] __cifs_unlink+0x830/0x1890
> [ 1087.262134] vfs_unlink+0x2f0/0xbd0
> [ 1087.262369] filename_unlinkat+0x345/0x6d0
> [ 1087.262628] __x64_sys_unlinkat+0xc4/0x130
> [ 1087.262886] do_syscall_64+0x111/0x690
> [ 1087.263125] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 1087.263427]
> [ 1087.263531] kfence-#97: 0xffff8881f5cc4e40-0xffff8881f5cc4fff, size=448, cache=cifs_small_rq
> [ 1087.263531]
> [ 1087.264219] allocated by task 1881 on cpu 0 at 1059.756104s (27.508113s ago):
> [ 1087.264648] mempool_alloc_noprof+0x18a/0x2c0
> [ 1087.264919] cifs_small_buf_get+0x36/0x80
> [ 1087.265210] __smb2_plain_req_init+0x4b/0x1140
> [ 1087.265487] SMB2_open_init+0x1ae/0x37f0
> [ 1087.265735] smb2_unlink+0x470/0x8d0
> [ 1087.265974] __cifs_unlink+0x830/0x1890
> [ 1087.266226] vfs_unlink+0x2f0/0xbd0
> [ 1087.266460] filename_unlinkat+0x345/0x6d0
> [ 1087.266717] __x64_sys_unlinkat+0xc4/0x130
> [ 1087.266975] do_syscall_64+0x111/0x690
> [ 1087.267214] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 1087.267514]
> [ 1087.267618] freed by task 1881 on cpu 0 at 1087.241106s (0.026511s ago):
> [ 1087.268109] mempool_free+0xde/0x130
> [ 1087.268352] cifs_small_buf_release+0x41/0x70
> [ 1087.268620] SMB2_open_free+0x78/0x1b0
> [ 1087.268858] smb2_unlink+0x5db/0x8d0
> [ 1087.269091] __cifs_unlink+0x830/0x1890
> [ 1087.269293] vfs_unlink+0x2f0/0xbd0
> [ 1087.269481] filename_unlinkat+0x345/0x6d0
> [ 1087.269687] __x64_sys_unlinkat+0xc4/0x130
> [ 1087.269895] do_syscall_64+0x111/0x690
> [ 1087.270086] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 1087.270327]
> [ 1087.270417] CPU: 0 UID: 0 PID: 1881 Comm: rm Tainted: G B 6.19.0-g44331bd6a610-dirty #5 PREEMPT(lazy)
> [ 1087.270900] Tainted: [B]=BAD_PAGE
> [ 1087.271061] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
> [ 1087.271561] ==================================================================
> [ 1087.723901] CIFS: VFS: \\10.0.0.2 RFC 1002 unknown response type 0x8
> [ 1087.739764] CIFS: VFS: \\10.0.0.2\IPC$ validate protocol negotiate failed: -11
> [ 1087.740391] CIFS: VFS: \\10.0.0.2\IPC$ reconnect tcon failed rc = -5
> [ 1087.746271] CIFS: VFS: generate_smb3signingkey: dumping generated AES session keys
> [ 1087.746842] CIFS: VFS: Session Id 02 00 00 00 00 00 00 00
> [ 1087.747238] CIFS: VFS: Cipher type 1
> [ 1087.747464] CIFS: VFS: Session Key 71 85 72 ad 7c b4 da e7 cf dc c0 ae 3a 07 98 19
> [ 1087.747888] CIFS: VFS: Signing Key 88 3f d1 03 8b 13 17 97 88 be 52 23 9b 8d a9 ed
> [ 1087.748463] CIFS: VFS: ServerIn Key 0e 28 bd af 95 9d 5d e4 34 0a d5 de a6 9a 74 0d
> [ 1087.749077] CIFS: VFS: ServerOut Key ba a1 76 7c c0 b9 32 db 27 09 85 1a e7 7d cf 65
> [ 1087.754602] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -13
> [ 1087.755289] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1087.758970] CIFS: VFS: smb2_get_data_area_len: invalid data area (off=10608 len=24)
> [ 1087.759770] CIFS: VFS: \\10.0.0.2\fuzzshare Malformed ioctl resp: len 24 offset 10608
> [ 1087.760271] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -5
> [ 1087.760742] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1087.764494] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -22
> [ 1087.765178] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1088.197368] CIFS: VFS: Bad protocol string signature header 420053fe
> [ 1088.198145] CIFS: VFS: Bad SMB detected. The Mid=16
> [ 1088.198652] 00000000: 420053fe 00010040 00000000 000a0005 .S.B@...........
> [ 1088.199364] 00000010: 00000001 00000000 00000010 00000000 ................
> [ 1088.200070] 00000020: 00000776 00000004 00000002 00000002 v...............
> [ 1088.459625] CIFS: VFS: \\10.0.0.2 RFC 1002 unknown response type 0x42
> [ 1089.503269] CIFS: VFS: generate_smb3signingkey: dumping generated AES session keys
> [ 1089.503705] CIFS: VFS: Session Id 02 00 00 00 00 00 00 00
> [ 1089.504013] CIFS: VFS: Cipher type 1
> [ 1089.504229] CIFS: VFS: Session Key d6 56 c8 0b 7a 8f 2c 81 4a 9a 16 b8 ef a6 df 50
> [ 1089.504575] CIFS: VFS: Signing Key b6 36 17 ad 2f 1d d5 d6 21 0a 98 37 50 9a 31 08
> [ 1089.504914] CIFS: VFS: ServerIn Key b6 c4 17 a9 16 ed 60 72 14 1b 64 6b d5 20 5f f2
> [ 1089.505485] CIFS: VFS: ServerOut Key e1 8c 7f af 9e 04 ed 2c 67 47 63 68 e4 eb 9e 2b
> [ 1089.718373] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -22
> [ 1089.719252] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1090.142104] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -5
> [ 1090.142986] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1090.353639] CIFS: VFS: \\10.0.0.2\fuzzshare validate protocol negotiate failed: -22
> [ 1090.354254] CIFS: VFS: \\10.0.0.2\fuzzshare reconnect tcon failed rc = -5
> [ 1091.057267] CIFS: VFS: \\10.0.0.2\IPC$ validate protocol negotiate failed: -22
> [ 1091.058141] CIFS: VFS: \\10.0.0.2\IPC$ reconnect tcon failed rc = -5
>
> ---
>
> Key forensic facts from KFENCE:
> - Object size: 448 bytes, cache `cifs_small_rq`
> - Object lifetime: 27.5 seconds (alloc at 1059.756s, first free at 1087.241s)
> - Time between frees: 0.027 seconds (deterministic, single-threaded)
> - Both frees from same task (PID 1881, `rm`) — no race condition involved
>
> 4.d. Relationship to crash_001
>
> crash_001 detected the same double-free via KASAN. This KFENCE detection (crash_008) is an independent confirmation of the same root cause with additional forensic data. Together they provide overwhelming evidence that the bug is real, deterministic, and affecting both KASAN and KFENCE instrumentation paths.
>
> 4.e. Suggested Fix
>
> Null out the pointer in `SMB2_open_free()` after releasing the buffer:
>
> ---
> void SMB2_open_free(struct smb_rqst *rqst)
> {
> int i;
> if (rqst && rqst->rq_iov) {
> cifs_small_buf_release(rqst->rq_iov[0].iov_base);
> + rqst->rq_iov[0].iov_base = NULL;
> for (i = 1; i < rqst->rq_nvec; i++)
> if (rqst->rq_iov[i].iov_base != smb2_padding)
> kfree(rqst->rq_iov[i].iov_base);
> + rqst->rq_nvec = 0;
> }
> }
> ---
>
> Alternatively, add `memset(open_iov, 0, sizeof(open_iov))` at the `again` label in `smb2_unlink()`.
>
> 5. Discovery Method and Reproduction
>
> 5.a. Discovery
>
> This vulnerability was discovered using ven0mfuzzer, a custom-designed MITM-based network filesystem fuzzer developed by our team. The fuzzer operates by positioning an AF_PACKET/TCP transparent proxy between a Linux kernel filesystem client (VM-A) and its server (VM-B), then mutating network protocol messages in-flight. We designed ven0mfuzzer specifically for this class of network filesystem vulnerabilities.
>
> Following the common syzkaller practice, we submit the kernel crash trace as the primary reproduction artifact. The trace above was captured with KFENCE enabled on kernel 6.19.0.
>
> 5.b. Reproduction Setup
>
> ---
> VM-A (CIFS client) ──SMB2──► Host:44446 (MITM proxy) ──TCP──► Host:44445 ──hostfwd──► VM-B:445 (ksmbd)
> ---
>
> Trigger condition: Any `unlink` operation on a CIFS mount while the MITM injects `STATUS_IO_TIMEOUT` (`0xC00000B5`) in CREATE responses followed by a forced reconnect.
>
> ---
> Reported-by: ven0mfuzzer <ven0mkernelfuzzer@xxxxxxxxx>
> Link: https://github.com/KernelStackFuzz/KernelStackFuzz
>


--
Thanks,

Steve