summaryrefslogtreecommitdiff
path: root/fs
AgeCommit message (Collapse)AuthorFilesLines
2026-08-17NFS/localio: remove dead FLUSH_SYNC handling from nfs_local_commitMike Snitzer3-16/+5
nfs_local_commit() is reached only through nfs_initiate_commit(), and every path that supplies its "how" argument has already cleared FLUSH_SYNC: __nfs_commit_inode() strips it (how &= ~FLUSH_SYNC) before dispatch and does its own waiting via wait_on_commit(), while the O_DIRECT path passes how=0. filelayout issues its DS commit with a NULL localio, so it never enters nfs_local_commit() at all. The FLUSH_SYNC branch has therefore been dead since it was introduced with commit 70ba381e1a43 ("nfs: add LOCALIO support"). Remove the never-taken FLUSH_SYNC branch along with the completion plumbing it was the sole user of: the struct nfs_local_fsync_ctx::done member, its initialization, and the complete() call in nfs_local_fsync_work(). With the branch gone the "how" parameter is unused, so drop it from nfs_local_commit() and its callers. No functional change. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS/localio: issue IO inline when not in a memory-reclaim contextMike Snitzer1-2/+31
Every LOCALIO read and write is currently bounced through the dedicated !WQ_MEM_RECLAIM nfslocaliod_workqueue. That bounce is only actually required when the submitting context is a memory-reclaim context: LOCALIO issues IO directly into a stacked local filesystem (e.g. XFS) which may in turn flush its own !WQ_MEM_RECLAIM workqueue. Doing that from a WQ_MEM_RECLAIM worker (most importantly writeback's wb_workfn on bdi_wq) or an explicit PF_MEMALLOC reclaim task trips check_flush_dependency() and risks a forward-progress deadlock, which is why commit b9f5dd57f4a5 ("nfs/localio: use dedicated workqueues for filesystem read and write") introduced the intermediate workqueue. Outside of reclaim context -- ordinary application/task submission such as O_DIRECT or fsync-driven writeback -- the workqueue hop buys nothing and merely adds a context switch and scheduling latency per IO while discarding the NFS client's inherent application-context parallelism. Add current_is_workqueue_mem_reclaim(), which reports whether %current is a WQ_MEM_RECLAIM worker using the same predicate check_flush_dependency() warns on. Use it, together with the PF_MEMALLOC check, in the new nfs_local_defer_io() helper to decide per-IO whether nfs_local_do_read() and nfs_local_do_write() must defer to nfslocaliod_workqueue or may issue the IO inline. Buffered writeback continues to bounce (wb_workfn is a WQ_MEM_RECLAIM worker); O_DIRECT and app-context submission now run inline. Running nfs_local_call_write() inline is safe: it already saves and restores current->flags around the PF_LOCAL_THROTTLE|PF_MEMALLOC_NOIO it sets and scopes the file opener's creds. The async O_DIRECT completion path is likewise unaffected: when the underlying filesystem returns -EIOCBQUEUED, the kiocb ki_complete callback (nfs_local_read_aio_complete / nfs_local_write_aio_complete) can run in bottom-half context and so must still defer the pgio completion (nfs_local_pgio_release -> rpc_call_done) to nfsiod_workqueue via nfs_local_pgio_aio_complete(). That completion hop is independent of how the IO was submitted, and this change leaves it as-is; only the submission side stops unconditionally hopping through nfslocaliod_workqueue. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS: Fix delayed delegation return list handlingGuangshuo Li1-1/+1
The delayed delegation return handling added a separate delegations_delayed list to keep delegations whose return needs to be retried later. The delayed list is then spliced back to delegations_return by nfs_server_clear_delayed_delegations(), which also causes the state manager to retry the delegation return. However, nfs_end_delegation_return() still moves delayed delegations to delegations_return instead of delegations_delayed. As a result, the new delayed list is never populated, nfs_server_clear_delayed_delegations() always returns false, and NFS4CLNT_DELEGRETURN is not set again to drive a retry. Move delayed delegations to delegations_delayed so that the delayed return path can splice them back to delegations_return and schedule the retry as intended. Fixes: 4039fbedcbcb ("NFS: fix delayed delegation return handling") Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS: Verify symlink inode before caching targetZhangGuoDong1-0/+6
nfs_symlink() copies the symlink target into a folio before issuing the SYMLINK RPC. After a successful reply, it caches that folio in the instantiated inode mapping and assumes that the dentry now names a symlink. If the dentry is instantiated with a non-symlink inode, the raw symlink target folio can be inserted into the wrong mapping. When that inode is a directory, reclaim or unmount later calls nfs_readdir_clear_array() through nfs_dir_aops and interprets the symlink target as a readdir cache array, which can lead to invalid kfree() calls. A vmcore from a 4.19-based kernel showed the crash when reclaiming a directory mapping on unmount: Stack trace: nfs_readdir_clear_array+0x4d/0x70 [nfs] page_cache_free_page.isra.35+0x1a/0x90 delete_from_page_cache_batch+0x1cf/0x2c0 truncate_inode_pages_range+0x24d/0x910 [...] nfs_evict_inode+0x15/0x30 [nfs] evict+0x115/0x2b0 dispose_list+0x48/0x60 evict_inodes+0x16c/0x1b0 generic_shutdown_super+0x3f/0x120 nfs_kill_super+0x1b/0x40 [nfs] deactivate_locked_super+0x3f/0x70 cleanup_mnt+0x3b/0x80 The current code still has the same unchecked cache insertion pattern, so it may be susceptible to the same failure mode. Verify that the instantiated inode is a symlink before caching the target folio. If the type is wrong, drop the suspect dentry and skip the cache insertion while preserving the successful SYMLINK result. Co-developed-by: Jackie Liu <liuyun01@kylinos.cn> Signed-off-by: Jackie Liu <liuyun01@kylinos.cn> Signed-off-by: ZhangGuoDong <zhangguodong@kylinos.cn> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFS: fix folio dereference before NULL check in nfs_inode_remove_request()Jiangshan Yi1-5/+6
nfs_inode_remove_request() obtains the folio for the head request via nfs_page_to_folio(), which returns NULL when the PG_FOLIO flag is not set on req->wb_head. The presence of the "if (likely(folio))" check shows the code already assumes folio can be NULL. However, folio was dereferenced before that check: folio = nfs_page_to_folio(req->wb_head); mapping = folio->mapping; /* deref */ spin_lock(&mapping->i_private_lock); if (likely(folio)) { /* too late */ folio->mapping is read (and mapping->i_private_lock is taken, and folio_end_dropbehind(folio) is called outside the check) before folio is validated, so a NULL folio would crash before the guard is ever reached, rendering the check useless. Move the folio->mapping read, the i_private_lock section and the folio_end_dropbehind() call inside the "if (likely(folio))" block so the folio is only dereferenced after it has been confirmed non-NULL. The behaviour is unchanged when folio is non-NULL. Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17nfs4.2: open UNCACHEABLE_FILE_DATA files with O_DIRECTMike Snitzer3-0/+16
Honor the per-file UNCACHEABLE_FILE_DATA attribute by transparently opening such regular files with O_DIRECT, so reads and writes bypass the page cache as the attribute requires, without the application having to request O_DIRECT itself. This follows the model the specification describes: the attribute is "similar in intent to O_DIRECT" and clients "retain flexibility in how they satisfy the requirements" (draft-ietf-nfsv4-uncacheable-files Section 4.4, "Relationship to Direct I/O"), and its Implementation Status (Section 6) describes a prototype Linux client that "treats the attribute as an indication to use O_DIRECT-like behavior for file access". Introduce an NFS_CONTEXT_O_DIRECT open-context flag: nfs4_atomic_open() sets it when the resolved inode has uncacheable_file_data set (and the open is not O_APPEND), and the open paths nfs_atomic_open() and nfs4_file_open() apply O_DIRECT to the file when the flag is set. The I/O mode is thus selected at open time and is not changed for an already-open file: a later change to the attribute takes effect on the next open. The specification permits this -- a client that has already opened a file MAY continue with its existing caching behavior and apply the updated attribute to subsequent operations (Section 5). The delegation interaction in Section 4.3 was considered: it permits read caching to remain when another NFSv4.2 mechanism, such as a delegation, already ensures a consistent view of the file. That relaxation is optional ("may remain appropriate") and read-only -- it does not relax write-behind suppression (Section 4.1) or the WRITE durability invariant (Section 4.2). This implementation deliberately does not take it: an uncacheable file is opened O_DIRECT regardless of any delegation held, which is compliant (read caching is simply suppressed more aggressively than the Section 4.3 minimum) and avoids decoupling read vs write caching behind a single open flag. Relaxing reads under a delegation is left as a possible future optimization. Section 6 observes the benefit holds "for applications that issue well-formed I/O requests". That alignment caveat does not constrain the Linux NFS client's over-the-wire path: the client readily issues misaligned I/O using O_DIRECT over SunRPC to the remote NFS server. The only place a fallback from O_DIRECT to buffered I/O for misaligned I/O applies is NFS LOCALIO (fs/nfs/localio.c), which detects non-DIO-aligned I/O and falls back internally; that path is unaffected by this change. Link: https://datatracker.ietf.org/doc/draft-ietf-nfsv4-uncacheable-files/ Signed-off-by: Mike Snitzer <snitzer@kernel.org> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17nfs4.2: request UNCACHEABLE_FILE_DATA only for regular filesMike Snitzer2-7/+45
The UNCACHEABLE_FILE_DATA attribute applies only to regular files (NF4REG); per draft-ietf-nfsv4-uncacheable-files a server MUST reject a query of it on any other object type with NFS4ERR_INVAL. The previous commit decodes and tracks the attribute but does not gate it: the bit rides in the per-server attribute bitmask (server->attr_bitmask) and in the generic getattr request bitmap (nfs4_fattr_bitmap), so it would be requested for non-regular objects too -- e.g. a plain directory GETATTR, a LOOKUP that resolves to a directory, or a CREATE (which only ever makes non-regular objects). A strict server would fail those compounds. Gate the client accordingly: - Only set NFS_INO_INVALID_UNCACHEABLE_FILE_DATA on regular-file inodes. In particular, drop it from nfs4_update_changeattr_locked()'s force-revalidation aggregation: that helper only ever runs on directory inodes (its callers update a directory's change information after OPEN-create, REMOVE, RENAME and LINK), so it was setting the file-only bit on directories. - Gate the request by object type at the choke point nfs4_bitmap_copy_adjust(), which clears FATTR4_WORD2_UNCACHEABLE_FILE_DATA unless the target inode is a regular file (a NULL inode -- unknown object type -- clears it too). This already covers GETATTR, SETATTR and LINK; route LOOKUP, LOOKUPP and CREATE through it as well. - Type-gate nfs4_bitmask_set(), which translates NFS_INO_INVALID_UNCACHEABLE_FILE_DATA into a request for attr 87 in the getattr attached to WRITE, CLOSE and DELEGRETURN. WRITE and CLOSE only ever pass regular files, but DELEGRETURN passes whatever object held the delegation -- with directory delegation support that includes directories -- so request attr 87 there only for S_ISREG inodes. The bit is kept in server->attr_bitmask (it is server-supported, and OPEN still requests it via its regular-file-only open_bitmap), so no bespoke per-data-file bitmask plumbing is needed. The remaining getattr-bearing compounds are already safe: ACCESS and LAYOUTCOMMIT use server->cache_consistency_bitmask (no word2 attributes); READDIR does not encode the bit; and LOOKUP_ROOT, FSINFO, STATFS and PATHCONF use fixed bitmaps without it. Signed-off-by: Mike Snitzer <snitzer@kernel.org> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17nfs4.2: add UNCACHEABLE_FILE_DATA attribute supportTom Haynes5-9/+69
Recognize the NFSv4.2 per-file UNCACHEABLE_FILE_DATA attribute (attr 87, draft-ietf-nfsv4-uncacheable-files): decode it via GETATTR, track per- exported-filesystem support, and record on the inode whether a regular file's data must not be cached. Acting on the attribute (opening such files O_DIRECT) is done by a subsequent change. If the NFSv4 server reports a regular file's UNCACHEABLE_FILE_DATA as true, it indicates the file's data must not be cached; the client records this in NFS_I(inode)->uncacheable_file_data for use by the I/O paths. The UNCACHEABLE_FILE_DATA attribute applies only to regular files (NF4REG); per the draft a server MUST reject a query of it on any other object type with NFS4ERR_INVAL. A subsequent commit gates the client accordingly. Link: https://datatracker.ietf.org/doc/draft-ietf-nfsv4-uncacheable-files/ Signed-off-by: Tom Haynes <loghyr@hammerspace.com> [snitzer: adapt Tom's original code focused on metadata for ABE] Co-developed-by: Mike Snitzer <snitzer@hammerspace.com> Signed-off-by: Mike Snitzer <snitzer@hammerspace.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4/flexfiles: report cancelled I/O as a layout errorBenjamin Coddington1-1/+22
When a layout is recalled or revoked the client cancels its in-flight I/O so the layout can be returned. The metadata server needs to learn that this I/O to the storage device did not complete, so that it can reconcile the affected mirror instance (or, if none remains, take other action). The cancellation completed with -EAGAIN, which ff_layout_io_track_ds_error() does not recognise: it fell through the switch and recorded nothing, so no error was reported to the server. -EAGAIN is overloaded in the RPC layer, so rather than key the reporting on it, cancel the I/O with -ECANCELED and map that to NFS4ERR_NXIO in ff_layout_io_track_ds_error() -- the status the client already reports for the transport errors that leave an in-flight write incomplete. The cancelled I/O is then reported to the server via LAYOUTERROR / LAYOUTRETURN. Unlike a genuine transport error, though, we aborted the I/O ourselves and have no evidence the device is at fault, so once the error is recorded we skip marking the device unreachable and forcing a further layout return. The retry disposition is unchanged from the original -EAGAIN cancellation: both NFS4ERR_NXIO and -ECANCELED are no-ops in ff_layout_async_handle_error(), which still resets the I/O to pNFS (or the MDS), so it is re-driven as before. Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17pNFS: honor clora_changed when recalling a layoutBenjamin Coddington3-11/+16
When the metadata server recalls a layout with clora_changed FALSE, the layout is not changing and the client may complete its modified writes to the storage devices before returning the layout (RFC 8881, Section 20.3.3). Only when clora_changed is TRUE -- the server is restriping, or a storage device has failed -- should the client stop writing to the storage devices and redirect through the metadata server. Since commit b739a5bd9d9f ("NFSv4/flexfiles: Cancel I/O if the layout is recalled or revoked") the client cancels in-flight I/O on every recall, regardless of clora_changed. For an unchanged recall this abandons writes whose data may already have reached the storage device; such a write can then land after the LAYOUTRETURN, which the server sees as a write without a layout. Pass the recall's clora_changed value through pnfs_mark_matching_lsegs_return() and only cancel in-flight I/O when the layout is actually changing. When it is not, the existing deferred return path waits for the in-flight writes to drain before sending the LAYOUTRETURN. Other callers, which are tearing down or returning the layout for their own reasons, continue to cancel as before. Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17pNFS: report clora_changed in the cb_layoutrecall_file tracepointBenjamin Coddington2-2/+55
A CB_LAYOUTRECALL carries the clora_changed flag (RFC 8881, Section 20.3.3), which tells the client whether the server is changing the layout (and therefore whether the client should flush modified data to the storage devices before returning, or stop writing to them and go through the metadata server). The client decodes this into cbl_layoutchanged, but it is otherwise invisible. Give nfs4_cb_layoutrecall_file its own event definition and report clora_changed, so the intent of a recall can be observed in a trace. Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17pnfs/blocklayout: Fix device leaks on parse failureZhangGuoDong1-6/+15
bl_parse_concat() and bl_parse_stripe() allocate a child device array and then parse each child in turn. If parsing a child fails, the failed child is not counted in nr_children and the parent may be left with a children array that bl_free_device() will not release when nr_children is zero. Release the failed child and the already parsed children before returning the error. Also make bl_free_device() release the child array whenever the children pointer is set, so that partially initialised concat or stripe devices are cleaned up correctly. bl_parse_scsi() can also fail after assigning d->bdev_file and dropping the file reference. Clear the pointer after fput() so that an outer cleanup path does not put it again. Fixes: 5c83746a0cf2 ("pnfs/blocklayout: in-kernel GETDEVICEINFO XDR parsing") Signed-off-by: ZhangGuoDong <zhangguodong@kylinos.cn> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17NFSv4: remove callback IDR entry on client allocation failureRuoyu Wang3-1/+15
nfs4_alloc_client() allocates an NFSv4.0 callback identifier before it finishes setting up the client. If any later initialization step fails, the error path frees the nfs_client directly with nfs_free_client(). That bypasses nfs_put_client(), which is where the callback IDR entry is removed during normal teardown. A failed allocation can therefore leave cb_ident_idr pointing at a freed nfs_client. A later NFSv4.0 callback lookup by cb_ident would find the stale pointer and take a reference to it. Make the callback IDR removal helper callable by the allocation failure path, and remove the callback identifier before freeing the client. This was found by a local static-analysis checker for publish-before-free lifetime bugs and confirmed by manual inspection. Fixes: f4eecd5da342 ("NFS implement v4.0 callback_ident") Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17nfs: refactor pNFS functions using clear_and_wake_up_bitArnaud Bonnet1-25/+10
Commit 8236b0ae31c83 ("bdi: wake up concurrent wb_shutdown() callers.") introduces the clear_and_wake_up_bit() helper as a wrapper for the common clear -> barrier -> wake up bitops sequence. The file pnfs.c has several helpers with identical contents. Thus they are replaced with the more recent clean_and_wake_up_bit() global helper which describes accurately its effects at the call and still specifies the cleared bit. This also homogenizes the code with other subsystems. Since the helpers are no longer used after this, they can be safely removed. Suggested-by: Agatha Isabelle Moreira <code@agatha.dev> Link: https://kernelnewbies.org/Beginner%20Cleanup%20and%20Refactor%20Tasks%20by%20Agatha%20Isabelle%20Moreira#task_007 Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") Signed-off-by: Arnaud Bonnet <abo@medichon.fr> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17nfs: replace atomic bitops sequence with clear_and_wake_up_bit helperArnaud Bonnet1-3/+1
Commit 8236b0ae31c83 ("bdi: wake up concurrent wb_shutdown() callers.") introduces the clear_and_wake_up_bit() helper as a wrapper for the common clear -> barrier -> wake up bitops sequence. Use the helper in nfs_clear_invalid_mapping as inode.c already relies on functions from <linux/wait_bit.h> and to homogenize with other subsystems. Suggested-by: Agatha Isabelle Moreira <code@agatha.dev> Link: https://kernelnewbies.org/Beginner%20Cleanup%20and%20Refactor%20Tasks%20by%20Agatha%20Isabelle%20Moreira#task_007 Fixes: d529ef83c355 ("NFS: fix the handling of NFS_INO_INVALID_DATA flag in nfs_revalidate_mapping") Signed-off-by: Arnaud Bonnet <abo@medichon.fr> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17Merge tags 'vfs-7.3-rc1.efs' and 'vfs-7.3-rc1.freevxfs' of ↵Linus Torvalds27-3596/+0
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull efs and freevxfs removal from Christian Brauner: "This removes the EFS and freevxfs filesystems: - EFS was the read-only on-disk format SGI used on IRIX before XFS - freevxfs provided compatibility with various old-school Unix systems from the 1990s and was fun 25 years ago. Today it mostly serves as fodder for automated bug checkers. There has been only one known user and contributor in the last 15 years" * tag 'vfs-7.3-rc1.efs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: efs: Remove EFS * tag 'vfs-7.3-rc1.freevxfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: freevxfs: remove the driver
2026-08-17fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-freeRochan Avlur1-1/+2
The abort_on_kill path in request_wait_answer() calls fuse_abort_conn() and returns without waiting for FR_FINISHED. If fuse_dev_do_write() is concurrently processing the same request (FR_LOCKED set), the caller frees req->args while it is still being accessed, causing a use-after-free. Fix this by jumping to the existing wait_event(FR_FINISHED) instead of returning early. The wait will not hang because fuse_abort_conn() ensures all requests are ended. Reported-by: syzbot+d6540a3fa1626e11360d@syzkaller.appspotmail.com Fixes: 204aa22a686b ("fuse: abort on fatal signal during sync init") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Rochan Avlur <rochan.avlur@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17Merge tag 'vfs-7.3-rc1.binfmt' of ↵Linus Torvalds8-516/+1688
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull binfmt updates from Christian Brauner: "This contains a bunch of work for binfmt_misc. It fixes a bunch of old bugs, reworks the locking, and then extends the format registry so a binary type can be matched programmatically and its interpreter computed per exec instead of being a fixed string recorded at registration time. This allows nixos and other to e.g., implement relocatable binaries meaning the interpreter/dynamic loader can be determined programatically, say found relative to the binary. The mechanism is flexible and can support other policies: - Handler lookup is now an rcu walk. An exec that matches no binfmt_misc entry should now never write to a shared cacheline - remove the VERBOSE_STATUS and USE_DEBUG compile time toggles - convert the entry file to a seq_file which simplifies things quite a bit and kills a lot of custom logic - make flags proper enums - rename struct Node to binfmt_misc_entry - allow entries to be removed with unlink(2) - Add the ability to attach bpf programs to binfmt_misc entries so it's possible to dynamically choose the execution environment such as the loader or interpreter on a per binary basis. A handler is an instance of a binfmt_misc_ops struct_ops with a ->match() and a ->load() program. match() decides from the entry lookup walk whether the handler applies under the same registration-order. It can read file content as needed not only the prefetched 256 bytes in bprm->buf. load() then selects the interpreter and stages it through the new bpf_binprm_set_interp(), bpf_binprm_set_interp_arg() and bpf_binprm_set_flags() kfuncs. Handlers are published in a registry keyed by the registering task's user namespace and activated through the existing text interface with a new 'B' type carrying the handler name: echo ':origin:B::::nix:' > /proc/sys/fs/binfmt_misc/register The permission and namespacing model is unchanged. Activating a handler requires the same write access to an instance as any other registration. A container mounting its own instance escapes the host's entries exactly as before. The computed interpreter is opened with open_exec() under the caller's credentials and goes through full LSM vetting as the next binprm level. A program can only ever redirect the caller to something the caller could exec anyway. - Two dispatch modes are added. So far the chosen interpreter owns the whole process identity (argv[0], /proc/pid/cmdline, /proc/self/exe all name interpreter information). So relocatable find the dynamic linker instead. Also a binary passed to execveat() as an inaccessible O_CLOEXEC fd cannot run at all and gdb trips because AT_ENTRY and AT_PHDR do not match the exe file. So PIE symbols are unrelocated. This adds transparent dispatch which allows the interpreter to load the binary through AT_EXECFD and leaves the argument vector exactly as the caller built it and labels mm->exe_file and comm with the binary. It also raises the AT_FLAGS_TRANSPARENT_INTERP aux vector bit. The interpreter keeps control of mapping the binary. The second mode is loader substitution. This allows a binary to be executed natively and only the interpreter to be changed. - Last, interpreters can be bound at registration time. Each interpreter is opened by its own write with the credentials the entry file was opened with. The program picks one per exec with bpf_binprm_select_interp(). Ucounts are used to properly account for pre-opened interpreters via /proc/sys/user/max_binfmt_misc_interpreters" * tag 'vfs-7.3-rc1.binfmt' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (63 commits) binfmt_misc: document the pre-opened interpreter limit selftests/exec: test the pre-opened interpreter limit binfmt_misc: correctly account pre-opened interpreters binfmt_misc: document interpreters bound by a 'B' entry selftests/exec: test interpreters bound to a 'B' entry binfmt_misc: let a 'B' entry bind its interpreters binfmt_misc: carry pre-opened interpreters in struct binfmt_misc_interp selftests/exec: share the bpf handler preconditions binfmt_misc: document registering an entry disabled selftests/exec: test registering an entry disabled selftests/exec: let binfmt_flag_supported() return a bool selftests/exec: check that a binfmt_misc instance cannot be pinned binfmt_misc: let a register string create an entry disabled binfmt_misc: document loader substitution selftests/exec: test binfmt_misc loader substitution binfmt_misc: let a bpf handler request loader substitution binfmt_misc: add the 'L' loader substitution flag binfmt_elf_fdpic: consume a stashed PT_INTERP substitute binfmt_elf: consume a stashed PT_INTERP substitute exec: carry a PT_INTERP substitute in struct linux_binprm ...
2026-08-17fuse: make dentry_tree_work staticBen Dooks1-1/+1
The dentry_tree_work is not exported, so make it static to remove the followign sparse warning: fs/fuse/dir.c:37:21: warning: symbol 'dentry_tree_work' was not declared. Should it be static? Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17fuse: add zero-copy over io-uringJoanne Koong6-16/+202
Implement zero-copy in fuse io-uring to eliminate memory copies between the application, kernel, and server for read/write operations. The server can directly access client pages or page cache folios without copying data through an intermediary buffer. When a fuse request arrives, the kernel registers the relevant pages into a sparse slot in the server's io_uring registered buffer table. The server can then operate on these pages directly using io-uring fixed buffer operations (eg read_fixed/write_fixed) and the kernel unregisters these pages when the request completes. Non-page-backed args (eg op out headers) will go through the payload buffer as normal. The server can specify which open files should have their reads/writes go through zero-copy, by setting the FOPEN_IO_URING_ZERO_COPY flag when servicing opens. This requires CAP_SYS_ADMIN and bufpools. This is gated behind CAP_SYS_ADMIN because zero-copy allows the server direct access to the client's underlying pages, rather than operating on an intermediary buffer that the contents of the client's pages were copied into or on page cache folios. The request flow for the zero-copy direct-io write path (client writes data, server reads it) is as follows: ======================================================================= | Kernel | FUSE server | | | "write(fd, buf, 1MB)" | | | | >sys_write() | | >fuse_file_write_iter() | | >fuse_send_one() | | [req->args->in_pages = true] | | [folios hold client write data] | | | | >fuse_uring_copy_to_ring() | | >copy_header_to_ring(IN_OUT) | | [memcpy fuse_in_header] | | >copy_header_to_ring(OP) | | [memcpy write_in header] | | | | >fuse_uring_args_to_ring() | | >setup_fuse_copy_state() | | [skip_folio_copy = true] | | | | >fuse_uring_set_up_zero_copy() | | [folio_get for each client folio] | | [build bio_vec array from folios] | | >io_buffer_register_bvec() | | [register pages at ent->zero_copy_index] | | [ent->zero_copied = true] | | | | >fuse_copy_args() | | [skip_folio_copy => return 0 | | for page arg, skip data copy] | | | | >copy_header_to_ring(RING_ENT) | | [memcpy ent_in_out] | | >io_uring_cmd_done() | | | | | [CQE received] | | | | [issue io_uring READ at | | ent->zero_copy_index] | | [reads directly from | |client's pages (ZERO_COPY)] | | | | [write data to backing | | store] | | [submit COMMIT AND FETCH] | | | >fuse_uring_commit_fetch() | | >fuse_uring_commit() | | >fuse_uring_copy_from_ring() | | >fuse_uring_req_end() | | >io_buffer_unregister(ent->zero_copy_index) | | [unregister pages from index] | | >fuse_zero_copy_release() | | [folio_put for each folio] | | [ent->zero_copied = false] | | >fuse_request_end() | | [wake up client] | The zero-copy read path is analogous. Some requests may have both page-backed args and non-page-backed args. For these requests, the page-backed args are zero-copied while the non-page-backed args are copied to the buffer selected from the buffer pool: zero-copy: pages registered via io_buffer_register_bvec() non-page-backed: copied to payload buffer via fuse_copy_args() For a request whose payload is zero-copied, the registration/unregistration path looks like: register: fuse_uring_set_up_zero_copy() folio_get() for each folio io_buffer_register_bvec(ent->zero_copy_index) unregister: fuse_uring_req_end() io_buffer_unregister(ent->zero_copy_index) -> fuse_zero_copy_release() callback folio_put() for each folio Please note that on abort for in-flight zero-copied requests that have been sent to userspace, the registered bvec slot remains occupied and its folios remain pinned until the io-uring ring is destroyed, at which point io-uring unregisters all buffers and the fuse_zero_copy_release() callback drops the folio references. Unregistering at teardown would require operating on the ring context directly, whose validity is hard to ascertain; this is deemed not worth the complexity for the abort race, since everything is freed when the ring is torn down. The throughput improvement from zero-copy depends on how much of the per-request latency is spent on data copying vs backing I/O. The gain comes from eliminating the payload-buffer memcpy, but accessing the zero-copied pages requires the server to issue the read/write as an IORING_OP_READ/WRITE_FIXED operation. The benefit is largest when the mempcy is a meaningful fraction of per-request latency while backing i/o is still noticable enough that the extra io-uring op's overhead doesn't dominate. Benchmarked with passthrough_hp (--nopassthrough, q_depth=8) on a 2-socket Intel Xeon Gold 6138 (40 cores / 80 threads), using fio (sync engine, bs=1M, O_DIRECT, numjobs=2, 30s run + 10s ramp, 3 runs) where direct-I/O throughput is against a RAM-backed (tmpfs) source (backing I/O is not the bottleneck): baseline registered-buf zero-copy (zc vs base) direct read ~5.1 GB/s ~5.4 GB/s ~8.9 GB/s (+75%) direct write ~3.4 GB/s ~4.8 GB/s ~5.1 GB/s (+50%) Reads end up higher than writes because the backing store reads faster than it writes (the baseline shows the same read>write gap, and the raw device does too). On a device-bound NVMe (~2 GB/s reads) the read gain shrinks to ~10-16% (and no measurable gains for writes), as backing I/O rather than the eliminated copy dominates latency. The benefit overall scales with how much of the per-request latency is the data copy versus backing I/O. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17fuse: support registered buffer pools in io-uringJoanne Koong2-21/+99
Allow servers to use a buffer pool that is also registered through io-uring. When the server registers a buffer pool with io-uring, the pages backing the pool are pinned upfront. This eliminates the overhead of pinning/unpinning user pages and translating virtual addresses per i/o request. This also allows servers to use the same registered memory for subsequent backing store I/O (eg read_fixed/write_fixed), keeping data in the same pinned pages without additional pinning or mapping overhead required. To use this, the server needs to set the FUSE_URING_REGISTERED_BUFPOOL flag when adding a bufpool through the FUSE_IO_URING_CMD_ADD_BUFPOOL cmd. For every sqe submitted (including the one for adding the bufpool), it should set sqe->uring_cmd_flags to include IORING_URING_CMD_FIXED, and pass in the index where the registered bufpool resides to sqe->buf_index. Benchmarked with passthrough_hp (--nopassthrough, q_depth=8) on a 2-socket Intel Xeon Gold 6138 (40 cores / 80 threads), using fio (sync engine, bs=1M, O_DIRECT, numjobs=2, 30s run + 10s ramp, 3 runs) where direct-I/O throughput is against a RAM-backed (tmpfs) source (backing I/O is not the bottleneck): baseline registered buffers direct read ~5.1 GB/s ~5.4 GB/s (+~5%) direct write ~3.4 GB/s ~4.8 GB/s (+~45%) Registered buffers bring up the write path speed up closer to speed of reads. There isn't much improvement for reads because it is already fast enough where it's at the copy-bound ceiling (surpassing that requires doing zero-copy). On a device-bound NVMe though, the differences are within noise, as backing I/O dominates per-request latency. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17fuse: add io-uring buffer poolsJoanne Koong3-29/+249
Right now, ents and buffers are tightly coupled in fuse io-uring where each entry has its own dedicated payload buffer, requiring N buffers for N entries where each buffer must be large enough to accomodate the maximum payload size. This is suboptimal as most request types (lookup, open, release, getattr, etc) require vastly less bytes than the maximum payload size and some requests (unlink, rmdir, fsync, flush, etc) do not require payload buffers at all. Instead of requiring a 1:1 coupling between ents and payload buffers, allow the server to pass in a buffer pool (a contiguous chunk of memory) that the kernel will use as it wishes for servicing ents/requests. Entries only reserve a "buffer" from the pool while actively processing a request that requires a payload buffer. This decoupling and letting the kernel delegate memory from the pool for requests allows the kernel to optimize memory usage and reduces the memory usage requirements needed to use fuse-over-io-uring. A pool is registered per queue with the new FUSE_IO_URING_CMD_ADD_BUFPOOL command. The server passes the pool's base address and length in fuse_uring_cmd_req.bufpool.{uaddr,len}. Internally, the kernel splits the region into buffers of ring->max_payload_sz bytes each (nr_bufs = pool len / max_payload_sz). A queue commits to a payload mode on first use: registering an entry that carries its own payload selects the legacy per-entry mode, while ADD_BUFPOOL selects pool mode. The two are mutually exclusive, so ADD_BUFPOOL must be issued before any payload-carrying entries are registered on that queue. The queue must have been created before the bufpool is added, through the FUSE_IO_URING_CMD_ADD_QUEUE command. The kernel tracks free buffers with a bitmap (a set bit marks a free buffer). On dispatch, a request that needs a payload claims a free buffer (find_first_bit + clear). A request that needs none claims nothing. The buffer's byte offset within the pool is reported to the server in the new fuse_uring_ent_in_out.offset field so that the server can locate the payload. On completion the buffer is returned to the pool or reused directly if the next request on that entry also has a payload. The FUSE_HAS_IO_URING_BUFPOOL flag advertises kernel support to the server for bufpools. Buffer pool request flow ~~~~~~~~~~~~~~~~~~~~~~~~ | Kernel | FUSE daemon | | | [request arrives] | | [claim a free pool buffer] | | >fuse_uring_select_buffer() | | [copy headers to ring] | | [copy payload to buffer] | | [report buffer offset in ent_in_out] | | >io_uring_cmd_done() | | | [read headers] | | [read/write payload at offset] | | [process request] | | >io_uring_submit() | | COMMIT_AND_FETCH | >fuse_uring_commit_fetch() | | [copy reply from ring] | | [return buffer to the pool] | | >fuse_uring_recycle_buffer() | Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17fuse: add FUSE_IO_URING_CMD_ADD_QUEUEJoanne Koong1-7/+38
fuse-over-io-uring queues are currently created lazily, as a side effect of the first FUSE_IO_URING_CMD_REGISTER command for a given qid. This ties queue creation to entry registration. Add a FUSE_IO_URING_CMD_ADD_QUEUE command so a server can create a queue explicitly, decoupling queue setup from entry registration. This is additionally a prerequisite for FUSE_IO_URING_CMD_ADD_BUFPOOL, which attaches a buffer pool to an existing queue and therefore needs the queue to have been created first. Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17fuse: decouple fuse_ring creation from ent registrationJoanne Koong5-23/+22
Currently, the connection's fuse_ring is created lazily on the first FUSE_IO_URING_CMD_REGISTER command. A server registers entries from one thread per queue (one per CPU) and those threads issue their first REGISTER command concurrently. They then race to create the single per-connection fuse_ring, which required open-coded handling in fuse_uring_create() to detect and protect against concurrent creations. Decouple fuse_ring creation from ent registration and move it to FUSE_INIT reply processing after a server has negotiated and set FUSE_OVER_IO_URING. The ring is published before the connection is marked initialized. fuse_uring_register() no longer creates the ring and it instead uses the ring set up at init time. Reviewed-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
2026-08-17smb/server: fix session counter on session removalZe Tan1-4/+10
See the procedure below: smb2_sess_setup ksmbd_smb2_session_create __session_create hash_add(sessions_table, &sess->hlist, sess->id) ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS) ksmbd_conn_handler_loop ksmbd_server_terminate_conn ksmbd_sessions_deregister hash_del(&sess->hlist) // do not decrement KSMBD_COUNTER_SESSIONS KSMBD_COUNTER_SESSIONS tracks sessions published in sessions_table, but session removal does not decrement it. The value therefore keeps growing after sessions are expired, rejected during registration, or removed on the last channel disconnect. Fixes: b38f99c1217a ("ksmbd: add procfs interface for runtime monitoring and statistics") Signed-off-by: Ze Tan <tanze@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: update session counter under sessions table lockZe Tan1-1/+1
KSMBD_COUNTER_SESSIONS tracks sessions published in sessions_table. Increment it while holding sessions_table_lock so publishing a session and updating the counter happen together. Fixes: b38f99c1217a ("ksmbd: add procfs interface for runtime monitoring and statistics") Signed-off-by: Ze Tan <tanze@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: fix session leak in ksmbd_session_register()Ze Tan1-1/+12
See the procedure below: smb2_sess_setup ksmbd_smb2_session_create __session_create atomic_set(&sess->refcnt, 2) hash_add(sessions_table, &sess->hlist, sess->id) ksmbd_session_register xa_store(&conn->sessions, sess->id, sess) // fail ksmbd_user_session_put atomic_dec(&sess->refcnt) // refcnt is 1, session is not freed Remove the session from sessions_table and drop its table reference if xa_store() fails. Fixes: f5c779b7ddbd ("ksmbd: fix racy issue from session setup and logoff") Signed-off-by: Ze Tan <tanze@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: warn if ksmbd_proc_create() failsZe Tan4-6/+16
Print a warning if the sessions procfs entry cannot be created. Signed-off-by: Ze Tan <tanze@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: bound smb_check_perm_dacl() ACE walks by DACL sizeHang Nan1-2/+2
smb_check_perm_dacl() validates that the DACL fits inside the NT security descriptor, but then bounds its two ACE walks by the remaining NTSD length (acl_size) rather than the DACL's declared size (pdacl_size). When pdacl->size is smaller than the trailing NTSD buffer, bytes after the declared DACL boundary - still inside the stored security descriptor - are parsed as ACEs during access checks. A crafted DACL can place an access-granting ACE beyond pdacl->size, and the current code accepts it during SMB2_CREATE access validation, while parse_dacl() and smb_inherit_dacl() stop at pdacl_size. Bound both ACE walks by pdacl_size to match the DACL boundary semantics used elsewhere in the server. Validation: - semantic KUnit harness shows the post-boundary ACE is selected before the fix and rejected (EACCES) after it - linux master (7.2-rc6), x86_64 Fixes: 8f0541186e9a ("ksmbd: fix heap-based overflow in set_ntacl_dacl()") Signed-off-by: Hang Nan <2122295973@qq.com> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: make RDMA encryption diagnostics conditionalNamjae Jeon2-18/+90
The temporary RDMA encryption diagnostics logged every SMB3 request and successful payload operation with pr_err(), which made normal traffic too noisy. Keep only negotiation, RDMA READ preparation, RDMA WRITE transform metadata, crypto completion, and final transfer completion messages as KSMBD_DEBUG_RDMA diagnostics. Keep error reports for malformed metadata, crypto, RDMA transfer, and file write failures at error level. This preserves the diagnostics needed to verify RDMA transform operation without flooding the kernel error log during normal I/O. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: add SMB Direct RDMA encryption transformNamjae Jeon10-63/+663
Port SMB Direct RDMA payload encryption support to the current ksmbd tree. The current tree already supports all-state lookup for encrypted expired sessions, so the overlapping lookup hunk from the original patch is intentionally omitted. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: handle encrypted compressed requestsNamjae Jeon4-24/+97
SMB3 permits a message to be compressed before it is encrypted. After decrypting such a request, ksmbd must trim the AEAD tag using OriginalMessageSize, decompress the nested compression transform, and validate the resulting SMB2 PDU. Share the decompression helper between the connection receive path and the post-decryption work path so unencrypted and encrypted compressed requests follow the same validation. Fixes: a08de24c2b85 ("ksmbd: negotiate and decode SMB2 compression") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: decrypt requests from expired encrypted sessionsNamjae Jeon2-6/+14
Previous-session replacement marks the old session expired but retains its SMB3 encryption key. An in-flight encrypted request can still arrive on that connection. Rejecting the expired session before decryption made ksmbd treat the request as a key failure and abort the transport, causing reconnect failures. Allow key lookup for expired sessions that have encryption enabled. Keep the session reference during validation so the normal STATUS_USER_SESSION_DELETED response is encrypted with the old key. The session remains expired and no command is executed. Fixes: fa9415d4024f ("ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: disconnect on SMB3 decryption failureNamjae Jeon4-1/+26
MS-SMB2 requires the server to disconnect a connection when an encrypted transform cannot be associated with a session or fails authenticated decryption. This includes an encrypted request that still carries a SessionId invalidated through PreviousSessionId. Move the connection to EXITING and shut down its transport when decrypt_req() fails. Add the missing TCP shutdown callback so a receive blocked in kernel_recvmsg() is released; SMB Direct already provides the corresponding callback. Plaintext requests using an invalidated SessionId do not take this path and continue to receive STATUS_USER_SESSION_DELETED. Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: encrypt interim responses to encrypted requestsNamjae Jeon1-4/+67
The normal response path applies an SMB3 transform when the request was encrypted. Async interim responses, completed compound prefixes and two CHANGE_NOTIFY cleanup paths write their synthetic response work directly, bypassing that encryption step. A packet capture shows FE SMB2 STATUS_PENDING, CREATE and CHANGE_NOTIFY responses following FD SMB3 requests. The client resets the connection immediately after receiving those plaintext responses. Send synthetic interim work through a common helper that applies the session encryption transform first. A compound prefix shares the original work's response iov, which encryption would replace in place, so flatten it into an independently owned work before encrypting and sending it. Fixes: 64bfa9d49026 ("smb/server: use MSG_EOR for async interim response") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: scope session state changes to bound connectionsNamjae Jeon4-16/+41
ksmbd_all_conn_set_status() treats every connection whose transient binding flag is set as belonging to the target SessionId. A logoff or session replacement can consequently move an unrelated connection to NEED_RECONNECT or NEED_SETUP. Pass the target session itself and select connections using either the connection-local session xarray or the session's permanent channel list. Use the same association test while waiting for requests to drain. Serialize session-wide status changes under request_lock and do not overwrite EXITING or RELEASING. Protect the shutdown transition with the same lock so a concurrent session update cannot revive a closing connection. Fixes: f5a544e3bab7 ("ksmbd: add support for SMB3 multichannel") Fixes: abcc506a9a71 ("ksmbd: fix racy issue from smb2 close and logoff with multichannel") Fixes: c444139cb747 ("ksmbd: rewrite stop_sessions() with restartable iteration") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: fix encrypted request lookup on bound channelsNamjae Jeon2-3/+10
An SMB3 multichannel binding registers the secondary connection in the session channel list, but does not insert the session into the secondary connection's session xarray. The decryption path only searches the connection-local xarray. As a result, every encrypted request received on a bound channel fails with "Could not get decryption key". Use the channel-aware session lookup for decryption. Also stop using the temporary conn->binding flag to decide whether the global lookup is allowed. Validate the permanent channel association under chann_lock instead. Fixes: f5a544e3bab7 ("ksmbd: add support for SMB3 multichannel") Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: add per-share SMB3 encryption enforcementNamjae Jeon5-5/+34
Add a share flag for requiring SMB3 encryption on an individual share. Advertise SMB2_SHAREFLAG_ENCRYPT_DATA in TREE_CONNECT responses and reject both unencrypted TREE_CONNECT attempts and plaintext requests for shares carrying the flag. Keep BIT(19) reserved for the existing ksmbd-tools WIDE_LINKS flag and use BIT(20) for the new netlink ABI flag. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: notify parent directory leases on child createNamjae Jeon2-4/+8
BVT_DirectoryLeasing_ReadWriteHandleCaching requires a parent directory lease break notification when another client creates a child in the leased directory. A child CREATE without a lease context did not notify the parent lease holders because the notification path expected a non-NULL lease context. Allow the parent lease notification helper to handle a NULL child lease context and notify matching parent leases. Invoke it after a child is created without a lease context while preserving the existing lease-key filtering for requests that provide one. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: implement SMB2 AppInstanceVersion takeoverNamjae Jeon3-9/+101
BVT_AppInstanceVersion_SMB311_GreaterVersion, BVT_AppInstanceVersion_SMB311_SameVersion, BVT_AppInstanceVersion_SMB311_LowerAppInstanceVersionHigh, and BVT_AppInstanceVersion_SMB311_LowerAppInstanceVersionLow exercise ordered opens using the same AppInstanceId. ksmbd tracked the AppInstanceId, but did not parse the version context or enforce the version ordering, so versioned opens returned incorrect sharing violations. Parse and retain the 24-byte AppInstanceVersion context with each open. Reject a version that is lower than or equal to the active version with STATUS_FILE_FORCED_CLOSED, reject an unversioned open against a versioned handle, and close the previous handle for a newer takeover. Do not apply the takeover check to durable reconnect or replay requests. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: accept unspecified volatile ID on durable reconnectNamjae Jeon1-2/+6
BVT_DurableHandleV1_Reconnect_WithBatchOplock, BVT_DurableHandleV1_Reconnect_WithLeaseV1, BVT_DurableHandleV2_Reconnect_WithBatchOplock, and BVT_DurableHandleV2_Reconnect_WithLeaseV1 fail to reconnect a durable handle when the request leaves VolatileFileId unset. A durable reconnect request may omit VolatileFileId by setting it to zero. Treating zero as an ID makes ksmbd reject the request whenever the saved volatile ID is nonzero. Only compare the saved and requested volatile IDs when the request contains a nonzero value. Explicit mismatches continue to be rejected. This allows SMB2 durable handle V1 and V2 reconnects that identify the handle through the persistent ID and reconnect context. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: fix tree connection leak in smb2_tree_connect()Ze Tan1-1/+9
See the procedure below: smb2_tree_connect ksmbd_tree_conn_connect xa_store(&sess->tree_conns, tree_conn->id, tree_conn) ksmbd_counter_inc(KSMBD_COUNTER_TREE_CONNS) ksmbd_share_tree_conn_inc(sc) ksmbd_iov_pin_rsp // fail status.ret = KSMBD_TREE_CONN_STATUS_NOMEM // do not disconnect tree_conn Disconnect the new tree connection if ksmbd_iov_pin_rsp() fails. Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound") Signed-off-by: Ze Tan <tanze@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: wait for deferred notify cancellationNamjae Jeon1-0/+12
A cancelled SMB2 CHANGE_NOTIFY request is completed from system_wq. The deferred work keeps a reference to the connection, but it is not included in the connection's r_count. During connection teardown, ksmbd_conn_transport_destroy() can therefore finish the connection handler and destroy session proc entries before the deferred response runs. Account for the deferred cancellation work in r_count. The connection handler now waits for the deferred response to finish before it deregisters sessions and removes their proc entries. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: fix use-after-free in ksmbd_conn_transport_destroy()ChenXiaoSong1-1/+6
Reproducer (Link[1]): 1. Build kernel with CONFIG_KASAN=y 2. server: systemctl start ksmbd 3. client: mount -t cifs //localhost/export /mnt 4. client: umount /mnt 5. server: modprobe -r ksmbd The error message is as follows: ================================================================== BUG: KASAN: slab-use-after-free in proc_remove+0x3e/0x80 Read of size 8 at addr ffff88810654e098 by task modprobe/785 ... Call Trace: <TASK> __dump_stack+0x19/0x30 dump_stack_lvl+0x49/0x60 print_address_description+0x7b/0x200 print_report+0x5b/0x70 kasan_report+0xed/0x130 __asan_report_load8_noabort+0x18/0x20 proc_remove+0x3e/0x80 ksmbd_conn_transport_destroy+0x2b/0x320 [ksmbd] cleanup_module+0x33/0xe00 [ksmbd] __se_sys_delete_module+0x276/0x400 __x64_sys_delete_module+0x5f/0x70 x64_sys_call+0x2675/0x3030 do_syscall_64+0xf0/0x3b0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f5b56d2b02b ... </TASK> Allocated by task 159: kasan_save_track+0x2f/0x70 kasan_save_alloc_info+0x40/0x50 __kasan_slab_alloc+0x52/0x70 kmem_cache_alloc_noprof+0x168/0x3e0 __proc_create+0x20b/0x710 proc_create_single_data+0x78/0x150 ksmbd_proc_create+0x24/0x30 [ksmbd] ksmbd_conn_transport_init+0x4f/0x80 [ksmbd] server_ctrl_handle_work+0x64/0x2c0 [ksmbd] process_scheduled_works+0x788/0xec0 worker_thread+0x894/0xc10 kthread+0x2e5/0x3c0 ret_from_fork+0x168/0x4f0 ret_from_fork_asm+0x1a/0x30 Freed by task 785: kasan_save_track+0x2f/0x70 kasan_save_free_info+0x4a/0x60 __kasan_slab_free+0x47/0x70 kmem_cache_free+0x122/0x410 pde_put+0xfd/0x160 remove_proc_subtree+0x365/0x540 proc_remove+0x6a/0x80 ksmbd_proc_cleanup+0x1f/0x60 [ksmbd] cleanup_module+0x18/0xe00 [ksmbd] __se_sys_delete_module+0x276/0x400 __x64_sys_delete_module+0x5f/0x70 x64_sys_call+0x2675/0x3030 do_syscall_64+0xf0/0x3b0 entry_SYSCALL_64_after_hwframe+0x76/0x7e ================================================================== Reported-by: Kyenghwan Hwang <obnred@gmail.com> Link[1]: https://lore.kernel.org/linux-cifs/8ea028f5-90f4-4d21-b1ac-a343f0f04d88@chenxiaosong.com/ Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: detach blocked lock requests before freeingNamjae Jeon2-8/+17
A file_lock retained by ksmbd for byte-range lock bookkeeping can still be part of the VFS blocked-request graph. In particular, the VFS can chain a new waiter below an already blocked request through flc_blocked_requests. The ksmbd_file reference count does not cover that graph. Both __ksmbd_close_fd() and the cross-request unlock path free these retained file_lock objects directly. If a dependent waiter is still attached, locks_release_private() hits BUG_ON(!list_empty(&flc->flc_blocked_requests)). The same lifetime mismatch can leave a freed ksmbd_lock reachable through its request-local llist. Detach the file_lock from the blocked-request graph before freeing it in the close, cross-request unlock, and rollback paths. locks_delete_block() also wakes requests chained below the object. Remove llist when a completed lock is published so a globally visible ksmbd_lock no longer points into the submitting worker's stack. Fixes: d63528eb0d43 ("ksmbd: free ksmbd_lock when file is closed") Reported-by: Kyenghwan Hwang <obnred@gmail.com> Tested-by: Kyenghwan Hwang <obnred@gmail.com> Tested-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: Clear Preauth_HashValue in smb2pdu.c with kfree_sensitive()Thomas Huth1-2/+2
struct preauth_session contains the Preauth_HashValue[] array that might contain sensitive data. Use kfree_sensitive() to clear it before returning the memory to the heap. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: Free sensitive data in connection.c with kfree_sensitive()Thomas Huth1-3/+3
struct ksmbd_conn contains an embedded struct ntlmssp_auth with the ciphertext[] and cryptkey[] arrays, so to avoid leaking this information via the heap, it should be freed with kfree_sensitive(). While we're at it, also use kfree_sensitive() for freeing preauth_info in ksmbd_conn_free() to avoid that the Preauth_HashValue[] could leak via the heap here, too. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: Free session data in user_session.c with kfree_sensitive()Thomas Huth1-2/+2
struct ksmbd_session contains some arrays with sensitive information, like sess_key, smb3encryptionkey, smb3decryptionkey and smb3signingkey. Thus let's make sure that this information cannot leak via the heap and use kfree_sensitive() to free it. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: Make sure that passkey is not leaked on the heap in user_config.cThomas Huth1-3/+3
Use kfree_sensitive() to free the user->passkey (and the struct ksmbd_login_response in ksmbd_login_user() that contains the same information) to avoid that this information could leak somewhere else via the heap. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: Clear sensitive stack and heap data in auth.cThomas Huth1-2/+10
Sensitive data like keys that are stored in stack-local arrays could be leaked via the stack to the calling functions, or via the heap when using only normal kfree() functions. There is no known vulnaribility for this right now, but it's good security style to explicitly zeroize this sensitive matieral as soon as possible to avoid that it could be exploited together with other bugs later. In calc_ntlmv2_hash(), the struct hmac_md5_ctx is normally cleared during hmac_md5_final() already, but in case of errors, this function is skipped and ctx is never zeroized, so add a memzero_explicit(&ctx, sizeof(ctx)) there to fix the problem. In ksmbd_krb5_authenticate(), the ksmbd_spnego_authen_response contains the session key in the payload. It's currently freed with plain kvfree(). Let's better use kvfree_sensitive() instead. In generate_key(), the prfhash[] array is used to calculate the key, but it's never cleared, so it leaks on the stack. Thus clear this with a memzero_explicit(), too. In ksmbd_crypt_message(), the sign[] and key[] arrays are leaked via the stack, too. Make sure to clear them via memzero_explicit() at the end. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>