From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Namjae Jeon <linkinjeon@kernel.org>,
Steve French <stfrench@microsoft.com>,
Sasha Levin <sashal@kernel.org>,
smfrench@gmail.com, linux-cifs@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18-6.1] ksmbd: start file id allocation at 1
Date: Mon, 31 Aug 2026 09:24:51 -0400 [thread overview]
Message-ID: <20260831133314.4125787-263-sashal@kernel.org> (raw)
In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org>
From: Namjae Jeon <linkinjeon@kernel.org>
[ Upstream commit 6b375be0b4e1be89e9a817880515311503a19114 ]
ksmbd allocates both the volatile id (per-session file table) and the
persistent id (global file table) with idr_alloc_cyclic() starting at 0.
The first open after the module loads therefore gets volatile id 0 and
persistent id 0, and ksmbd returns an SMB2 FileId of {0, 0} in the create
response.
Clients treat an all-zero FileId as a null handle. smbtorture's
smb2_util_handle_empty() considers {0, 0} empty, so tests that guard the
close with it (e.g. smb2.oplock.statopen1, smb2.lease.statopen*) never
close that first handle. The leaked open keeps the inode's oplock count
non-zero, so a later batch oplock request on the same file is downgraded
to level II and the test fails.
Start the id allocation at 1 (KSMBD_START_FID) so no handle is ever
assigned a {0, 0} FileId, matching the behaviour of other SMB servers.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `ksmbd: start file id allocation at 1`
**Local tree:** Linux **6.18.44** (`v6.18.44-1-g2736c32da98b9`,
`VERSION=6`, `PATCHLEVEL=18`, `SUBLEVEL=44`)
**Commit under review:** `6b375be0b4e1be89e9a817880515311503a19114` (not
yet in this tree)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Parse the subject line
**Record:** `[ksmbd]` `[start]` — Change SMB2 file ID allocation so the
first assigned ID is 1 instead of 0.
### Step 1.2: Parse all commit message tags
**Record:**
- **Fixes:** — none
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** — none
- **Acked-by:** — none
- **Link:** — none
- **Cc: stable@vger.kernel.org:** — none (expected for manual review)
- **Signed-off-by:** Namjae Jeon `<linkinjeon@kernel.org>`
(author/maintainer), Steve French `<stfrench@microsoft.com>` (SMB
maintainer)
- No syzbot, no user bug reports, no explicit stable nomination in the
commit message.
### Step 1.3: Analyze commit body
**Record:**
- **Bug:** `idr_alloc_cyclic()` starts at 0 for both volatile (per-
session) and persistent (global) file IDs. The first open after module
load returns SMB2 FileId `{0, 0}`.
- **Symptom:** Clients treat `{0, 0}` as a null handle and skip `CLOSE`.
The server leaks the open; oplock counts stay elevated, breaking batch
oplock behavior.
- **Root cause:** ID allocation starts at 0; `{0, 0}` is semantically a
null handle in the SMB ecosystem.
- **Fix:** Set `KSMBD_START_FID` to 1 and pass it to
`idr_alloc_cyclic()`, matching Samba/Windows behavior.
- **Version info:** None in the message.
### Step 1.4: Detect hidden bug fixes
**Record:** Not disguised as cleanup — this is an explicit protocol-
correctness and resource-management fix. The leak is real: clients that
treat `{0, 0}` as empty never send `CLOSE`, so `__ksmbd_close_fd()` and
`fd_limit_close()` are never called for that handle.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory the changes
**Record:**
- `fs/smb/server/vfs_cache.h`: +6 / -1 (comment + `KSMBD_START_FID` 0 →
1)
- `fs/smb/server/vfs_cache.c`: +2 / -1 (`idr_alloc_cyclic` start `0` →
`KSMBD_START_FID`)
- **Functions modified:** `__open_id()` (indirectly via macro)
- **Scope:** Single-subsystem, 2-file surgical fix (~8 lines net)
### Step 2.2: Code flow change
**Record:**
- **Hunk 1 (`vfs_cache.h`):** `KSMBD_START_FID` was defined as `0` but
unused; now `1` with documentation.
- **Hunk 2 (`vfs_cache.c`):** `idr_alloc_cyclic(ft->idr, fp, 0, ...)` →
`idr_alloc_cyclic(ft->idr, fp, KSMBD_START_FID, ...)`.
- **Before:** First allocated volatile and persistent IDs are 0; CREATE
response is `{PersistentFileId=0, VolatileFileId=0}`.
- **After:** First IDs are 1; CREATE response is never `{0, 0}`.
- **Path affected:** Every file open via `ksmbd_open_fd()` →
`__open_id()` and durable opens via `ksmbd_open_durable_fd()`.
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Resource leak + logic/protocol correctness
- **Mechanism:** Server assigns ID 0 and considers it valid
(`has_file_id(0)` is true). Clients treat `{0, 0}` as null and never
close. Server leaks `ksmbd_file` entries and fd-limit budget; oplock
state becomes incorrect for affected inodes.
### Step 2.4: Fix quality
**Record:** Obviously correct — uses an existing macro name, one-line
behavioral change, matches other SMB servers. Very low regression risk;
no API or locking changes.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame changed lines
**Record:**
- `idr_alloc_cyclic(..., 0, ...)` introduced in `3867369ef8f760`
(2021-07-08, Namjae Jeon): `ksmbd: change data type of
volatile/persistent id to u64`
- `KSMBD_START_FID` defined as `0` since `1a93084b9a898` (2021-06-28):
`ksmbd: move fs/cifsd to fs/ksmbd`
- Bug present since ksmbd inception; long-lived in this tree.
### Step 3.2: Follow Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: File history for related changes
**Record:** Recent `vfs_cache.c` history is active (UAF fixes, durable-
handle races, fd management). No prior fix for ID-0 allocation. Part of
a 29-patch series (`[PATCH 27/29]`), but this patch is standalone — no
dependency on other series commits.
### Step 3.4: Author's other commits
**Record:** Namjae Jeon is the ksmbd maintainer; recent commits in this
tree include multiple UAF and race fixes in the same subsystem. Steve
French committed the merge.
### Step 3.5: Prerequisites
**Record:** No prerequisites. `KSMBD_START_FID` already exists in this
tree; patch applies cleanly with no structural dependencies.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original patch discussion
**Record:**
- `b4 dig -c 6b375be0b4e1b`:
https://patch.msgid.link/20260621124844.6235-27-linkinjeon@kernel.org
- Series: v1, 29 patches, dated 2026-06-21
- Lore page blocked by bot protection; could not read thread replies
- No stable nomination verified from lore
### Step 4.2: Reviewers
**Record:** `b4 dig -w`: CC'd to `linux-cifs@vger.kernel.org`, Steve
French, and other SMB reviewers. Maintainer involvement confirmed.
### Step 4.3: Bug report search
**Record:** No external bug report. Evidence is smbtorture failure
(`smb2.oplock.statopen1`, `smb2.lease.statopen*`) and maintainer
knowledge of client behavior.
### Step 4.4: Related patches
**Record:** Patch 27/29 in a larger ksmbd series; this change is
independent.
### Step 4.5: Stable mailing list
**Record:** Not searched (lore blocked); no stable discussion found.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `__open_id()`, `ksmbd_open_fd()`, `ksmbd_open_durable_fd()`,
`has_file_id()`
### Step 5.2: Callers
**Record:**
- `__open_id()` called from `ksmbd_open_fd()` (normal opens) and
`ksmbd_open_durable_fd()` (persistent IDs)
- `ksmbd_open_fd()` is on the hot SMB2 CREATE path for every file open
- Reachable from userspace over the network (SMB client CREATE)
### Step 5.3: Callees
**Record:** `idr_alloc_cyclic()`, `idr_preload()`,
`fd_limit_depleted()`, `__open_id_set()`, `write_lock/unlock`
### Step 5.4: Call chain / reachability
**Record:** SMB client CREATE → `ksmbd_open_fd()` → `__open_id()` → ID 0
on first open after module load. **Userspace-reachable** via SMB
protocol; triggers on every server's first file open after (re)start.
### Step 5.5: Similar patterns
**Record:** `has_file_id()` treats `0` as valid (`id < KSMBD_NO_FID`),
but SMB clients treat `{0, 0}` as null — server/client semantic
mismatch. No other instances of this pattern found in ksmbd.
---
## PHASE 6: CROSS-REFERENCING AGAINST LOCAL TREE
### Step 6.1: Does buggy code exist?
**Record:** **YES.** In this 6.18.44 tree:
- `KSMBD_START_FID` is `0` in `fs/smb/server/vfs_cache.h:26`
- `idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT)` at
`vfs_cache.c:676`
- Fix commit `6b375be0b4e1b` is **not** an ancestor of HEAD
### Step 6.2: Backport complications
**Record:** Clean apply expected — identical code structure, macro
already present. No conflicts anticipated.
### Step 6.3: Related fixes already present?
**Record:** No duplicate fix found. `git log --grep="start file id"`
returns nothing in this tree.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `fs/smb/server/` (ksmbd, `CONFIG_SMB_SERVER`) —
**IMPORTANT** for deployments using the in-kernel SMB server; not core
kernel, but file-serving correctness matters for those users.
### Step 7.2: Subsystem activity
**Record:** Highly active — 239 ksmbd commits since 2025-01-01 in this
tree; ongoing maintenance and bug fixes.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users with `CONFIG_SMB_SERVER` (ksmbd) enabled. Every
deployment hits this on the first file open after module load or server
restart.
### Step 8.2: Trigger conditions
**Record:**
- **When:** First SMB2 CREATE after ksmbd module load/restart (per
session for volatile ID; globally for persistent ID)
- **Likelihood:** Certain on every restart
- **Privilege:** Any SMB client with access to a share
### Step 8.3: Failure mode severity
**Record:**
- Leaked `ksmbd_file` entry (never closed by client)
- `fd_limit` counter permanently decremented (`fd_limit_depleted()` on
open, no matching `fd_limit_close()` on client-driven close) — can
eventually cause `-EMFILE` for new opens
- Incorrect oplock state (elevated oplock count blocks proper batch
oplocks)
- **Severity: MEDIUM-HIGH** for ksmbd users — not a kernel oops, but a
real resource leak with functional impact on a common path
### Step 8.4: Risk-benefit ratio
**Record:**
- **Benefit:** Fixes protocol non-compliance and per-restart resource
leak affecting all ksmbd deployments; aligns with Samba/Windows
- **Risk:** Very low — 8-line constant change, no new APIs, no locking
changes
- **Ratio:** Strong benefit, minimal risk for `CONFIG_SMB_SERVER` users
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence compiled
**FOR backport:**
- Real bug: resource leak + broken oplock semantics on first open after
restart
- Affects every ksmbd deployment on a common path
- Tiny, obviously correct fix from subsystem maintainers
- Bug present since ksmbd was added (~2021)
- Buggy code confirmed in this 6.18.44 tree; fix not yet applied
- Clean backport with no dependencies
- Progressive fd-limit depletion from leaked handles
**AGAINST backport:**
- No user bug reports — discovered via smbtorture
- Not a crash, UAF, security issue, or data corruption
- `CONFIG_SMB_SERVER` is optional; smaller user base than core
subsystems
- Lore review thread not accessible for stable nomination confirmation
**Unresolved:**
- Could not verify lore review comments (bot protection)
- No independent confirmation that Windows clients skip CLOSE for `{0,
0}` beyond maintainer statement and smbtorture behavior
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — trivial constant change;
maintainer-signed; part of tested series
2. Fixes a real bug? **PASS** — handle leak and oplock breakage
3. Important issue? **PASS** — resource leak on common path with
functional impact (oplocks, fd limits); not crash-level but
materially affects file-server operation
4. Small and contained? **PASS** — 8 lines, 2 files
5. No new features or APIs? **PASS** — behavior correction only
6. Can apply to local tree? **PASS** — clean apply, no prerequisites
### Step 9.3: Exception categories
**Record:** None (not a device ID, quirk, DT, build, or docs fix).
Qualifies on merit as a protocol/resource-management bug fix.
### Step 9.4: Decision rationale
For this **6.18.y** tree, ksmbd is present and the buggy code is live.
Every server restart leaks the first opened handle from compliant SMB
clients, permanently consumes fd-limit budget, and corrupts oplock
state. The fix is minimal, maintainer-authored, and matches established
SMB server practice. The issue is below crash/security severity but
clearly meets stable criteria as a real, user-visible resource leak on a
guaranteed code path.
---
## Verification
- **[Phase 1]** Parsed commit `6b375be0b4e1b`: only Signed-off-by tags;
no Fixes/Reported-by/Link/Cc: stable
- **[Phase 2]** Diff: 2 files, ~8 lines; `KSMBD_START_FID` 0→1;
`idr_alloc_cyclic` start 0→`KSMBD_START_FID`
- **[Phase 3]** `git describe HEAD`: v6.18.44; `git blame` line 676:
`idr_alloc_cyclic` with start 0 since 2021
- **[Phase 3]** `git merge-base --is-ancestor 6b375be0b4e1b HEAD`: exit
1 — fix NOT in tree
- **[Phase 3]** `git log -S KSMBD_START_FID`: macro introduced
2021-06-28
- **[Phase 4]** `b4 dig -c 6b375be0b4e1b`: lore URL found; patch 27/29
in v1 series
- **[Phase 4]** `b4 dig -w`: maintainers CC'd (linux-cifs, smfrench)
- **[Phase 4]** UNVERIFIED: Lore thread content (bot protection on
patch.msgid.link)
- **[Phase 5]** `grep has_file_id`: `has_file_id(0)` returns true (`id <
KSMBD_NO_FID`); CREATE sets `rsp->PersistentFileId`/`VolatileFileId`
from fp IDs at `smb2pdu.c:3649-3650`
- **[Phase 5]** `fd_limit_depleted()`/`fd_limit_close()` at
`vfs_cache.c:48-61`: leaked handle prevents limit restoration
- **[Phase 6]** `grep KSMBD_START_FID`: only in header, value 0;
`idr_alloc_cyclic` uses literal 0 at line 676
- **[Phase 6]** `CONFIG_SMB_SERVER` in `fs/smb/server/Kconfig`
- **[Phase 7]** 239 ksmbd commits since 2025-01-01 in this tree
- **[Phase 8]** Failure mode: resource leak + oplock corruption + fd-
limit depletion; severity MEDIUM-HIGH for ksmbd users
**YES**The background search finished: the fix is commit `6b375be0b4e1b`
on master (merged via the v7.2 SMB3 server fixes tag). It is not in this
6.18.44 tree yet.
That matches the earlier analysis: the buggy `{0, 0}` FileId allocation
is still present here, and the fix is a small, low-risk protocol
correction that stops handle leaks and oplock issues on the first open
after ksmbd starts.
**YES**
fs/smb/server/vfs_cache.c | 3 ++-
fs/smb/server/vfs_cache.h | 7 ++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index aee974a264d51..7b8d3b5ad1c2d 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -698,7 +698,8 @@ static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
idr_preload(KSMBD_DEFAULT_GFP);
write_lock(&ft->lock);
- ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT);
+ ret = idr_alloc_cyclic(ft->idr, fp, KSMBD_START_FID, INT_MAX - 1,
+ GFP_NOWAIT);
if (ret >= 0) {
id = ret;
ret = 0;
diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h
index ad7a487a21bb0..955bbf11f1926 100644
--- a/fs/smb/server/vfs_cache.h
+++ b/fs/smb/server/vfs_cache.h
@@ -23,7 +23,12 @@
#define FILE_GENERIC_WRITE 0x120116
#define FILE_GENERIC_EXECUTE 0X1200a0
-#define KSMBD_START_FID 0
+/*
+ * Start volatile/persistent file id allocation at 1. A file id of 0 yields an
+ * SMB2 FileId of {0, 0}, which clients (e.g. Windows, Samba) treat as a null
+ * handle and never close, leaking the open on the server.
+ */
+#define KSMBD_START_FID 1
#define KSMBD_NO_FID (INT_MAX)
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
--
2.53.0
next prev parent reply other threads:[~2026-08-31 13:41 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:20 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: preserve VFS inherited POSIX ACL mask Sasha Levin
2026-08-31 13:20 ` [PATCH AUTOSEL 6.18-6.1] ksmbd: fix outstanding credit leak on abort and error paths Sasha Levin
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.12] cifs: Fix support for creating SFU fifo Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: find bound sessions during reauthentication Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18] ksmbd: propagate failed command status in related compounds Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: treat read-control opens as stat opens only for leases Sasha Levin
2026-08-31 13:23 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: mark invalid session responses as signed Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: Fix acl.sd_buf memory leak and invalid sd_size error handling Sasha Levin
2026-08-31 13:24 ` Sasha Levin [this message]
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-6.1] smb/client: reduce fallocate zero buffer allocation Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18-6.12] cifs: Fix support for creating SFU socket Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: apply create security descriptor first Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-6.1] smb: client: bound dirent name against end of SMB response in cifs_filldir Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-5.10] cifs: validate idmap key payload length Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: validate SMB2 lease create contexts Sasha Levin
2026-08-31 13:26 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: fix credit charge calculation for SMB2 QUERY_INFO Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: validate SID namespace before mapping IDs Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-6.12] smb/client: zero-initialize stack-allocated cifs_open_info_data Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: break RH leases before delete-on-close Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18] smb/client: emulate small EOF-extending mode 0 fallocate ranges Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] smb/client: do not account EOF extension as allocation Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18-6.6] smb/client: flush dirty data before punching a hole Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.6] smb: client: fix races in cifsd thread creation Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: fix lease break and ack state handling Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: fix n.data memory leak in ksmbd_vfs_set_dos_attrib_xattr Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-6.1] ksmbd: align SMB2 oplock break ack handling Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-6.6] ksmbd: deny renaming directory with open children Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-5.15] ksmbd: treat unnamed DATA stream as base file Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831133314.4125787-263-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=smfrench@gmail.com \
--cc=stable@vger.kernel.org \
--cc=stfrench@microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox