summaryrefslogtreecommitdiff
path: root/fs/smb/client
AgeCommit message (Collapse)AuthorFilesLines
9 daystreewide: refresh kmalloc_obj() conversionsKees Cook3-3/+3
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
12 daysMerge tag 'cifs-fixes-7.3-rc2' of https://git.manguebit.org/linuxLinus Torvalds5-56/+231
Pull smb client fixes from Paulo Alcantara: - Fixes for fallocate range operations (insert, collapse, zero, punch hole) The insert range implementation copied overlapping chunks in the wrong direction, corrupting file data on every server except Windows. Several related issues in the same area are also addressed — stale page cache and FS-Cache readback, an integer truncation on large files, missing RLIMIT_FSIZE validation and missing sparse file marking. - Data corruption fixes in the O_TRUNC open path: one where i_size was zeroed before the server confirmed the truncate and another where the lack of locking allowed concurrent buffered writes to be silently discarded - Heap overflow fixes in legacy SMB1 paths: one in extended attribute writes and one in POSIX ACL handling, both exploitable via unprivileged setxattr(2) - Fix for multiuser mount with krb5 failing because the username option was not propagated to new per-user connections - Fix for split debug message in __release_mid() after a printk conversion * tag 'cifs-fixes-7.3-rc2' of https://git.manguebit.org/linux: smb: client: reject SetEA requests that do not fit the request buffer smb: client: fix data corruption with concurrent writes and O_TRUNC cifs: don't update i_size in cifs_do_truncate without a cached handle smb: client: fix heap overflow in cifs_do_set_acl() smb: client: fix multiuser mount with krb5 smb: client: transport: Fix debug printing in __release_mid() smb/client: invalidate fscache for fallocate range operations smb/client: fix stale page cache in insert/collapse range smb/client: fix integer truncation in collapse range smb/client: fix data corruption in emulated insert range smb/client: mark file sparse before emulating insert range smb/client: validate new EOF for zero range smb/client: validate new EOF for insert range cifs: add revalidation on FSCTL failure in smb2_duplicate_extents()
13 dayssmb: client: reject SetEA requests that do not fit the request bufferYunpeng Tian1-1/+10
CIFSSMBSetEA() copies the caller's extended attribute value into the SMB request buffer without checking that it fits. The requirement is stated in the source but was never implemented: /*BB add length check to see if it would fit in negotiated SMB buffer size BB */ /* if (ea_value_len > buffer_size - 512 (enough for header)) */ if (ea_value_len) memcpy(parm_data->list.name + name_len + 1, ea_value, ea_value_len); The only bound applied on the way in is in cifs_xattr_set(): #define MAX_EA_VALUE_SIZE CIFSMaxBufSize ... if (size > MAX_EA_VALUE_SIZE) CIFSMaxBufSize is the full payload capacity of the buffer, so a value of exactly that size leaves no room for the SMB header, the TRANS2 parameter block, the fealist header and the EA name that are written ahead of it in the same object. SendReceive() already enforces the correct limit on this very length: if (in_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) but it is called after the copy has taken place. An unprivileged setxattr(2) on an SMB1 mount with a 250-byte name and a 16384-byte value writes 16384 bytes starting 345 bytes into a 16588-byte cifs_request object, ending 141 bytes past it: BUG: KASAN: slab-out-of-bounds in CIFSSMBSetEA+0xabc/0xde0 Write of size 16384 at addr ffff888003aa0159 by task init/68 __asan_memcpy+0x3c/0x60 CIFSSMBSetEA+0xabc/0xde0 cifs_xattr_set+0xd3a/0xff0 __vfs_setxattr+0x13e/0x1a0 The buggy address is located 345 bytes inside of allocated 16588-byte region Apply SendReceive()'s limit to the assembled request before the copy rather than after it, and widen the byte counters so the sum cannot wrap before it is tested. byte_count is also tested against U16_MAX, because it is stored in the 16-bit pSMB->ByteCount. That becomes reachable when CIFSMaxBufSize is raised at module load, where it may be set as high as 1024*127: with a 5-byte EA name and a 65521-byte value, count is exactly U16_MAX while byte_count is 65556, and cpu_to_le16() would truncate it to 20 and transmit a frame whose ByteCount does not match its length. Testing byte_count covers count as well, since byte_count is the larger of the two and count's only 16-bit consumer is written after this point. check_add_overflow() is evaluated first so that total_len is assigned before it is reported. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Yunpeng Tian <shionthanatos@gmail.com> Reported-by: Mingda Zhang <npczmd@qq.com> Reported-by: Gongming Wang <gmwgg05@gmail.com> Reported-by: Qinrun Dai <jupmouse@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Yunpeng Tian <shionthanatos@gmail.com> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
13 dayssmb: client: fix data corruption with concurrent writes and O_TRUNCPaulo Alcantara1-10/+18
cifs_do_truncate() flushes dirty pages with filemap_write_and_wait() and truncates the file on the server, but in the old code both operations ran without holding i_rwsem or invalidate_lock. A concurrent buffered write via netfs_perform_write() -- which only needs i_rwsem shared -- could dirty new pages after the flush but before the local truncation, and those pages would be silently discarded by cifs_setsize() -> truncate_pagecache(). Fix by acquiring inode_lock (exclusive i_rwsem) and filemap_invalidate_lock at the top of cifs_do_truncate(), so the entire flush-truncate-resize sequence is atomic with respect to: - buffered writes (blocked by exclusive i_rwsem, since netfs_start_io_write takes i_rwsem shared), - read page faults (blocked by exclusive invalidate_lock, since filemap_fault takes it shared), - writeback collection (blocked by netfs_wb_begin/netfs_wb_end around the server truncate and local resize, since netfs_writepages also acquires the wb lock). Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") Signed-off-by: Paulo Alcantara <pc@manguebit.org> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com> Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Tom Talpey <tom@talpey.com> Cc: Bharath SM <bharathsm@microsoft.com> Cc: stable@vger.kernel.org
2026-08-30cifs: don't update i_size in cifs_do_truncate without a cached handleFrank Sorenson1-4/+20
If find_writable_file() returns null, cifs_file_flush will return 0 without issuing set_file_size, and the outer 'if (!rc)' block will set i_size to 0 before telling the server to truncate. If the cifs_open() then fails, the inode will have size 0, while the server file is unchanged. Move the netfs_resize_file() and cifs_setsize() into the 'if (cfile)', so they only run after a successful set_file_size. In the no-handle else branch, evict stale pages with truncate_inode_pages before the O_TRUNC open to dispose of old cache pages, and let the open response set the i_size. Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb: client: fix heap overflow in cifs_do_set_acl()Frank Sorenson1-2/+11
cifs_set_acl() validates ACL size using posix_acl_xattr_size(): 4 + (count * 8) // 4-byte header + 8 bytes per ACE cifs_do_set_acl() then calls posix_acl_to_cifs() to write the CIFS wire format into the same buffer: 6 + (count * 10) // 6-byte header + 10 bytes per ACE An ACL that passes the xattr-based check in cifs_set_acl() can overflow the heap when posix_acl_to_cifs() writes the larger CIFS format. Validate the CIFS format size against the remaining buffer space and USHRT_MAX before converting--data_count is __u16, so sizes above USHRT_MAX truncate the on-wire packet length, causing the server to apply a partial ACL. Replace MaxDataCount = 1000 with min(CIFSMaxBufSize, USHRT_MAX). Fixes: dc1af4c4b4721 ("cifs: implement set acl method") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb: client: fix multiuser mount with krb5Paulo Alcantara1-5/+16
Customer reported that they could no longer mount their SMB shares with multiuser mount option and krb5. Turned out that the client wasn't duplicating username option when creating multiuser connections, therefore failing to retrieve credentials as cifs.upcall(8) couldn't find them in keytab. Fix this by duplicating username option (if set) from original fs context before creating multiuser connections with krb5. Reproducer: ``` $ ktutil ktutil: add_entry -password -p testuser -k 1 -e aes256-cts Password for testuser@ZELDA.TEST: ktutil: write_kt /etc/krb5.keytab ktutil: quit $ klist -ke Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- ---------------------------------------------------------------- 1 testuser@ZELDA.TEST (aes256-cts-hmac-sha1-96) $ mount.cifs //w22-root2/scratch /mnt/1 -o \ uid=1000,sec=krb5,username=testuser@ZELDA.TEST,multiuser mount error(13): Permission denied Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg) ``` Reported-by: Jacob Shivers <jshivers@redhat.com> Fixes: 12b4c5d98cd7 ("smb: client: fix krb5 mount with username option") Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com> Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Tom Talpey <tom@talpey.com> Cc: Bharath SM <bharathsm@microsoft.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Cc: stable@vger.kernel.org Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb: client: transport: Fix debug printing in __release_mid()Andy Shevchenko1-6/+5
Long time ago during upgrading printk():s to the respective pr_<level>() calls one misconversion happened and nobody has noticed that. So, previously printk(KERN_DEBUG) + printk() worked as one long debug print since the trailing '\n' is only present in the followup printk() format string. The culprit change missed that and split the message to two on the different levels. Restore the original behaviour to make users be less confused in the most likely never happen cases of partially getting that message. Fixes: 0b456f04bcdf ("cifs: convert printk(LEVEL...) to pr_<level>") Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: invalidate fscache for fallocate range operationsHuiwen He1-0/+7
smb3_zero_range(), smb3_punch_hole(), smb3_insert_range(), and smb3_collapse_range() modify file contents through server-side range operations. These operations discard the affected page cache, but leave the FS-Cache cookie valid, so a later read may return data cached before the range operation. Fix this by invalidating FS-Cache after outstanding I/O has completed and before modifying the file on the server. Run the following as root on a CIFS mount with fsc enabled and an active CacheFiles backend: bash -c ' MNT=/mnt/cifs FILE="$MNT/repro" # Generate four 1 MiB random blocks: [A][B][C][D]. dd if=/dev/urandom of=/tmp/src bs=1M count=4 status=none # Expected contents after zeroing B: [A][zero][C][D]. cp /tmp/src /tmp/expected dd if=/dev/zero of=/tmp/expected bs=1M seek=1 count=1 \ conv=notrunc status=none cp /tmp/src "$FILE" # Populate FS-Cache, then discard the page cache. sync echo 1 > /proc/sys/vm/drop_caches cat "$FILE" > /dev/null sync echo 1 > /proc/sys/vm/drop_caches fallocate --zero-range -o 1M -l 1M "$FILE" if cmp -s /tmp/expected "$FILE"; then echo "readback: OK" else echo "readback: STALE DATA" fi ' Before this change, the readback differs from /tmp/expected: readback: STALE DATA After this change, it matches: readback: OK Fixes: 30175628bf7f ("[SMB3] Enable fallocate -z support for SMB3 mounts") Fixes: 31742c5a3317 ("enable fallocate punch hole ("fallocate -p") for SMB3") Fixes: 5476b5dd82c8 ("cifs: add support for FALLOC_FL_COLLAPSE_RANGE") Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Suggested-by: Namjae Jeon <linkinjeon@kernel.org> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: fix stale page cache in insert/collapse rangeHuiwen He1-5/+18
smb3_insert_range() and smb3_collapse_range() use truncate_pagecache_range() to invalidate the affected page cache. However, if off or old_eof is not page-aligned, the boundary pages are only partially zeroed and remain uptodate. As a result, the client may return stale data after a successful insert/collapse range operation. For example, with 4K pages: page 0 page 1 page 2 0------4K 4K------8K 8K------12K ^ ^ off=2K old_eof=10K Page 1 is removed from the page cache, while the boundary pages are only partially zeroed. After COPYCHUNK moves the data on the server, these cached pages may still return stale data. This can be reproduced on a CIFS mount: bash -c ' FILE=/mnt/scratch/repro # Use a 6 KiB file so EOF is not page-aligned. dd if=/dev/urandom of=/tmp/src bs=1K count=6 status=none # Expected: a 4 KiB hole followed by the original data. rm -f /tmp/expected truncate -s 4K /tmp/expected cat /tmp/src >> /tmp/expected cp /tmp/src "$FILE" # Prime the page cache before moving data on the server. cat "$FILE" > /dev/null fallocate --insert-range -o 0 -l 4K "$FILE" if cmp -s /tmp/expected "$FILE"; then echo "readback: OK" else echo "readback: STALE DATA" fi ' Fix this by writing back dirty data and discarding the page cache from the start of the page containing off to EOF before moving data on the server. Fixes: 9c8b7a293f50 ("smb3: fix temporary data corruption in insert range") Fixes: fa30a81f255a ("smb3: fix temporary data corruption in collapse range") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: fix integer truncation in collapse rangeHuiwen He1-2/+2
smb3_collapse_range() stores the ssize_t return value of smb2_copychunk_range() in an int. A successful copy larger than INT_MAX is truncated to a negative value and treated as an error. Reproducer: MNT=/mnt/scratch truncate -s 2056M "$MNT/file" fallocate --collapse-range -o 1M -l 1M "$MNT/file" Fix this by using __smb2_copychunk_range(), which reports success as zero instead of returning the copied byte count. Before this change, the reproducer fails with: fallocate: fallocate failed: Success and the file size remains unchanged at 2056 MiB. After this change, the reproducer succeeds and the file size becomes the expected 2055 MiB. Fixes: 5476b5dd82c8 ("cifs: add support for FALLOC_FL_COLLAPSE_RANGE") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: fix data corruption in emulated insert rangeHuiwen He1-26/+106
smb3_insert_range() shifts [off, EOF) right with COPYCHUNK, copying from low to high offsets. When the ranges overlap, the copy can overwrite source data that has not yet been copied. For a 1 MiB insert at offset 0: offset: 0 1M 2M 3M 4M 5M before: | A | B | C | D | expected: | hole | A | B | C | D | current: | hole | A | A | A | A | (corrupted) Let x be the insertion offset, L the total length to move, delta the insert length, and C the normal chunk size allowed by the server. Insert range maps [x, x + L) -> [x + delta, x + delta + L). When delta >= L, the complete source and target ranges are disjoint, so the normal copy order and chunk size are safe: offset: 0 4 8 12 16 20 24 28 32 source: [--S0--][--S1--][--S2--][--S3--] target: [--T0--][--T1--][--T2--][--T3--] When delta < L, the complete source and target ranges overlap, so the copy must proceed from EOF backwards. There are two subcases. If delta >= C, each corresponding source and target chunk is disjoint. The 1 MiB example has L = 4 MiB and delta = C = 1 MiB: offset: 0 1M 2M 3M 4M 5M source: [--S0--][--S1--][--S2--][--S3--] target: [--T0--][--T1--][--T2--][--T3--] Copying S0 from [0, 1M) to [1M, 2M) overwrites S1 before it is copied. Processing chunks from EOF backwards prevents this inter-chunk overwrite. If delta < C, the source and target ranges of a normal chunk also overlap. For example, with L = 16, delta = 2 and C = 4: offset: 0 2 4 6 8 10 12 14 16 18 source: [--S0--][--S1--][--S2--][--S3--] target: [--T0--][--T1--][--T2--][--T3--] Here S0 and T0 overlap over [2,4), S1 and T1 over [6,8), and so on. Backward ordering cannot control how the server copies bytes inside one descriptor, so the chunk size must be limited to delta. Fix this by copying overlapping right shifts from EOF backwards. Limit the chunk size to delta when delta < C so that each chunk's source and target ranges do not overlap. Using larger chunks would require a way to identify servers that safely handle overlapping COPYCHUNK descriptors. Therefore: delta >= L: keep the normal copy order and chunk size delta < L: delta >= C: copy backwards and keep the normal chunk size delta < C: copy backwards and limit the chunk size to delta Only the delta < C subcase requires reducing the chunk size for data integrity. Reproducer: bash -c ' MNT=/mnt/scratch # Generate four 1 MiB random blocks: [A][B][C][D]. dd if=/dev/urandom of=/tmp/src bs=1M count=4 status=none # With C = 1 MiB, test delta = C and delta < C. for delta in 1M 1K; do truncate -s 0 /tmp/expected truncate -s "$delta" /tmp/expected cat /tmp/src >> /tmp/expected cp /tmp/src "$MNT/file" fallocate --insert-range -o 0 -l "$delta" "$MNT/file" if cmp -s /tmp/expected "$MNT/file"; then echo "delta=$delta: OK" else echo "delta=$delta: CORRUPTED" fi done ' The corruption reproduces with Samba and ksmbd, while Windows handles the overlapping COPYCHUNK ranges safely. The 1 MiB case tests delta >= C, while the 1 KiB case tests delta < C. Before this change, the reproducer reports: delta=1M: CORRUPTED delta=1K: CORRUPTED After this change, it passes against both ksmbd and Samba: delta=1M: OK delta=1K: OK Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: mark file sparse before emulating insert rangeHuiwen He1-0/+5
The SMB client emulates FALLOC_FL_INSERT_RANGE with SET_EOF, COPYCHUNK and SET_ZERO_DATA. SET_ZERO_DATA creates a hole only when the file is sparse. On a non-sparse file, it clears the inserted range but leaves its blocks allocated, causing the extent count check in xfstests generic/064 to fail. Fix this by marking the file sparse before modifying it. This patch produces the expected sparse extents in xfstests generic/064 only when the server-reported block size is compatible with the server's deallocation granularity. For ksmbd, the reported block size follows the backing filesystem, and the test passes. For Samba, the test passes with a block size matching the backend granularity, for example, 4 KiB on Btrfs, but not with the default 1 KiB value. For Windows Server 2022, 4 KiB inserts do not generate holes, while aligned inserts of 64 KiB or larger do. Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: validate new EOF for zero rangeHuiwen He1-1/+8
When FALLOC_FL_ZERO_RANGE is used without FALLOC_FL_KEEP_SIZE, smb3_zero_range() may extend EOF without checking RLIMIT_FSIZE, allowing the file to grow beyond the caller's file-size limit. Fix this by calling inode_newsize_ok() before sending the zero-range request when the operation would extend EOF. Reproducer, using a file on a CIFS mount: bash -c ' FILE=/mnt/cifs/repro trap "" SIGXFSZ ulimit -f 3072 truncate -s 2M "$FILE" fallocate --zero-range -o 0 -l 4M "$FILE" echo "fallocate rc=$?" stat -c "file size=%s" "$FILE" ' Before this change, the operation succeeds despite the 3 MiB limit: fallocate rc=0 file size=4194304 After this change, fallocate fails and leaves the file at 2 MiB. Fixes: 72c419d9b073 ("cifs: fix smb3_zero_range so it can expand the file-size when required") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-30smb/client: validate new EOF for insert rangeHuiwen He1-2/+10
smb3_insert_range() does not check if the new file size (i_size + len) is valid. This allows FALLOC_FL_INSERT_RANGE to bypass RLIMIT_FSIZE, exceed s_maxbytes, or produce a size outside the loff_t range. Use check_add_overflow() to calculate the new EOF. Validate it with inode_newsize_ok() before modifying the file. Reproducer, using a file on a CIFS mount: bash -c ' FILE=/mnt/cifs/repro trap "" SIGXFSZ ulimit -f 3072 # RLIMIT_FSIZE = 3 MiB # A regular write is stopped at 3 MiB. dd if=/dev/zero of="$FILE" bs=1M count=4 status=none stat -c "size after write: %s" "$FILE" # Insert 2 MiB into a 2 MiB file. truncate -s 2M "$FILE" fallocate -i -o 0 -l 2M "$FILE" stat -c "size after insert: %s" "$FILE" ' Before this change, the regular write stops at the 3 MiB limit, but insert range grows the file to 4 MiB: dd: error writing '/mnt/cifs/repro': File too large size after write: 3145728 size after insert: 4194304 After this change, insert range also fails at the limit and leaves the 2 MiB file unchanged: dd: error writing '/mnt/cifs/repro': File too large size after write: 3145728 fallocate: fallocate failed: File too large size after insert: 2097152 Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-27Merge tag 'mm-stable-2026-08-26-15-22' of ↵Linus Torvalds1-26/+39
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Pull more MM updates from Andrew Morton: - "mm/rmap: index MAP_PRIVATE file-backed folios by anonymous pgoff" (Lorenzo Stoakes) Index MAP_PRIVATE file-backed folios by their anonymous page offset to resolve confusion around reverse mapping for zeroed and CoW'd file-backed memory. Use this new VMA anonymous page offset tracking to eliminate index conflicts and lay the foundation for scalable CoW performance improvements. - "promote mapped executable folios after first usage for MGLRU" (Baolin Wang) Make MGLRU's protection of mapped executable file folios more reliable. Follow the classical LRU's logic, promoting mapped executable file folios after their first usage to give executable code a better chance to stay in memory and improve workload performance. - "mm: vmscan: fix node reclaim ignoring swappiness parameter" (Ridong Chen) Fix per-node proactive reclaim interface's ignoring the swappiness parameter when CONFIG_MEMCG is disabled by consolidating sc_swappiness() into a single function that checks proactive_swappiness regardless of kernel configuration. - "mm/vmscan: reduce lru_lock contention via vmstat-derived scan-balance cost" (Usama Arif) Reduce lru_lock contention in the reclaim path by deriving scan-balance costs from vmstat counters rather than lock-acquired producer updates. Read and decay these cost signals on the reclaim side under a dedicated per-lruvec lock, reducing total LRU lock wait time by over 60% without impacting scan throughput. - "zram: fix zram issues reported by sashiko" (Sergey Senozhatsky) Fix two low-risk zram bugs which Sashiko spotted in drive-by review. - "Honor XA_FLAGS_ACCOUNT in xas_split_alloc() and charge to folio's memcg" (Zi Yan) Fix xas_split_alloc() by enabling target folio memcg charging during splits and adding the missing __GFP_ACCOUNT flag for proper XArray node memory accounting. - "selftests/mm: use pattern matching in .gitignore" (Pratyush Mallick) Replace hardcoded binary names in selftests/mm/.gitignore with a generic pattern-matching rule to automatically ignore generated test files and avoid manual updates when adding new tests. - "mm/page_ext: remove pgdat_page_ext_init()" (Sang-Heon Jeon) Make the incompatibility between FLATMEM and NUMA explicit in mm/Kconfig and remove the unused pgdat_page_ext_init() function. - "zram: fix zstd error paths and add parameter validation" (Haoqin Huang) Clean up zram compression backends by removing redundant error cleanup, adding parameter and dictionary validation, auto-prefixing algorithm error logs, and resetting parameters prior to reinitialization. - "zram: fix stale scan bounds after reinitialization" (Longlong Xia) Prevent out-of-bounds slot accesses during concurrent zram resets by moving table scan bound calculations under dev_lock in writeback_store() and read_block_state(). - "add anon mTHP collapse test cases" (Baolin Wang) Extend selftests helper functions to support arbitrary page orders and add new test cases and options for mTHP collapse in khugepaged. - "selftests/mm: Handle unsupported and transient test conditions" (Muhammad Usama Anjum) Update MM selftests to report a SKIP status instead of a failure when required kernel or filesystem features are unsupported, while adding retry logic for transient page migration errors. - "mm/zswap: Fixes and improves the zswap shrink" (Hao Jia) Fix the missing zswap global shrinker when CONFIG_MEMCG is disabled and extend shrink_memcg() to support batch writeback for improved writeback efficiency. - "alloc_tag: introduce IOCTL-based filtering for MAP" (Suren Baghdasaryan) Introduce an IOCTL-based binary interface for memory allocation profiling that enables kernel-side filtering before per-CPU counter aggregation. This eliminates the text-parsing overhead of /proc/allocinfo and provides up to a 20x speedup by transferring only filtered allocation data to userspace. - "better block swap batching and a different take on swap_ops v5" (Christoph Hellwig) Refactor block swap I/O to use swap_iocb for batching instead of single-bio requests and rebase the swap_ops interface, achieving faster swap throughput during kernel builds. - "mm: kmemleak: reduce transient false positives by confirming leaks" (Catalin Marinas) Reduce false-positive kmemleak reports by combining two kmemleak enhancements that add a second confirmation scan and a configurable minimum unreferenced scan count module parameter. - "mm: kmemleak: default min_unref_scans to 2 for verbose kernels" (Breno Leitao) Auto-scanning kernels can generate false-positive memory leak reports on single scans, so this patch defaults min_unref_scans to 2 when CONFIG_DEBUG_KMEMLEAK_VERBOSE is enabled to require a second confirming scan. - "swap_ops updates" (Christoph Hellwig) Batching I/O for synchronous swap devices causes performance regressions and filesystem-based swap suffers from double-indirection overhead. This series resolves both issues by reintroducing per-folio writes for synchronous swap and allowing filesystems to directly export their own swap_ops. - "mm/khugepaged: several cleanups" (Nico Pache) khugepaged accumulated redundant state-checking patterns and outdated comments following mTHP integration. Introduce dedicated helpers for PTE validation and event counting while refreshing the internal documentation. - "maple_tree: lock checking and clean ups" (Liam Howlett) Syzbot reports incorrectly blame memory management exit paths for locking bugs, maple tree erase operations risk allocation failures without gfp flags and internal documentation lacks clarity. Improve lock error detection, update docs, fix race and allocation edge cases and optimize erase allocations using a fallback to GFP_KERNEL | GFP_NOFAIL. * tag 'mm-stable-2026-08-26-15-22' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (172 commits) selftests/proc: make proc-maps-race work with READ_IMPLIES_EXEC memcg: move LRU size accounting on reparenting instead of copying it mm/vmscan: fix comment logic in balance_pgdat maple_tree: add helper mas_make_walkable() maple_tree: avoid extra gap calculation maple_tree: fix argument name in header maple_tree: change two GFP flags in tests maple_tree: document erase and allocations better maple_tree: avoid mas_erase() and mtree_erase() failures maple_tree: document that erase may use GFP_KERNEL for allocations maple_tree: catch race in mas_alloc_cyclic() maple_tree: add bulk parent set helper maple_tree: micro optimisation of mas_wr_store_type() maple_tree: optimise mas_wr_node_store() when not in rcu mode maple_tree: use prefetched value in mas_wr_store_type() maple_tree: clarify comments on mas_nomem() maple_tree: drop MAPLE_ALLOC_SLOTS maple_tree: drop dead code from mas_extend_spanning_null() maple_tree: documentation fix maple_tree: add write lock checking with lockdep sequence numbers ...
2026-08-26cifs: add revalidation on FSCTL failure in smb2_duplicate_extents()Frank Sorenson1-2/+5
smb2_duplicate_extents() has no handling for FSCTL_DUPLICATE_EXTENTS_TO_FILE failure: when the FSCTL fails, local inode metadata may be stale from the pre-extension or from concurrent remote writes, but is never refreshed. Force revalidation on FSCTL failure and use i_size_read() for the pre-extension check. Fixes: cfc63fc8126a ("smb3: fix cached file size problems in duplicate extents (reflink)") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24mm/swap: move swap_ops into file systems for file system-based swapChristoph Hellwig1-24/+39
Currently swap to and from file systems goes through two indirect calls between the swap ops and the swap_rw method. Reduce this by directly providing the swap_ops from the file system. For this refactor swap_fs_submit into a swap_fs_prepare_rw helper that initializes the iov_iter on the callers stack so that file systems can call it directly, and use that to initialize file system specific ops in the NFS and SMB clients, which then get passed to swap_fs_activate. Link: https://lore.kernel.org/20260723054622.3460249-4-hch@lst.de Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Chris Li <chrisl@kernel.org> Cc: Baoquan He <baoquan.he@linux.dev> Cc: Kairui Song <kasong@tencent.com> Cc: Kairui Song <ryncsn@gmail.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Steve French <sfrench@samba.org> Cc: Usama Arif <usama.arif@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-08-24mm/swap: remove SWP_FS_OPSChristoph Hellwig1-3/+1
Provide a swap_fs_activate helper that directly sets up swap_fs_ops, and a flag in struct swap_ops to indicate of NOFS swapping is allowed. Link: https://lore.kernel.org/20260713093350.2154226-7-hch@lst.de Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Baoquan He <baoquan.he@linux.dev> Cc: Barry Song <baohua@kernel.org> Cc: Chris Li <chrisl@kernel.org> Cc: Kairui Song <kasong@tencent.com> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Youngjun Park <youngjun.park@lge.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-08-24Merge tag 'cifs-fixes-7.3-rc1' of https://git.manguebit.org/linuxLinus Torvalds22-108/+223
Pull smb client updates from Paulo Alcantara: - clear sensitive data after use (stack and heap cryptographic keys/hashes) - file size and cache synchronization fixes (fscache cookie serialization and truncation handling) - protocol validation and buffer safety fixes (prevent OOB access and loff_t underflow) - metadata and POSIX attribute fixes (proper hard-link counts and setuid/setgid stripping) - DFS cache and unmount fixes (prevent target-hint UAF and unmount hangs) - general client improvements (fix read request leaks, stats loops, handle servers that don't support O_TMPFILE) * tag 'cifs-fixes-7.3-rc1' of https://git.manguebit.org/linux: (33 commits) cifs: fix loff_t underflow in cifs_remap_file_range() when len == 0 smb: client: reject a tree connect response whose byte count is too small cifs: call pagecache_isize_extended() in cifs_setsize() when extending smb: client: fix copy-paste error in WSL EA length accounting for $LXDEV smb: client: remove redundant NULL check before kfree() smb: client: restore the data_offset bound in is_valid_oplock_break() cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size() smb: client: Avoid leaking sensitive data to the heap in connect.c smb: client: Clear sensitive stack data in smb1encrypt.c smb: client: Clear sensitive stack data in cifsencrypt.c smb: client: Clear sensitive stack and heap data in smb2ops.c smb: client: Clear sensitive stack data in smb2transport.c Revert "cifs: remove all cifs files before kill super" smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr() smb: client: fix ALIGN() overflow in symlink_data() error context loop smb: client: simplify __build_path_from_dentry_optional_prefix() smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2 smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2() smb/client: decode reparse metadata using its payload type smb/client: preserve open info type across compound queries ...
2026-08-24cifs: fix loff_t underflow in cifs_remap_file_range() when len == 0Frank Sorenson1-2/+13
With len == 0 (clone to EOF), the effective length is computed as: len = src_inode->i_size - off; If off > i_size, this is a negative loff_t, corrupting the ByteCount in the FSCTL_DUPLICATE_EXTENTS_TO_FILE request and inverting the range in filemap_write_and_wait_range(). The existing off >= i_size check fires only after the ioctl has already been sent. Snapshot i_size_read() once for both the bounds check and the length calculation, eliminating the TOCTOU and 32-bit torn-read risk. Reject off > src_size with -EINVAL. Treat off == src_size as a no-op, consistent with __generic_remap_file_range_prep(). Fixes: 04b38d601239 ("vfs: pull btrfs clone API to vfs layer") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: reject a tree connect response whose byte count is too smallBryam Vargas2-1/+8
CIFSTCon() bounds its strnlen() over the byte area with the server's ByteCount minus two, which for ByteCount 0 or 1 goes negative as an int and converts to a huge size_t. The later subtraction wraps the __u16 bytes_left, and that is what bounds cifs_strndup_from_utf16(): a bound of up to 65535 against a ~16 KB cifs_req_poolp object runs off the end of the slab object, and the bytes reach userspace through tcon->nativeFileSystem in /proc/fs/cifs/DebugData. Reject a byte area too small for what the parser consumes. Two bytes is the least it can consume, and no conformant response carries fewer. The new trace point is the 129th smb_eio_trace entry, which __mode(byte) cannot represent, so the attribute goes with it. Fixes: cc20c031bb06 ("cifs: convert CIFSTCon to use new unicode helper functions") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24cifs: call pagecache_isize_extended() in cifs_setsize() when extendingFrank Sorenson1-0/+2
cifs_setsize() calls truncate_pagecache() but skips pagecache_isize_extended() on extension. truncate_setsize() shows the correct pattern: i_size_write(inode, newsize); if (newsize > oldsize) pagecache_isize_extended(inode, oldsize, newsize); truncate_pagecache(inode, newsize); pagecache_isize_extended() zeroes the tail of the page straddling old EOF. Without it, dirty bytes in that region can be written back to the server, exposing stale data in the newly extended range. Cc: stable@vger.kernel.org Cc: David Howells <dhowells@redhat.com> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: fix copy-paste error in WSL EA length accounting for $LXDEVFrank Sorenson1-1/+1
The LXDEV block in cifs_query_path_info() uses SMB2_WSL_XATTR_MODE_SIZE (4) instead of SMB2_WSL_XATTR_DEV_SIZE (8), undercounting eas_len by 4 bytes per $LXDEV EA. eas_len is used only as a zero/non-zero presence flag so there is no current functional impact, but the value is incorrect and misleading. Fixes: 97db41604555 ("smb: client: parse uid, gid, mode and dev from WSL reparse points") Cc: stable@vger.kernel.org Cc: Paulo Alcantara <pc@manguebit.org> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: remove redundant NULL check before kfree()Mohammad Shahid1-2/+1
kfree() safely handles NULL pointers, so the explicit NULL check before calling kfree() is unnecessary. This issue was reported by ifnullfree.cocci. Signed-off-by: Mohammad Shahid <mdshahid03@gmail.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: restore the data_offset bound in is_valid_oplock_break()Bryam Vargas1-1/+2
Commit 83bfbd0bb902 ("cifs: Remove the RFC1002 header from smb_hdr") changed the quantity this bound is measured against. It used to be srv->total_read minus the 4-byte RFC1002 preamble that total_read then included, so it was the SMB message length. The same commit stopped counting the preamble, and the mechanical substitution to srv->total_read - srv->pdu_size left an expression that is identically zero: standard_receive3() reads MID_HEADER_SIZE() bytes and then exactly pdu_length - MID_HEADER_SIZE() more, adding both to total_read. len is therefore 0, the subtraction below it wraps, and no __u32 DataOffset can exceed the result, so the check from commit 097f5863b1a0 ("cifs: read overflow in is_valid_oplock_break()") no longer rejects anything. Use total_read, which is now the message length on its own. Fixes: 83bfbd0bb902 ("cifs: Remove the RFC1002 header from smb_hdr") Cc: stable@kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size()Frank Sorenson1-0/+1
When the else branch of cifs_file_set_size() finds a writable file handle via find_writable_file(), it borrows tcon and server from the handle's tlink, attempts the handle-based set_file_size() RPC, and then releases the handle with cifsFileInfo_put(). If set_file_size() fails, execution falls through to the path-based fallback, which reuses the borrowed tcon and server under the "if (tcon == NULL)" guard. Since tcon is not NULL at that point, the guard is skipped. If cifsFileInfo_put() dropped the last reference on a tlink that was already removed from the tlink tree (TCON_LINK_IN_TREE cleared, as happens during reconnection or session teardown), cifs_put_tlink() will have freed tcon; the subsequent set_path_size() call is then a use-after-free. Setting tcon = NULL after cifsFileInfo_put() causes the existing guard to take the cifs_sb_tlink() path, which acquires a fresh reference for the path-based operation or fails cleanly if the session is gone. Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") Cc: stable@vger.kernel.org Cc: Paulo Alcantara <pc@manguebit.com> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: Avoid leaking sensitive data to the heap in connect.cThomas Huth1-1/+1
TCP_Server_Info contains a preauth_sha_hash[] and a cryptkey[] array that might contain sensitive data. Thus free its memory with kfree_sensitive() to avoid that we are leaking this information to the heap. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: Clear sensitive stack data in smb1encrypt.cThomas Huth1-10/+9
Make sure to not leak signature data via the stack, clear it with memzero_explicit() before leaving the function. To avoid that we have to introduce "goto"-cleanup here, we re-arrange the code a little bit (and drop the commented cifs_dump_mem debug code that looks like a leftover from very early days). Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: Clear sensitive stack data in cifsencrypt.cThomas Huth1-3/+9
Make sure to not leak hash data via the stack, clear it with memzero_explicit() before leaving the function. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: Clear sensitive stack and heap data in smb2ops.cThomas Huth1-2/+2
Make sure to not leak key-related data via the heap or the stack by using kfree_sensitive() or memzero_explicit() here. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: Clear sensitive stack data in smb2transport.cThomas Huth1-0/+4
Sensitive data like keys that are stored in stack-local arrays could be leaked via the stack to the calling functions. There is no known vulnerability for this right now, but it's good security style to explicitly zeroize this sensitive material as soon as possible to avoid that it could be exploited together with other bugs later. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24Revert "cifs: remove all cifs files before kill super"Zizhi Wo1-3/+0
This reverts commit 6d9a4aaaa8b2612b5ef9d581e2f286a458b71ee1. First, directly flushing fileinfo_put_wq in that commit cannot guarantee that all in-flight I/O has run its cleanup_work on system_dfl_wq and subsequently called queue_work(fileinfo_put_wq, ...). Flushing only the latter workqueue may therefore miss puts that have not yet been queued, so the fix is not reliable in the first place. Moreover, this fix flushes inside cifs_umount(), which means the busy-dentry warning can still be triggered when umount_check() is called inside kill_anon_super(), because kill_anon_super() is executed before cifs_umount(). Second, commit 75f5c412fa86 ("smb: client: fix busy dentry warning on unmount after DIO") already drains both serverclose_wq and fileinfo_put_wq in cifs_kill_sb(), before kill_anon_super(). By adding a per-superblock outstanding-rreq counter, it guarantees that all cleanup_work for this sb have run, and thus all relevant cfile puts are queued on fileinfo_put_wq or serverclose_wq. Third, no path between those drains and cifs_umount() can queue new work onto either workqueue. In the "cifs_sb->root == NULL" path there are no file-related workers either, so that case is safe as well. Therefore the busy-dentry and null-ptr-deref problems cannot arise, and the flush added by commit 6d9a4aaaa8b2 ("cifs: remove all cifs files before kill super") is redundant and can be removed. Signed-off-by: Zizhi Wo <wozizhi@huawei.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr()Frank Sorenson1-2/+4
reparse_buf_ptr() reads buf->ReparseDataLength before checking that count covers the full fixed header: buf = (struct reparse_data_buffer *)((u8 *)io + off); len = sizeof(*buf); /* 8 bytes */ rdlen = le16_to_cpu(buf->ReparseDataLength); /* offset 4, 2 bytes */ if (count < len || count < rdlen + len) /* check comes after */ struct reparse_data_buffer has ReparseDataLength at offset 4. If a server returns OutputCount < 6, the read at offset 4-5 reaches past the end of the received data. The off+count bounds against iov_len were already validated, but that does not protect against count being smaller than sizeof(*buf). Split the check: verify count >= sizeof(*buf) before reading ReparseDataLength, then verify count covers the data region. Fixes: a158bb66b137 ("smb: client: optimise reparse point querying") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: fix ALIGN() overflow in symlink_data() error context loopFrank Sorenson1-1/+4
The check added by commit 7d9a7f1f96cd ("smb/client: fix possible infinite loop and oob read in symlink_data()") compared the post-ALIGN length against the remaining buffer, but ALIGN() itself can overflow: for ErrorDataLength near UINT32_MAX (e.g. 0xFFFFFFF9), ALIGN(x, 8) wraps to 0, so the subsequent bounds check passes, and the loop advances by zero bytes leaving 'p' pointing into stale data. Fix by checking the raw ErrorDataLength against the remaining space before applying ALIGN(), then checking again after. Since raw_len is bounded by the buffer, raw_len + 7 cannot overflow, so the second check is an exact post-alignment bounds guard. Fixes: 76894f3e2f71 ("cifs: improve symlink handling for smb2+") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: simplify __build_path_from_dentry_optional_prefix()Dmitry Antipov1-5/+1
Use the convenient 'strreplace()' to simplify '__build_path_from_dentry_optional_prefix()'. Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed ↵Frank Sorenson1-3/+11
secondary T2 When a valid primary TRANSACT2 response has been received (mid->resp_buf set, mid->multiRsp true) and a subsequent secondary response causes cifs_check_trans2() to return false -- either because the SMB header is invalid (malformed != 0) or because check2ndT2() rejects the PDU -- handle_mid() overwrites mid->resp_buf with the new buffer (leaking the primary buffer) and, because mid->multiRsp is set, skips the server->smallbuf/bigbuf NULL-out. When the user thread frees mid->resp_buf, server->smallbuf or server->bigbuf is left dangling; the demux thread reuses it for the next packet, resulting in a use-after-free. Combine both early-exit conditions and, when mid->multiRsp is already set, abort the pending transaction inline: set multiEnd, call dequeue_mid() with malformed=true, and return true so handle_mid() exits without touching mid->resp_buf or the server buffer pointers. Fixes: 316cf94a910f ("CIFS: Move trans2 processing to ops struct") Cc: stable@vger.kernel.org # cifs_check_trans2() is in smb1ops.c on kernels < 7.0 Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()Frank Sorenson1-1/+20
coalesce_t2() computes data pointers directly from server-supplied DataOffset fields with no validation against buffer bounds: data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); data_area_of_src = (char *)&pSMBs->hdr.Protocol + get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); data_area_of_tgt += total_in_tgt; ... memcpy(data_area_of_tgt, data_area_of_src, total_in_src); A small DataOffset can push a pointer below the actual byte area, overwriting header fields; a large one can push it past the buffer end, causing out-of-bounds heap reads (source) or writes (target). The BCC overflow guard does not prevent this: BCC reflects how much data is present, while DataOffset controls where in the buffer it starts. The "validate target area" comment present since the function was first written in 2005 was a placeholder that was never implemented. Add lower- and upper-bound checks for both data pointers before the memcpy, and before any target header fields are modified. Fixes: e4eb295d38b5 ("[PATCH] cifs: Handle multiple response transact2 part 1 of 2") Cc: stable@vger.kernel.org Reported-by: Shen Yongchao <grayhat@foxmail.com> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb/client: decode reparse metadata using its payload typeZe Tan3-13/+19
cifs_open_info_data stores FILE_ALL_INFORMATION and SMB3 POSIX query information in a union. reparse_info_to_fattr() selects a union member from the mount mode, while several directory checks always read fi.Attributes. The metadata can instead come from an SMB2 CREATE response on a POSIX mount, or from a POSIX query while processing a reparse point. In those cases the mount mode and hard-coded fi accesses select the wrong union member. See the procedures below: cifs_nt_open smb2_open_file SMB2_open data->fi = SMB2 CREATE response data->contains_posix_file_info = false cifs_get_inode_info reparse_info_to_fattr if (tcon->posix_extensions) // true smb311_posix_info_to_fattr data->posix_fi // wrong union member smb311_posix_get_fattr smb2_query_path_info smb2_compound_op data->posix_fi = SMB3 POSIX query response data->contains_posix_file_info = true reparse_info_to_fattr data->fi.Attributes // wrong union member Add a common DOS attribute accessor and use contains_posix_file_info both for attribute reads and for the final fattr conversion. Signed-off-by: Ze Tan <tanze@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb/client: preserve open info type across compound queriesZe Tan2-4/+6
contains_posix_file_info describes the metadata stored in the fi/posix_fi union. GET_REPARSE and QUERY_WSL_EA do not update that union, so clearing the flag while processing those responses can make POSIX metadata look like FILE_ALL_INFORMATION. Set the flag when CREATE or a validated query response actually populates the union, and leave it unchanged for auxiliary compound operations. This also avoids changing the type when a query fails before copying any metadata. The issue can be reproduced against a Samba server with SMB3 UNIX extensions enabled: mount -t cifs //<server>/<share> /mnt/cifs \ -o vers=3.1.1,posix,reparse=nfs,actimeo=0 mkfifo /mnt/cifs/test-fifo umount /mnt/cifs mount -t cifs //<server>/<share> /mnt/cifs \ -o vers=3.1.1,posix,reparse=nfs,actimeo=0 stat -c '%F %s' /mnt/cifs/test-fifo Before this change, stat reports "fifo 1024" although the server-side EOF is zero. After this change, it reports "fifo 0". Fixes: 9df23801c83d ("smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions") Signed-off-by: Ze Tan <tanze@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24smb/client: mark missing nlink values as unknownZe Tan2-1/+8
Several SMB1 fallback and open responses do not provide the hard link count. The SMB2 create-only query fallback has the same limitation. These paths currently leave a zero link count or synthesize a value of one and then expose it as authoritative metadata. Mark those results with unknown_nlink so existing inodes keep their cached link count and new inodes receive the usual sane default. This was tested against Samba with "server min protocol = NT1". Mount the share using SMB1 with Unix extensions disabled: mount -t cifs //<server>/<share> /mnt/cifs \ -o username=<user>,vers=1.0,nounix Create three names for the same inode and cache its real link count: TESTDIR=/mnt/cifs/nlink-repro-$$ mkdir "$TESTDIR" touch "$TESTDIR/file1" ln "$TESTDIR/file1" "$TESTDIR/file2" ln "$TESTDIR/file1" "$TESTDIR/file3" stat -c 'before open: %h' "$TESTDIR/file1" Open the file and read the link count through the open descriptor: exec 3<"$TESTDIR/file1" stat -Lc 'after open: %h' /proc/$$/fd/3 exec 3<&- Clean up the test files: rm -f "$TESTDIR/file1" "$TESTDIR/file2" "$TESTDIR/file3" rmdir "$TESTDIR" Before this change, the two stat commands report 3 and 1 because the SMB1 open response overwrites the known link count. With this change, both commands report 3. Signed-off-by: Ze Tan <tanze@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-24cifs: fix clearing stats for fastest execution of each smb2 commandFrank Sorenson1-1/+1
The code to clear the 'fastest_cmd' statistics has a typo that repeatedly clears the stat for cmd 0, rather than iterating through each cmd. Fix the typo (0->i). Fixes: 433b8dd7672be ("SMB3: Track total time spent on roundtrips for each SMB3 command") Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-23Merge tag 'ksmbd-for-7.3-rc1' of ↵Linus Torvalds1-24/+0
git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/smb Pull smb server updates from Namjae Jeon: "This contains server updates focused on SMB2 command sequencing, SMB3 request replay and encryption, Apple Time Machine interoperability, protocol-compatibility fixes validated with smbtorture, security hardening, SMB Direct transport support, connection reliability, and other correctness improvements. New features: - Implement the SMB2 command sequence window Enforce the credit-based MessageId range for each connection, rejecting out-of-window, duplicate, and wrapped sequence numbers. This prevents invalid requests and same-channel replays from being processed - Add SMB3 request replay support SMB3 clients may resend requests with SMB2_FLAGS_REPLAY_OPERATION after a channel disconnect when the original response was lost. Track the required channel and open state to safely handle durable CREATE replays and make oplock, lease, and lock replays idempotent, avoiding duplicate state changes and improving multichannel reconnect reliability - Add opt-in Apple Time Machine support Implement the AAPL negotiation and related Finder, stream, COPYCHUNK, sparse-file, CHANGE_NOTIFY, and RPC compatibility required for Time Machine shares, allowing macOS backupd to use ksmbd for backups - Add per-share SMB3 encryption support Allow individual shares to require SMB3 encryption by advertising SMB2_SHAREFLAG_ENCRYPT_DATA in TREE_CONNECT responses and rejecting unencrypted tree connects and plaintext requests for protected shares - Add SMB Direct RDMA encryption support Extend SMB Direct to support SMB3 encrypted payloads over RDMA, with transform negotiation and encryption/decryption for RDMA READ/WRITE Other changes: - Parse and retain AppInstanceVersion contexts, enforce version ordering, close older active handles for newer takeovers, and reject invalid or unversioned opens according to the SMB2 semantics - Accept durable reconnect requests that omit VolatileFileId when the persistent ID and reconnect context identify the handle, while continuing to reject explicit volatile-ID mismatches - Fix SMB2/SMB3 protocol validation and security issues, including request offsets, file and object IDs, IPC responses, output buffer sizes, SMB3.1.1 binding validation, signing-required handling, durable handles, ACLs, maximal access, and security information - Fix heap out-of-bounds accesses, use-after-free bugs, memory leaks, invalid pointer dereferences, and sensitive-data lifetime issues in authentication, Kerberos, preauthentication, sessions, connections, and module teardown - Correct alternate-data-stream and named-stream handling, COPYCHUNK behavior, sparse-file and compression attributes, allocated-range queries, file trimming, duplicate extents, DOS attributes, snapshots, normalized names, and partial information responses - Fix locking, lease, oplock, durable reconnect, async request, and CHANGE_NOTIFY races, including deferred-lock rollback, parent directory lease notifications, and connection teardown lifetime bugs - Fix SMB3 encryption handling for compressed requests, expired encrypted sessions, interim responses, bound multichannel connections, and decryption failures - Fix SMB3 multichannel session lookup and session state transitions so changes are scoped to the correct bound connections and cannot revive connections that are already shutting down - Fix DACL access checks so ACE walks are bounded by the declared DACL size, preventing data beyond the DACL boundary from being interpreted during access validation - Fix session accounting and lifetime issues, including session counter updates during publication and removal, session leaks on registration failure, and procfs creation diagnostics - Improve TCP connection reliability by enabling TCP keepalive for accepted connections and preserving TCP timers for kernel sockets, preventing silent peers from holding connections indefinitely - Fix smbdirect RDMA cleanup ordering for completion queues, QPs, child sockets, and listener locking - Improve async response framing, multi-iovec signing, RPC pipe status handling, and ksmbd procfs monitoring for server, share, connection, session, and open-file state - Remove the obsolete DES crypto header and Kconfig dependency now that NTLMv1 support has been removed - Update the ksmbd repository URL in MAINTAINERS and add an additional KSMBD reviewer" * tag 'ksmbd-for-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/smb: (142 commits) MAINTAINERS: update ksmbd repository URL MAINTAINERS: add myself as KSMBD reviewer smb: server: remove unused DES crypto header smb: server: Remove obsolete "select CRYPTO_LIB_DES" from Kconfig file ksmbd: keep TCP timers alive for kernel sockets ksmbd: enable TCP keepalive for accepted connections smb/server: fix session counter on session removal smb/server: update session counter under sessions table lock smb/server: fix session leak in ksmbd_session_register() smb/server: warn if ksmbd_proc_create() fails ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size ksmbd: make RDMA encryption diagnostics conditional ksmbd: add SMB Direct RDMA encryption transform ksmbd: handle encrypted compressed requests ksmbd: decrypt requests from expired encrypted sessions ksmbd: disconnect on SMB3 decryption failure ksmbd: encrypt interim responses to encrypted requests ksmbd: scope session state changes to bound connections ksmbd: fix encrypted request lookup on bound channels ksmbd: add per-share SMB3 encryption enforcement ...
2026-08-19smb/client: fix nlink of an overwritten open fileChenXiaoSong1-5/+6
Reproducer: 1. server: systemctl start ksmbd 2. client: mount with `posix` option mount -t cifs -o posix //${server_ip}/export /mnt 3. client: touch /mnt/file1 /mnt/file2 4. client: C program: int fd = open("/mnt/file2", O_RDONLY); 5. client: C program: rename("/mnt/file1", "/mnt/file2"); 6. client: C program: struct stat stbuf; fstat(fd, &stbuf); stbuf.st_nlink is 1, should be 0 This patch fixes xfstests generic/035 when mounted with `posix` option. Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19cifs: remove dead size-update blocks in cifs_setattr_unix/nounixFrank Sorenson1-14/+0
Commit 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") introduced cifs_file_set_size(), which calls netfs_resize_file() and cifs_setsize() on success. cifs_setsize() calls i_size_write(), updating i_size to the new value. The subsequent blocks in both cifs_setattr_unix() and cifs_setattr_nounix(): if ((attrs->ia_valid & ATTR_SIZE) && attrs->ia_size != i_size_read(inode)) { truncate_setsize(inode, attrs->ia_size); netfs_resize_file(&cifsInode->netfs, attrs->ia_size, true); fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); } are therefore unreachable on the success path: attrs->ia_size == i_size_read(inode) always holds after cifs_file_set_size() succeeds. On the failure path, execution jumps to out/cifs_setattr_exit before reaching these blocks. truncate_setsize() and netfs_resize_file() are redundant with what cifs_file_set_size() already did; fscache_resize_cookie() was moved there by commit fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()"). Remove both dead blocks. Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") Signed-off-by: Frank Sorenson <sorenson@redhat.com> Reviewed-by: Huiwen He <hehuiwen@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19cifs: remove redundant size-update block in cifs_remap_file_range()Frank Sorenson1-5/+1
cifs_remap_file_range() acquires i_rwsem on both inodes via lock_two_nondirectories() before calling smb2_duplicate_extents(). cifs_setsize() (called inside smb2_duplicate_extents() when the clone extends the file) therefore already runs under the lock, meaning the fscache_resize_cookie() added to cifs_setsize() by commit fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()") is correctly serialised for this path without further changes. That same commit made the caller-side block: if (rc == 0 && new_size > i_size) { truncate_setsize(target_inode, new_size); fscache_resize_cookie(cifs_inode_cookie(target_inode), new_size); } redundant: smb2_duplicate_extents() already performs the full size update via cifs_setsize() when the operation extends the file. Remove the now-dead block. Signed-off-by: Frank Sorenson <sorenson@redhat.com> Reviewed-by: Huiwen He <hehuiwen@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19cifs: add cifs_resize_file_locked() to guard fscache_resize_cookie() under ↵Frank Sorenson3-11/+23
i_rwsem cifs_setsize() calls fscache_resize_cookie() without holding i_rwsem. When the fscache cookie is active (FSCACHE_COOKIE_IS_CACHING is set), fscache_resize_cookie() performs a real resize that requires i_rwsem held exclusively. If another file descriptor has the same inode open, fscache_use_cookie() was already called from that cifs_open(), making the cookie active. In that case, calling cifs_setsize() from cifs_do_truncate() (invoked from cifs_open() without i_rwsem) races against concurrent fscache I/O. Strip fscache_resize_cookie() from cifs_setsize(), making it a pure size/page-cache helper. Add cifs_resize_file_locked() for callers that already hold i_rwsem: it calls netfs_resize_file() and cifs_setsize(), then temporarily activates the cookie with fscache_use_cookie() to perform the resize under the lock, then deactivates it with cifs_fscache_unuse_inode_cookie(). Using fscache_use_cookie() before the resize ensures correctness whether or not another fd already holds the cookie active. Switch cifs_file_set_size(), smb2_duplicate_extents(), and both size- extension branches of smb3_simple_falloc() to the new wrapper; those paths already hold i_rwsem via VFS setattr, lock_two_nondirectories(), or cifs_fallocate() respectively. cifs_do_truncate() continues to call cifs_setsize() followed by cifs_invalidate_cache(), since it runs without i_rwsem. Fixes: fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()") Cc: stable@vger.kernel.org Cc: David Howells <dhowells@redhat.com> Cc: Paulo Alcantara <pc@manguebit.com> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19cifs: use cifs_invalidate_cache() in cifs_do_truncate() for O_TRUNCFrank Sorenson1-0/+1
cifs_do_truncate() is invoked from cifs_open() without i_rwsem, so it cannot use cifs_resize_file_locked() to perform a proper fscache cookie resize. Instead, add cifs_invalidate_cache() after cifs_setsize(). cifs_invalidate_cache() calls fscache_invalidate(), which works without holding i_rwsem: it unconditionally increments inval_counter and sets FSCACHE_COOKIE_NO_DATA_TO_READ, ensuring that stale cached data is not served once the cookie is later activated by fscache_use_cookie(). Truncation to zero leaves no valid cached data, making invalidation the correct semantic here. Fixes: fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()") Cc: stable@vger.kernel.org Cc: David Howells <dhowells@redhat.com> Cc: Paulo Alcantara <pc@manguebit.com> Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19smb: client: clear ce->tgthint in free_tgts()Fredric Cover1-0/+2
When free_tgts() frees all structures in ce->tlist, ce->tgthint is left pointing to one of the freed cache_dfs_tgt structures. If ce->tgthint is not reset before it is used later, it results in a use-after-free. Set ce->tgthint to NULL in free_tgts() after the elements are freed to reflect that no elements remain. Fixes: 54be1f6c1c37 ("cifs: Add DFS cache routines") Cc: stable@vger.kernel.org # depends on: smb: client: harden DFS cache against invalid target hints Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
2026-08-19smb: client: harden DFS cache against invalid target hintsFredric Cover1-7/+24
Currently, get_tgt_name() returns ERR_PTR(-ENOENT) when ce->tgthint is NULL, and dfs_cache_noreq_update_tgthint() assumes ce->tgthint is always valid. In preparation for clearing ce->tgthint in free_tgts(), harden callers of get_tgt_name() against ERR_PTR results and harden dfs_cache_noreq_update_tgthint() against NULL pointer dereferences. Cc: stable@vger.kernel.org Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org>