summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-08-17ksmbd: implement full-file copy for AAPL ChunkCount=0 COPYCHUNKGael Blivet2-13/+93
fsctl_copychunk() treats FSCTL_SRV_COPYCHUNK with ChunkCount=0 as the standard SMB2 "query my copy limits, don't copy anything" request and returns success without ever looking up the file handles. That's correct for compliant SMB2 clients, but macOS Finder's Cmd+D duplicate sends ChunkCount=0 expecting the server to copy the whole file/stream -- so duplicated files are left at their just-created 0 bytes while the client reports success. Scope the full-copy fallback to AAPL-negotiated connections on a Time Machine share (conn->is_aapl && KSMBD_SHARE_FLAG_TIME_MACHINE) only, so standard non-AAPL SMB2 clients, and AAPL-negotiated clients on ordinary shares, keep the spec-correct query-limits behavior unchanged. both streams and regular files now share a single chunk_count == 0 fast path added right after src_file_size is computed, reusing the same buffered-copy helper and vfs_copy_file_range()/COPY_FILE_SPLICE fallback the existing per-chunk loop already uses, rather than the separate xattr-specific get/setxattr path this used before that rework. ChunksWritten/ChunkBytesWritten are 0 in the response: this is a synthesized whole-file copy, not a response to any chunk descriptor the client actually sent (it sent none), so there's no real chunk to report the count/size of. Only TotalBytesWritten is meaningful here. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: defer CHANGE_NOTIFY completion instead of STATUS_NOT_IMPLEMENTEDGael Blivet5-3/+280
smb2_notify() currently returns STATUS_NOT_IMPLEMENTED synchronously for every CHANGE_NOTIFY request. Genuine SMB2 servers never complete a CHANGE_NOTIFY spontaneously -- it's satisfied only by a real directory change or with STATUS_NOTIFY_CLEANUP when the watched handle is closed. macOS smbfs.kext depends on this deferred-completion contract: receiving STATUS_NOT_IMPLEMENTED instead makes it hard-freeze on unmount, since it never sees the cleanup it's waiting for. Add a notify_pendings list on struct ksmbd_file (protected by the existing f_lock) and a notify_entry list_head on struct ksmbd_work to link onto it. smb2_notify() now replies STATUS_PENDING immediately and queues a deferred STATUS_NOTIFY_CLEANUP response on the watched handle; __ksmbd_close_fd() drains and sends any pending notifications when the handle is actually closed. The drain splices the list out under fp->f_lock first, then processes the detached copy without the lock -- smb2_notify() on another connection can be adding to the same list at the same time a close happens on this one, and ksmbd_conn_write() can sleep (it takes the connection's write mutex), so it must not be called while the spinlock is held. Also handle the FileId=FFFF...FFFF share-root sentinel that macOS backupd sends to watch for changes without holding an open handle -- without an immediate STATUS_PENDING/STATUS_NOTIFY_CLEANUP reply here, backupd aborts Time Machine setup with STATUS_FILE_CLOSED. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: send inline FinderInfo in FIND responses when READDIR_ATTR negotiatedGael Blivet1-5/+53
Without READDIR_ATTR, macOS Finder resolves type/creator/icon for every file in a directory listing by opening its AFP_AfpInfo stream individually -- one extra CREATE+QUERY_INFO+CLOSE round trip per file, which is the dominant cost of browsing a large directory over SMB from a Mac. When the client negotiates READDIR_ATTR (conn->aapl_readdir_attr, set during CREATE's AAPL context exchange), inline the same information directly into each FILEID_BOTH_DIRECTORY_INFORMATION FIND entry: EaSize = max_access, expanded specific rights (GENERIC_ALL_FLAGS), not the raw FILE_GENERIC_ALL_LE "generic" meta-bit -- that bit has none of the specific FILE_* rights macOS's smbfs.kext checks bit-by-bit, so reporting it directly would fail every access check and show Finder's "no entry" badge on every file/folder. ShortNameLength = 24 (fixed; the spec says 0 when there's no short name; kept for wire parity with reference server, see below) ShortName[0..7] = resource fork size (0 -- no resource forks) ShortName[8..23] = compressed FinderInfo (all zero: type/creator unset, client falls back to extension-based icon/type detection, consistent with the AFP_AfpInfo synthesis this mirrors) Reserved2 = Unix mode bits Reparse-point status is still carried via ExtFileAttributes rather than EaSize once READDIR_ATTR is active, since EaSize is repurposed for max_access. Reverse-engineered from macOS smbfs.kext network behavior and cross-checked against reference implementation marshalling (reference implementation behavior). Also confirmed against AAPL's published public client behavior (public client behavior reference) -- every field here matches exactly, except ShortNameLength=24: real V1 clients read but never examine that field, so it's kept for wire parity with reference server, not because macOS requires it. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: synthesize empty AFP_AfpInfo xattr on first probeGael Blivet1-0/+24
Once a server advertises the AAPL COPYFILE capability, macOS requires an AFP_AfpInfo stream on every file it looks at for Finder type/ creator/icon resolution. smb2_set_stream_name_xattr() currently returns -EBADF (STATUS_OBJECT_NAME_NOT_FOUND) when a client opens AFP_AfpInfo with FILE_OPEN disposition and the xattr doesn't exist yet, which macOS treats as fatal for that file: Finder falls back to showing a generic icon, and file operations that depend on succeeding against this stream (e.g. Cmd+D duplication) fail. Synthesize a 60-byte zeroed AFP_AfpInfo xattr (magic 0x00051607, version 0x00020000, both big-endian per the AFP_AfpInfo wire format) on first FILE_OPEN probe instead. type=0/creator=0 tells macOS to fall back to extension-based type detection, which is correct for files with no explicit Finder metadata. The synthesized xattr persists on disk, so this only pays the extra write once per file; a later genuine write from macOS (e.g. after the user assigns a custom icon) overwrites it normally. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: add AAPL kAAPL_SERVER_QUERY create context supportGael Blivet10-2/+212
macOS clients (Finder, and specifically Time Machine's backupd) send an "AAPL" SMB2 create context on CREATE to negotiate AAPL-specific server capabilities (server_caps/vol_caps/model string). Without a response to this context, macOS Time Machine over SMB does not work at all. Add the AAPL create context structs (create_aapl_rsp, aapl_server_query_req) and create_aapl_rsp_buf(), which builds the kAAPL_SERVER_QUERY response mirroring the layout observed from macOS's own smbd, including the model string workaround: omitting the model string when the client requested it causes smbfs.kext to enter a broken disconnect path requiring a full macOS reboot to recover from. Command codes and bitmap values reuse the existing SMB2_CRTCTX_AAPL_* constants in fs/smb/common/smb2pdu.h. Wire format confirmed against AAPL's published public client kernel source (public client behavior reference) -- every field here and every SMB2_CRTCTX_AAPL_* constant matches exactly. Hook the request parsing and response into smb2_open()'s existing create-context handling, following the same DataOffset+DataLength bounds-checking convention already used by every other context parser in this file. The AAPL model string is configurable via the existing netlink startup path (server_conf.aapl_model, default "Xserve"). This is scoped to shares with the new KSMBD_SHARE_FLAG_TIME_MACHINE flag only, not enabled globally -- AAPL's AAPL extension is undocumented, so containing its blast radius to shares that explicitly opt in limits risk to ordinary SMB shares. conn->aapl_readdir_attr is set here when the client also advertises READDIR_ATTR support, but the actual inline-FinderInfo wire format (the feature that flag gates) is not implemented yet -- follow-up commit. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb: server: fix leak of ksmbd_ipc_login_request_ext() returned bufferEnzo Matsumiya2-0/+2
Free it unconditionally after ksmbd_alloc_user() calls. kmemleak splat: unreferenced object 0xffff888103b83540 (size 192): comm "pool-0", pid 16970, jiffies 4377290937 hex dump (first 32 bytes): 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace (crc 408ccc66): __kvmalloc_node_noprof+0x730/0x920 handle_generic_event+0xec/0x1a0 [ksmbd] genl_family_rcv_msg_doit+0xe0/0x130 genl_rcv_msg+0x181/0x290 netlink_rcv_skb+0x4f/0x100 genl_rcv+0x28/0x40 netlink_unicast+0x1e6/0x2c0 netlink_sendmsg+0x20a/0x450 ____sys_sendmsg+0x2e8/0x310 ___sys_sendmsg+0x78/0xc0 __sys_sendmsg+0x63/0xc0 do_syscall_64+0xa1/0x670 entry_SYSCALL_64_after_hwframe+0x76/0x7e Fixes: a77e0e02af1c ("ksmbd: add support for supplementary groups") Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: skip fallocate for SMB2_CREATE_ALLOCATION_SIZE on a stream handleGael Blivet1-7/+16
smb2_open() calls vfs_fallocate(fp->filp, ...) unconditionally when a client's CREATE request includes an AllocationSize create context. For a stream handle, fp->filp refers to the base file's data fork (streams are xattr-backed on the same underlying file, not separate files), so this pre-allocates storage on the base file's actual data instead of doing anything meaningful for the stream -- fallocate has no applicability to an xattr-backed stream at all. Skip the fallocate call for stream handles. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: don't check directory emptiness when deleting a streamGael Blivet1-1/+1
set_file_disposition_info() checks S_ISDIR(inode->i_mode) && ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY to refuse deleting a non-empty directory. A stream handle's fp->filp refers to the same underlying inode as its base file or directory (streams are xattr-backed on that same inode), so this check also fires when the target is actually a stream attached to a directory, not the directory itself -- deleting the stream then incorrectly fails with -EBUSY whenever the directory happens to be non-empty, even though removing an xattr has nothing to do with the directory's contents. Skip the directory-emptiness check for stream handles, matching how ksmbd_stream_fd() is already used elsewhere in this function. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: zero-initialize xattr_dos_attrib in smb2_update_xattrs()Gael Blivet1-1/+1
ndr_decode_dos_attr() only populates da->itime for version-4 DOS attribute xattrs; for version 3 it's skipped entirely (only da->create_time is set). smb2_update_xattrs() declared da without initializing it, so fp->itime = da.itime unconditionally copies whatever was on the kernel stack for any file carrying a version-3 xattr (e.g. written by an older client or server) -- uninitialized stack memory that can later be exposed to a client via QUERY_INFO. Zero-initialize da at declaration, matching the pattern fsctl_set_sparse() already uses in this same file. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: validate out_buf_len before FSCTL_CREATE_OR_GET_OBJECT_ID and ↵Gael Blivet1-0/+10
FSCTL_GET_REPARSE_POINT writes Both cases write a fixed-size response structure into rsp->Buffer without first checking that out_buf_len (the space smb2_ioctl() actually has available, computed by smb2_calc_max_out_buf_len() from the client's OutputBufferLength minus space already consumed earlier in a compound request) is large enough. Every comparable case in this same switch (FSCTL_SRV_ENUMERATE_SNAPSHOTS, FSCTL_GET_COMPRESSION, FSCTL_VALIDATE_NEGOTIATE_INFO, FSCTL_SRV_REQUEST_RESUME_KEY, FSCTL_SRV_COPYCHUNK) validates this first; these two don't. A client can send a compound SMB2 request where an earlier command in the same compound chain consumes most of work->response_buf, leaving smb2_calc_max_out_buf_len() only a few bytes of out_buf_len for a trailing FSCTL_CREATE_OR_GET_OBJECT_ID or FSCTL_GET_REPARSE_POINT. Both then unconditionally write their full fixed-size structure (64 bytes and 8 bytes respectively) at rsp->Buffer[0] regardless, overflowing past the actual remaining space in the response buffer. Add the same out_buf_len check used by every other fixed-size-response case in this function, before the write. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: fix durable handle v2 default timeout units (60 -> 60000)Gael Blivet1-1/+8
When a client's Durable Handle Request V2 sets Timeout=0 ("let the server choose"), fp->durable_timeout was set to 60. Every other use of this field is in milliseconds: DURABLE_HANDLE_MAX_TIMEOUT (300000) in smb2pdu.h, the nonzero branch immediately above (min_t(unsigned int, dh_info.timeout, DURABLE_HANDLE_MAX_TIMEOUT), where dh_info.timeout is the wire value and already milliseconds per spec), and the scavenger in vfs_cache.c, which adds it directly to jiffies_to_msecs(jiffies). 60 is off by 1000x: the handle becomes scavenger-eligible 60 milliseconds after close instead of 60 seconds. A client requesting Timeout=0 is relying entirely on the server's default to cover the gap between a dropped connection and its reconnect -- 60ms is not enough time for even a fast network blip to be detected and reconnected, so any real disruption loses the race and a subsequent DH2C reconnect fails with a durable-handle lookup miss instead of succeeding. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: route stream FileDispositionInformation through stream delete flagGael Blivet2-10/+48
ksmbd_fd_set_delete_pending()/ksmbd_fd_clear_delete_pending() to keep a stream's FileDispositionInformation from marking the whole file for deletion, but used the inode-wide S_DEL_ON_CLS_STREAM flag to do it -- the exact same problem class the commit was fixing, one level up. S_DEL_ON_CLS_STREAM lives on the shared ksmbd_inode, not on any specific stream handle. If a file has multiple stream handles open and one gets marked delete-pending via FileDispositionInformation, the flag can't record *which* stream should be deleted: whichever stream handle happens to close first (not necessarily the one that was actually marked) sees S_DEL_ON_CLS_STREAM set and has its xattr removed. Two clients (or two handles from the same client) touching different streams on the same file can end up deleting the wrong one. ksmbd_inode_pending_delete() has the same issue: it only checks S_DEL_PENDING, which is never set for a stream handle, so a client querying FileStandardInformation.DeletePending on a stream marked via this path would incorrectly see 0. Track this per-handle instead (stream_del_pending on struct ksmbd_file), matching the file itself rather than the shared inode. ksmbd_fd_set_delete_on_close() (the CREATE-time FILE_DELETE_ON_CLOSE option, a separate call path from FileDispositionInformation) still uses the inode-wide flag; __ksmbd_inode_close() now checks both, since either one should trigger removing the stream's xattr on close. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: handle empty QUERY_ALLOCATED_RANGES outputNamjae Jeon1-4/+12
FSCTL_QUERY_ALLOCATED_RANGES can be issued with a valid input buffer but without room for an output range. Do not reject the request before looking at the file layout. If the query would produce a range, return STATUS_BUFFER_TOO_SMALL. If it produces no ranges, return success with an empty output. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: allow FSCTL_SET_SPARSE without input bufferNamjae Jeon1-2/+8
FSCTL_SET_SPARSE without an input buffer sets a file sparse. Treat a zero-length input buffer as SetSparse=true and keep rejecting truncated non-empty buffers. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: reject FSCTL_SET_SPARSE on directoriesNamjae Jeon1-0/+5
FSCTL_SET_SPARSE applies to files. Return STATUS_INVALID_PARAMETER when a client sends it for a directory handle instead of setting the sparse file attribute on the directory. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: persist FSCTL_SET_SPARSE stateNamjae Jeon1-22/+18
Advertise FILE_SUPPORTS_SPARSE_FILES so clients can use FSCTL_SET_SPARSE. Do not mark regular files sparse just because sparse support is advertised; FILE_ATTRIBUTE_SPARSE_FILE should reflect the state set by FSCTL_SET_SPARSE. Persist the sparse attribute in the DOS attribute xattr regardless of the store dos attributes setting. Restore the sparse and compressed bits from that xattr when only those emulated attributes need to be preserved. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: preserve compression state across opensNamjae Jeon2-16/+12
The compression state can be emulated with the DOS attribute xattr when the backing filesystem cannot store it directly. Do not limit that state to shares with store dos attributes enabled, otherwise a file reopened through another handle can lose FILE_ATTRIBUTE_COMPRESSED in file information responses. Load only the compressed bit from the DOS attribute xattr when store dos attributes is disabled. Keep the normal DOS attribute behavior unchanged when it is enabled. Also avoid clearing an already restored compressed bit just because the backing filesystem does not report FS_COMPR_FL. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: preserve compression state in set basic infoNamjae Jeon1-2/+5
FILE_ATTRIBUTE_COMPRESSED is controlled by FSCTL_SET_COMPRESSION and should not be set directly through FileBasicInformation. Keep the existing compression state when updating basic attributes and ignore the compressed bit supplied by the client in the basic information request. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: support file compression attributesNamjae Jeon3-15/+91
Advertise file compression support and keep the compression state in the per-file DOS attributes when the backing filesystem cannot apply the compression flag directly. FSCTL_SET_COMPRESSION should still update the state returned by FSCTL_GET_COMPRESSION and file compression information in that case. When a new object is created under a compressed directory, inherit the compression attribute from the parent. If FILE_NO_COMPRESSION is specified, clear the compression state after creation and let it override inheritance for both files and directories. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: use MSG_EOR for async interim responseChenXiaoSong4-3/+14
Two kernel_sendmsg() calls can still use the same TCP skb if the first skb can take more data. This can happen when ksmbd sends two SMB2 responses very close to each other. Without MSG_EOR, TCP can append the next sendmsg data to the previous skb. Then STATUS_PENDING and the later response can be put into the same TCP skb. MSG_EOR marks the skb as end of record, so TCP will not collapse the next sendmsg data into it. Example: smbtorture //${server_ip}/export -U${username}%${password} smb2.compound_async.write_write Client request: Write Request Len:64 Off:0, File: compound_async_write_write; Write Request Len:64 Off:64 Before this patch, server responses: Write Response, File: compound_async_write_write Write Response SMB2, STATUS_PENDING, Write Response, MessageId 7 SMB2, Write Response, MessageId 7 After this patch: Write Response, File: compound_async_write_write Write Response, Error: STATUS_PENDING Write Response Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: introduce struct ksmbd_transport_writeChenXiaoSong4-19/+38
Put the arguments of ksmbd_transport_ops ->writev() into a struct. This makes the function call shorter and easier to read. Add __ksmbd_conn_write() for the common write code. A later patch will use it for another write helper. No functional change. Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17smb/server: send compound prefix before async pending responseChenXiaoSong1-0/+45
When the last request in a compound request becomes async, ksmbd sends a STATUS_PENDING response for it. But the responses for previous requests in the same compound request are still kept in the same response buffer. Send these previous responses first. Clear NextCommand for the last response in this part, sign it again if needed, and reset the iov state. After that, the async request sends STATUS_PENDING first, and sends the real response later. Both are separate responses. Example: smbtorture //${server_ip}/export -U${username}%${password} smb2.compound_async.write_write Client request: Write Request Len:64 Off:0, File: compound_async_write_write; Write Request Len:64 Off:64 Before this patch, STATUS_PENDING Write Response is the first of several responses: Write Response, Error: STATUS_PENDING Write Response, File: compound_async_write_write; Write Response But STATUS_PENDING Write Response should be in the middle of several responses, after this patch: Write Response, File: compound_async_write_write Write Response SMB2, STATUS_PENDING, Write Response, MessageId 7 SMB2, Write Response, MessageId 7 Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: distinguish unknown RPC pipe namesNamjae Jeon2-10/+7
Unknown RPC pipe names and malformed CREATE parameters both use -EINVAL. Mapping that errno to STATUS_OBJECT_NAME_NOT_FOUND therefore also hides invalid request parameters as a missing pipe. Return -ENOENT when RPC method lookup cannot find a supported pipe and map only that error to STATUS_OBJECT_NAME_NOT_FOUND. Preserve STATUS_INVALID_PARAMETER for -EINVAL returned by request validation. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: clear stale sparse attribute on non-sparse sharesGael Blivet1-0/+10
smb2_update_xattrs() copies the DOS SPARSE attribute bit verbatim from the stored xattr into the in-memory file attributes, without checking whether the share is currently advertising FILE_SUPPORTS_SPARSE_FILES. A file whose xattr has a stale SPARSE bit (set by a previous client, or from before the share was reconfigured) would keep reporting as sparse even after sparse-file support is turned off for the share. This matters for Time Machine: sparsebundle band files rely on accurate sparse-file status being reported, since macOS decides whether to issue FSCTL_SET_SPARSE based on it. Mask the bit out when the share doesn't currently advertise sparse-file support. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: quiet mdssvc RPC log spamGael Blivet1-0/+3
macOS routinely probes the mdssvc RPC pipe to check for Spotlight search support. __rpc_method() already falls through to returning 0 (unsupported) for it via the default case, but that path also logs "Unsupported RPC: mdssvc" via pr_err on every single probe -- which happens often enough during normal macOS browsing/backup activity to spam the kernel log. Add an explicit case that returns the same value without the log line; behavior is unchanged, this only removes noise for an expected, routine client behavior. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: return STATUS_OBJECT_NAME_NOT_FOUND for unknown IPC pipe namesGael Blivet1-1/+7
create_smb2_pipe() maps ksmbd_session_rpc_open() failing with -EINVAL (pipe name not recognized/supported) to STATUS_INVALID_PARAMETER. macOS Time Machine's backupd treats STATUS_INVALID_PARAMETER on a pipe open as a fatal error and aborts the backup immediately, whereas STATUS_OBJECT_NAME_NOT_FOUND is handled gracefully -- the client just treats that particular pipe as unavailable and continues. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: report actual xattr value length for stream EndOfFile/AllocationSizeGael Blivet1-12/+43
fp->stream.size holds the byte length of the mangled xattr *name* string (it's used as the attr_name_len argument when looking up the xattr), not the size of the stream's actual data. CREATE and every QUERY_INFO handler that reports EndOfFile/AllocationSize for a stream handle used fp->stream.size directly, so clients received a bogus size derived from the internal xattr key name length instead of the stream's real content length. Add ksmbd_stream_eof() to query the xattr's actual value length via ksmbd_vfs_casexattr_len(), and use it at every site that reports a stream handle's size: the CREATE response, get_file_standard_info(), get_file_all_info(), get_file_network_open_info(), and find_file_posix_info(). Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: route stream FileDispositionInformation through stream delete flagGael Blivet3-2/+36
set_file_disposition_info() calls ksmbd_set_inode_pending_delete() / ksmbd_clear_inode_pending_delete() unconditionally, which always sets S_DEL_PENDING on the whole inode (ci->m_flags), regardless of whether the handle being closed is a regular file or an alternate data stream. Requesting delete-pending on a single stream handle (e.g. deleting just an alternate data stream some clients keep alongside a file) would therefore incorrectly schedule deletion of the entire file's data, not just the stream. Add ksmbd_fd_set_delete_pending()/ksmbd_fd_clear_delete_pending(), following the same stream-vs-whole-file routing pattern already used by ksmbd_fd_set_delete_on_close() for the CREATE-time DeleteOnClose option, and switch set_file_disposition_info() to use them. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: fix off-by-one rejecting minimal COPYCHUNK query-limits requestGael Blivet1-1/+1
The FSCTL_COPYCHUNK/FSCTL_COPYCHUNK_WRITE input length check uses in_buf_len <= sizeof(struct copychunk_ioctl_req), which rejects a buffer that is exactly sizeof(struct copychunk_ioctl_req) bytes -- the minimal, valid request containing only the fixed header with ChunkCount=0 and no chunk entries, used by clients to query the server's copy limits before issuing a real copychunk. Since copychunk_ioctl_req ends in a flexible array member, the correct minimum is that the buffer covers the fixed header, so use offsetof(..., Chunks) with '<' instead of '<=' against sizeof(): same value, but the boundary case is now correctly accepted. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: handle AAPL stream copy length mismatchNamjae Jeon1-7/+37
macOS can reuse the main file's chunk list when issuing a copychunk request for alternate data streams. The requested source range can therefore exceed the length of the xattr-backed stream and currently fails with STATUS_INVALID_VIEW_SIZE. For AAPL connections copying between two streams, limit the actual copy to the available source data while reporting the requested chunk length as written. Keep the source range validation unchanged for non-AAPL connections and requests involving a regular file. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: support copychunk for alternate data streamsNamjae Jeon1-30/+50
Copychunk rejects requests when either handle refers to an alternate data stream. These streams are stored in extended attributes and cannot be passed directly to vfs_copy_file_range(). Use the bounded buffered copy path when a source or destination is a stream. Obtain the source length from the stream extended attribute and perform I/O through the existing stream-aware read and write helpers. Keep vfs_copy_file_range() and its fallback for regular files only. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: preserve access denied status for copychunkNamjae Jeon1-1/+1
The copychunk error mapping handles -EACCES in an independent if statement. The following error chain therefore reaches its final else clause and overwrites STATUS_ACCESS_DENIED with STATUS_UNEXPECTED_IO_ERROR. Join the -EACCES check to the remaining error chain so an access failure is returned as STATUS_ACCESS_DENIED. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: preserve data during overlapping copy chunkNamjae Jeon1-10/+66
Copying an overlapping range within the same file through do_splice_direct() can overwrite source data that has not yet been read. This corrupts the destination when the target range starts inside and after the source range. Handle overlapping ranges with a bounded temporary buffer. Copy from the end when the destination follows the source and from the beginning otherwise, providing memmove semantics without allocating the entire copy length. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: return complete resume key responseNamjae Jeon1-1/+1
The FSCTL_SRV_REQUEST_RESUME_KEY response contains a mandatory four-byte context field after ContextLength. Defining the context as a flexible array excludes it from sizeof(struct resume_key_ioctl_rsp), so ksmbd sends only 28 bytes instead of the required 32 bytes. The truncated response cannot be decoded and results in an NDR buffer size error. Define the reserved context as a fixed four-byte field. This makes the response size match the wire format and ensures the field is zeroed and included in OutputCount. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: support empty snapshot enumerationNamjae Jeon3-0/+32
FSCTL_SRV_ENUM_SNAPS is currently unimplemented, causing clients to treat shadow-copy enumeration as unsupported even when the share simply has no snapshots. Handle the count-only SRV_SNAPSHOT_ARRAY request and return a valid empty snapshot list after validating the file handle and minimum output buffer size. Report a two-byte empty UTF-16 MULTI_SZ array and zero snapshot counts. This allows smb2.ioctl.shadow_copy to run without a snapshot backend. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: require read control for security informationNamjae Jeon1-0/+6
SMB2 QUERY_INFO security requests currently return owner, group, and DACL information without checking the access granted to the opened handle. A handle opened with only SYNCHRONIZE or READ_ATTRIBUTES can consequently read the security descriptor. Require READ_CONTROL when OWNER_SECINFO, GROUP_SECINFO, or DACL_SECINFO is requested and return STATUS_ACCESS_DENIED otherwise. This fixes smb2.getinfo.getinfo_access. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: support normalized name informationNamjae Jeon1-2/+79
FILE_NORMALIZED_NAME_INFORMATION is not handled and is returned as STATUS_INVALID_INFO_CLASS. SMB 3.1.1 clients use this information class to obtain the share-relative path with the on-disk name casing. Build the normalized path from the opened dentry, remove the leading share-relative separator, and recover the canonical named-stream casing from its backing xattr. Return an empty name for the share root and STATUS_NOT_SUPPORTED for dialects older than SMB 3.1.1. Also distinguish a named $DATA stream on a directory from the unnamed data stream so that directory:stream:$DATA can be opened normally. This fixes smb2.getinfo.normalized. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: return buffer too small for short security queriesNamjae Jeon1-0/+6
SMB2 QUERY_INFO security requests with an output buffer too small for the self-relative security descriptor header can fall through descriptor construction and be reported as STATUS_INVALID_INFO_CLASS. After validating the file handle, reject buffers shorter than struct smb_ntsd with STATUS_BUFFER_TOO_SMALL before building the descriptor. This fixes smb2.getinfo.qsec_buffercheck. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: fix partial file information responsesNamjae Jeon1-11/+20
Variable-length file information handlers use the client output length while constructing the response. FILE_ALL_INFORMATION can consequently return -EINVAL before the common buffer check, while stream information can stop building the complete result too early. Build the complete response within the available server response buffer and apply the client output length only when selecting the final status and transmitted length. Use the protocol-defined fixed sizes for all, alternate-name, and stream information to distinguish STATUS_INFO_LENGTH_MISMATCH from STATUS_BUFFER_OVERFLOW. This fixes smb2.getinfo.qfile_buffercheck. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: Do not skip lock checks for single-byte rangesGuangshuo Li1-3/+0
check_lock_range() uses inclusive ranges. Its callers pass the end offset as start + length - 1, so start == end represents a valid single-byte range rather than an empty range. The start == end shortcut therefore skips mandatory byte-range lock checks for one-byte reads, writes, copychunk operations and one-byte truncate ranges. A conflicting lock covering that byte is not checked and the operation is allowed to proceed. Remove the shortcut. The truncate size == inode->i_size case is already handled by only calling check_lock_range() when the new size differs from the current file size. Fixes: 5d510ac31626 ("ksmbd: skip lock-range check on equal size to avoid size==0 underflow") Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: return buffer overflow for partial filesystem infoNamjae Jeon1-1/+25
The query-info buffer check returns STATUS_INFO_LENGTH_MISMATCH for every output buffer smaller than the complete response. Variable-length filesystem information instead requires STATUS_BUFFER_OVERFLOW when the fixed portion fits but the complete data does not. Pass the fixed size for each filesystem information class to the buffer checker. Keep INFO_LENGTH_MISMATCH for buffers below that size, and return BUFFER_OVERFLOW with a response truncated to the requested length for larger partial buffers. This fixes smb2.getinfo.qfs_buffercheck. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: allow I/O on directory named streamsNamjae Jeon1-2/+3
Named streams are stored as extended attributes on the base inode. The VFS read and write helpers reject directory inodes before or together with checking whether the handle represents a stream. Permit read and write operations when a directory-backed handle is a named stream. Continue rejecting direct I/O on ordinary directory handles. This fixes creation of the directory stream in smb2.getinfo.complex. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: protect private extended attributesNamjae Jeon1-6/+22
SMB clients can currently create an EA named NTACL because SMB EAs are mapped into the user namespace while the ksmbd security descriptor is stored as security.NTACL. Allowing the reserved logical name makes the server-private ACL metadata appear writable through the SMB EA API. Reject NTACL, DOSATTRIB, and DosStream-prefixed EA names without regard to case. Filter the same private names from EA query results so stale or externally-created user namespace attributes cannot be exposed. This fixes smb2.ea.acl_xattr when acl_xattr_name is configured as NTACL. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: reject delete-on-close for read-only filesNamjae Jeon1-3/+32
DELETE_ON_CLOSE is currently accepted for files carrying the read-only DOS attribute. The server consequently creates or opens the file and marks it for deletion instead of returning STATUS_CANNOT_DELETE. Reject creation of a new read-only file with DELETE_ON_CLOSE. For an existing file, load the stored DOS attributes before accepting the create option. Also reject FileDispositionInformation when the opened file has the read-only attribute. Preserve the explicit STATUS_CANNOT_DELETE value while unwinding the CREATE request. This fixes smb2.delete-on-close-perms.READONLY. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: honor owner rights ACEs in maximal accessNamjae Jeon2-3/+26
The SMB2 create maximal-access context is currently calculated from POSIX mode bits when the client does not request MAXIMUM_ALLOWED. This overwrites the access granted by a stored Windows DACL. Calculate the create-context result with the DACL permission checker. Recognize the S-1-3-4 Owner Rights SID as applying to the object owner and process its allow and deny ACEs in ACL order. When an Owner Rights ACE is present, do not add the owner implicit READ_CONTROL and WRITE_DAC rights. The Owner Rights ACE replaces those implicit grants as required by Windows access-check semantics. Without an Owner Rights ACE, preserve the existing implicit owner grants, including FILE_READ_ATTRIBUTES and DELETE. This fixes smb2.acls.OWNER-RIGHTS and its deny variants without regressing smb2.acls.GENERIC. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: support access-based directory enumerationNamjae Jeon4-5/+36
SMB shares can advertise access-based directory enumeration. ksmbd does not currently provide a share option or filter inaccessible directory entries. Add a hide-unreadable share flag and advertise SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM when it is enabled. During QUERY_DIRECTORY, omit entries unless the connected user has FILE_READ_DATA, FILE_READ_EA, and FILE_READ_ATTRIBUTES access according to the Windows ACL. Keep the existing implicit access allowances for normal CREATE permission checks while using strict access-mask matching for directory enumeration. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: fix maximum allowed access checksNamjae Jeon3-33/+61
The DACL permission check looks for an ACE matching the current user and falls back to the Everyone ACE. It does not consider an Authenticated Users ACE, even though an authenticated session is a member of that well-known group. As a result, opening a file whose access is granted through S-1-5-11 can incorrectly fail with STATUS_ACCESS_DENIED. Treat an Authenticated Users ACE as a fallback entry alongside Everyone. The maximal access calculation also combines access masks from every ACE, regardless of whether its SID applies to the current user. This can grant rights belonging to an unrelated principal. Process only ACEs applying to the user, Everyone, or Authenticated Users, and accumulate allowed and denied masks in ACL order. Preserve explicitly requested access bits so they are validated against the resulting maximal mask. When ACCESS_SYSTEM_SECURITY is denied, report STATUS_PRIVILEGE_NOT_HELD instead of the generic STATUS_ACCESS_DENIED. Access to the system ACL requires a security privilege that ksmbd does not grant. For regular files, include FILE_EXECUTE in maximal access when the client requested GENERIC_EXECUTE and the DACL grants the complete file-read set. Keep a direct FILE_EXECUTE request subject to the explicit DACL bit. This matches the POSIX file ACL mapping without broadening specific execute requests. Do not replace rights from an applicable NT ACE with a POSIX ACL entry. The POSIX ACL is only a fallback when no user, Everyone, or Authenticated Users ACE applies; otherwise it can incorrectly broaden the stored DACL. This fixes smb2.maximum_allowed.maximum_allowed. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: validate SMB2 write offsetsNamjae Jeon1-2/+20
An SMB2 WRITE request with a negative offset returns -EINVAL directly from smb2_write(). This bypasses the common error response path, leaving the client waiting until the request times out. ksmbd also allows nonempty writes at or beyond MAXFILESIZE as defined by [MS-FSA]. Writes beyond the limit must fail with STATUS_INVALID_PARAMETER. Writes ending at the limit fail with STATUS_DISK_FULL, while a zero-length write remains valid. Route negative offsets through the common error path and validate the end offset of nonempty writes against MAXFILESIZE. This fixes smb2.rw.invalid. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17ksmbd: reject SMB3.1.1 binding with mismatched cipherNamjae Jeon1-0/+15
SMB3.1.1 multichannel connections belonging to the same session must use the same negotiated encryption cipher. ksmbd validates the dialect and client GUID during session binding, but does not compare the cipher negotiated by the new connection with the cipher used by the existing session channels. This allows a channel negotiated with AES-128-CCM to bind to a session using AES-128-GCM. Compare the new connection's cipher with an existing session channel and return STATUS_INVALID_PARAMETER when they differ. This fixes smb2.session.bind_negative_smb3encGtoCs. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-17net: ionic: Fetch RCQ sign bit from firmwareAbhijit Gangurde1-1/+5
Read the rcq_sign_bit from the RDMA LIF identity reported by firmware. Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>