summaryrefslogtreecommitdiff
path: root/fs
AgeCommit message (Collapse)Author
32 hoursfuse: fix link error with CONFIG_FUSE_PASSTHROUGH=nSasha Levin
Commit 2f19d54c055d ("fuse: support 64 bit, server allocated backing ID") moved the CONFIG_FUSE_PASSTHROUGH check out of the backing ioctl handlers and into fuse_get_conn_for_passthrough(). The calls from the handlers into backing.c, which is only built with CONFIG_FUSE_PASSTHROUGH, are now only removed if the compiler inlines that helper. It does not have to, and with gcc 11 and CONFIG_CC_OPTIMIZE_FOR_SIZE it doesn't: dev.c:(.text+0x355c): undefined reference to `fuse_backing_open' nios2-linux-ld: dev.c:(.text+0x3594): undefined reference to `fuse_backing_open_64' nios2-linux-ld: dev.c:(.text+0x35d0): undefined reference to `fuse_backing_close' Check CONFIG_FUSE_PASSTHROUGH in each handler again, as fuse_notify_backing_remove() does. The check still comes after the fuse_get_dev() and -ENOTCONN checks, so the errors userspace sees do not change. Fixes: 2f19d54c055d ("fuse: support 64 bit, server allocated backing ID") Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202610171310.uqRzJkIx-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202610260719.sj08mXBr-lkp@intel.com/ Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
32 hoursMerge tag 'cifs-fixes-7.4-rc1' of https://git.manguebit.org/linuxLinus Torvalds
Pull smb client fixes from Paulo Alcantara: - Validate the offsets and lengths a server puts in its responses before using them, so that a malicious or broken server can no longer make the client read past the received data: - POSIX lock data (which leaked kernel bytes through F_GETLK) - NT transaction responses and SMB1 EA lists (both wrapping their pointer checks on 32-bit) - short SESSION_SETUP responses (which sent stale buffer content back to the server in the NTLMv2 AUTHENTICATE message) - SMB2 READ data areas - empty truncated fiemap responses - Fix a heap overflow in SMB2_tcon() with UNC paths longer than MAX_SHARENAME_LENGTH - Fix a slab-out-of-bounds write when chmod() rewrites a security descriptor that needs more room than was reserved - Fix a use-after-free of the server info between the cifsd thread and the release of the last session reference (reported by syzbot) - Fix a use-after-free in the demultiplex thread when a receive error reconnects and frees the read request still being processed - Fix a double teardown of a tcon that the cached directory laundromat took a reference on while it was being freed - Fix a NULL pointer dereference when /proc/fs/cifs/DebugData is read while the module is still initializing * tag 'cifs-fixes-7.4-rc1' of https://git.manguebit.org/linux: smb: client: validate SMB1 EA list bounds before parsing smb: client: stop processing a read response after a receive error smb: client: don't resurrect an exiting tcon from cached dir workers smb: client: fix early procfs exposure race smb: client: fix slab-out-of-bounds write in id_mode_to_cifs_acl() smb: client: hold server info until cifsd exits smb: client: fix fiemap wild read on empty truncated response smb: client: validate the data area in SMB2_read() smb: client: reject short SESSION_SETUP responses smb: client: fix buffer overflow in SMB2_tcon() smb: client: validate NT transaction response layout and offsets smb: client: bound POSIX lock data area by response length
32 hoursMerge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linuxLinus Torvalds
Pull fsverity fixes from Eric Biggers: "Fixes for several bugs found by LLMs: - Fix bypass of IPE's fsverity support, and a use-after-free in certain cases, when FS_IOC_ENABLE_VERITY fails when almost done - Fix FS_IOC_MEASURE_VERITY and FS_IOC_READ_VERITY_METADATA to no longer bypass Landlock and AppArmor's read permission checks - Be robust against the filesystem returning different values for a file's verity descriptor length in two successive queries" * tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux: fsverity: Set S_VERITY only after rollback is no longer possible fsverity: Tell LSMs about signature only after verity is enabled fsverity: Be more careful with return value of ->get_verity_descriptor() fsverity: Explicitly require FMODE_READ to retrieve hashes
36 hoursMerge tag 'ceph-for-7.4-rc1' of https://github.com/ceph/ceph-clientLinus Torvalds
Pull ceph updates from Ilya Dryomov: "The two things of note here are the disablement of inline data support and a new lazyio mount option to enable LAZYIO behavior globally (instead of via an ioctl on a per-file basis), both from Xiubo. Despite being over a decade old, the inline data feature never lost its experimental status -- it has always been off by default and required passing --yes-i-really-mean-it flag to be turned on. It was officially deprecated in 2020 and is now in the process of being removed on the MDS side. For now it's still possible to re-enable it in Kconfig, but the code will eventually be dropped from the kernel client entirely. Outside of that we have a number of bug fixes, a series from Tal to help phase out older page APIs, some cleanups from Max and a large pile of LLM-based hardening patches. Xiubo is also back in a maintainer role, replacing Slava" * tag 'ceph-for-7.4-rc1' of https://github.com/ceph/ceph-client: (66 commits) ceph: fix uninitialized err in ceph_netfs_issue_read() MAINTAINERS: update ceph and libceph maintainers ceph: validate encoded xattr name lengths ceph: validate MDS reply fragtree split array length ceph: bound name skips in ceph_mdsmap_decode() by the message end ceph: validate fscrypt auth blob length ceph: check the caps of a closed file after caps_wanted_delay_min ceph: don't fail write_begin with -EAGAIN after flushing old snapc ceph: fail readdir when the MDS reply carries no dirfrag ceph: clamp MDS reply result code to the errno range libceph: initialize CRUSH choose argument weights libceph: fix out-of-bounds reads from repeated CRUSH bucket entries ceph: fix 32-bit overflow in readdir reply count check libceph: reject bad connect_seq in msgr1 READY reply ceph: Fix mds session leak in __open_export_target_session() ceph: Fix xattr buffer leak in __send_cap() ceph: fix integer overflow in the snap trace bounds check libceph: bound mon_command ack decode to front len ceph: use alloc_page() in fill_fscrypt_truncate() libceph: use alloc_page() in ceph_alloc_page_vector() ...
37 hoursMerge tag 'vfs-7.4-rc1.fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: - writeback: - Update dirtied_when instead of dirtied_time_when when a wb switch puts an inode at the newest end of the target b_dirty list. The list was left out of order so move_expired_inodes() could stop before older inodes, and the lazytime expiration timestamp was reset - Clear the old wb's dirty-I/O state and bandwidth contribution when a batch of inode switches leaves its dirty lists empty. An empty wb stayed scheduled for periodic writeback and inflated bdi->tot_write_bandwidth - Take wb_switch_rwsem across the inode scan of cleanup_offline_cgwb(). The v7.3-rc5 fix that rotates scanned inodes let a scan racing a sync()'s queue_io() move lazytime inodes past the sync's cutoff, so sync() returned without persisting their timestamps - Don't kick writeback for an IOCB_DONTCACHE write on an inode that has no wb yet. With cgroup writeback an O_DIRECT RWF_DONTCACHE write to a block device dereferenced NULL - statmount/listmount/listns: - Refuse statmount() string requests with a buffer that isn't larger than struct statmount - Don't wrap around with a U64_MAX cursor in listmount() and listns() - Don't end listns() at an inactive namespace - Only add init_ipc_ns and init_net to the namespace trees if CONFIG_IPC_NS and CONFIG_NET_NS are enabled - iomap: - Only mark blocks uptodate in __iomap_write_begin() after reading them and let __iomap_write_end() mark the zeroed blocks uptodate once the copy from userspace succeeded - Check a chunk against max_integrity_io_size() on its own before the bio size check - Only enforce block alignment for direct I/O into holes and unwritten extents if IOMAP_DIO_FSBLOCK_ALIGNED is set - backing-file: - Check S_APPEND and S_IMMUTABLE on the backing inode. FUSE passthrough opens the backing file with vfs_open() which skips may_open(), so anyone who may open the FUSE file for writing could overwrite an append-only backing file anywhere or write to an immutable one. Open, mmap and writes now check the backing inode the way may_open() and do_mmap() do - Always call kiocb_end_write() for a queued write - Let backing files inherit FMODE_NONOTIFY from the user file. The event fds fanotify creates for permission events on a stacked filesystem raised FS_OPEN_PERM on the real path from inside the listener's read() and deadlocked listeners with marks on both layers - pidfs: - Look the task up before checking for exit information in PIDFD_GET_INFO and start over if the task no longer owns the pid once all fields have been read. A caller racing release_task() got neither PIDFD_INFO_PID nor PIDFD_INFO_EXIT or ESRCH although the exit information was available, and a caller racing a sub-thread's exec reported that thread's tid as the pid - Clear the mask bits of fields that lie beyond the struct size the caller passed. The uapi header promises that the mask names no such field but a caller passing PIDFD_INFO_SIZE_VER0 got the coredump and supported mask bits set for fields that were never written - aio: - Give the aio ring a ->read_folio that fails with EIO so a fault on a ring whose file was truncated gets SIGBUS instead of jumping to NULL - Check nr_events against the ring size before doubling it in ioctx_alloc() - splice: - Only write back an implicit file position in do_splice() when the splice helper succeeded. splice doesn't take f_pos_lock so a failed splice restored a stale snapshot over a position that a concurrent getdents() had moved. On ext2 the next readdir then trusted an offset inside a directory entry - Retry tee() when the input pipe was emptied or the output pipe filled between the prep steps and link_pipe() instead of returning 0 while the input pipe still has writers, as splice_pipe_to_pipe() does - ucount: - Take the reference that pins a ucounts level on the 0 -> 1 transition before checking the rlimit - Read the parent ucounts before dropping the rlimit count in do_dec_rlimit_put_ucounts() - inode: - Rotate inodes whose page cache couldn't be dropped to the tail of the LRU - Skip inodes that another LRU walker is isolating - setns: - Set nsset->flags before anything in prepare_nsset() can fail so the error path drops the cred prepared for CLONE_NEWUSER. A failing setns() with CLONE_NEWUSER and CLONE_NEWNS leaked it together with its user namespace - Refuse setns(CLONE_NEWNS) for a task that shares its fs_struct again when more namespaces are requested - minix: - Restore uptodate on the pinned bitmap buffers before redirtying them after a failed writeback instead of tripping the warning in mark_buffer_dirty(), as ext2 and ext4 do for their superblock buffers - Reject rmdir() of a directory with a corrupted link count with EFSCORRUPTED instead of hitting the drop_nlink() warning - userns: Keep the exec securebits and their locks when creating or joining a user namespace. set_cred_user_ns() reset all securebits to SECUREBITS_DEFAULT so anyone who may create a user namespace could shed SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE with a single unshare(CLONE_NEWUSER) - fs: Honor FOP_UNSIGNED_OFFSET in sys_llseek() and in the pread64(), pwrite64(), preadv() and pwritev() wrappers - proc/kcore: Advance the vmalloc retry in read_kcore_iter() by the last vread_iter() copy instead of the running total - eventpoll: Return the error when the wakeup source for EPOLLWAKEUP can't be created in EPOLL_CTL_MOD instead of reporting success without suspend protection - coredump: Mark do_coredump() noinline_for_stack - nsfs: Check the trailing bytes of a namespace file handle in bytes instead of words - netfs: Restore the per-level and per-point decoding of the debug mask - exportfs: Release the directory file get_name() opened with __fput_sync(). From nfsd's kernel threads the deferred fputs arrived faster than delayed_fput retired them and each pinned the directory's readdir state, growing unreclaimable slab by about 90 MB per second under a parallel tree walk - fs: Call ramfs_kill_sb() for a ramfs rootfs. Since rootfs can be unmounted as of v7.0 its struct ramfs_fs_info was leaked - signal: Check the blocked mask for every entry dequeue_synchronous_signal() looks at. The scan could select a blocked synchronous signal and deliver it while blocked - super: Convert the superblock device table from an rhltable to a plain hashtable under a spinlock. This fixes a bug from v7.3 where fs_bdev_freeze() froze a btrfs filesystem through a stale member that open_ctree() had already released while the freeze was waiting for SB_BORN - fork: Leave rcu_users at zero until copy_process() can't fail anymore. bpf_task_acquire() handed out trusted references to the new task from the task_alloc LSM hook and sched_ext's ops.init_task() and a failing fork freed the task behind them - xattr: Always run cap_convert_nscap() for a security.capability write. A zero-length setxattr() skipped it and let an unprivileged caller without CAP_SETFCAP or write permission on the file plant an empty security.capability xattr that made every execve() of the binary fail with EINVAL - namei: Skip the S_ISDIR assertion in - proc: Refuse to mount on entries below /proc/<pid>/net like fd/, fdinfo/ and map_files/. proc_net_d_revalidate() always fails so the first lookup by anyone with search permission ran d_invalidate() on the dentry and detached every mount on it, locked mounts included - libfs: Hold one mount reference for all pins instead of one per pin. The pin count is what keeps the mount alive, so the per-pin reference only cost a mntget() and a mntput() through mntput_no_expire_slowpath() for every debugfs, tracefs, securityfs or configfs file that comes and goes - iov_iter: Return 0 from iov_iter_alignment() for an empty iterator of any type - watch_queue: Give info_id its own storage instead of overlaying it with rcu_head - filelock: Take an active superblock reference while waiting for a delegation break. After a lazy umount closing the delegation holder could shut down the superblock under the waiter whose final iput() then ran shmem_evict_inode() on freed state - fs: Skip the copy_file_range() write limit checks when there is no data to copy - bpf: Allow bpf_d_path() from fentry on filp_close_sync(). Since close_range() became synchronous this cycle close(), close_range() and the closes on exec and exit no longer go through filp_close(). fexit stays rejected since the file may be gone by then - fs_pin: Dequeue the wait entry unconditionally in pin_kill(). A spuriously woken waiter kept its on-stack entry queued, took that as proof that the pin was alive and used the freed acct structure when umount() of the accounting file raced acct(2) - dcache: Don't fail __d_obtain_alias() for an inode without links and aliases. The ESTALE check added this cycle broke open_by_handle_at() and nfsd file handle decoding on NFS and FUSE where i_nlink is just what the server last reported and the handle may well still be valid - selftests/ovl: Fix the mountinfo expectations of the detached layer test which has failed since it was added * tag 'vfs-7.4-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (60 commits) fs: don't fail __d_obtain_alias() for unlinked inodes ns: don't add init_ipc_ns and init_net without namespace support aio: avoid request count overflow in ioctx_alloc() selftests/ovl: fix detached layer mountinfo expectations bpf: Allow bpf_d_path() from filp_close_sync() fs: skip copy_file_range write limits when there is no data minix: reject rmdir of a directory with a corrupted link count fs_pin: do not trust the pin after a spurious wakeup in pin_kill() ucount: read the parent ucounts before dropping the rlimit count splice: retry tee() instead of returning 0 when it races selftests/pidfd: test that fields beyond the struct size are not reported pidfs: do not report fields that do not fit into the caller's struct fs: let backing files inherit FMODE_NONOTIFY from the user file splice: avoid stale f_pos writeback on error backing-file: always end a queued write filelock: keep superblock active through delegation wait watch_queue: keep info_id separate from rcu_head iomap: only follow dio alignment requirement if specified iov_iter: fix NULL deref in iov_iter_alignment() backing-file: enforce append-only and immutable backing inodes ...
40 hoursfs: don't fail __d_obtain_alias() for unlinked inodesAmir Goldstein
Commit 669bb5af15d4 ("fs: make sure to call fsnotify_inoderemove() only once when inode is dead") did two things. It made dentry_unlink_inode() call fsnotify_inoderemove() only once the inode has neither links nor aliases left. And it made __d_obtain_alias() fail with -ESTALE for an inode in that state so that open_by_handle_at() can't create a new alias after FS_DELETE_SELF has been reported and the inode marks are gone. The second part is wrong for network filesystems. __d_obtain_alias() backs d_obtain_alias() and d_obtain_root(). Those are what the ->fh_to_dentry() and ->get_parent() methods use to turn the inode they looked up into a dentry for exportfs_decode_fh_raw(), i.e., for open_by_handle_at() and for nfsd file handle decoding. For a local filesystem an in-core inode without links and aliases is an orphan that goes away on the final iput(). For a network filesystem that's not true. i_nlink is just the link count the server last reported and whether the object is still reachable through its file handle is up to the server. If a file is unlinked while it is still open elsewhere, e.g., by another NFSv4 client or by a process on the server, the server keeps the object alive and its file handle stays valid. nfs_fh_to_dentry() fetches the attributes for such a handle, nfs_fhget() sets i_nlink to 0 from them, the new inode has no aliases yet and so __d_obtain_alias() now fails with -ESTALE. The same applies to fuse_get_dentry() which takes i_nlink from the fuse server. Filesystems that care about unlinked inodes already make that decision themselves in ->fh_to_dentry(), e.g., ceph's __fh_to_dentry() fetches the link count with CEPH_CAP_LINK_SHARED and only refuses an unlinked inode if it isn't open. Note that on a network filesystem i_nlink drops to zero through attribute updates when another client unlinks the file. So the inode might never have gone through dentry_unlink_inode() with i_nlink == 0, i.e., fsnotify_inoderemove() might never have been called for it and there's nothing for the -ESTALE to protect. So drop the two checks from __d_obtain_alias() again and go back to the unconditional alias lookup. While at it, update the comment above inode_notify_dead() since it no longer blocks new aliases. Amir sent this as v3 to replace 669bb5af15d4 but that commit was already in mainline by then. So do it as a fix on top. The resulting code is identical to v3. This means open_by_handle_at() can again create a new alias for an unlinked inode after FS_DELETE_SELF has been reported. Closing that file reports a second FS_DELETE_SELF and the file has none of the inode marks that were torn down. That's what Daehyeon's open_by_handle_at() LTP test checks so it is expected to fail again. This needs to be handled separately. A mark that is added through such a file while fsnotify_destroy_marks() is still running is rejected with -ENOENT since 36ebddca56b9 ("fsnotify: prevent mark additions during connector teardown") so it can't end up on a detached connector. Christian Brauner <brauner@kernel.org> says: Amir's v3 replaced 669bb5af15d4 as a whole. I turned it into an incremental fix on top of mainline and wrote a new commit message. Jan's Reviewed-by was given on v3 and the resulting code is identical. Fixes: 669bb5af15d4 ("fs: make sure to call fsnotify_inoderemove() only once when inode is dead") Cc: stable@vger.kernel.org Reported-by: Daehyeon Ko <4ncienth@gmail.com> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://patch.msgid.link/CAOQ4uxg7Qt436SiKhKEJKOjtCjeB_XyTjazYF7HMyQAGGcgx2A@mail.gmail.com Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20261030-work-dcache-obtain_alias-v1-1-a1f7e44536d2@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursaio: avoid request count overflow in ioctx_alloc()Jan Kara
ioctx_alloc() saves the 32-bit nr_events in max_reqs, then doubles nr_events before checking the ring-size bound. For nr_events=0x80000001, the doubled value wraps to 2, so the ring check passes and aio_setup_ring() builds a one-page/127-slot ring. The original 0x80000001 is still stored in ctx->max_reqs and charged to the global aio_nr quota. If an administrator has raised fs.aio-max-nr to at least 0x80000001, an unprivileged process can create that context and make later normal io_setup() calls fail with -EAGAIN until the wrapped context is destroyed. Check for too large number of requests before multiplying. Link: https://lore.kernel.org/all/20261022091748.3653127-1-teel4res@gmail.com Reported-by: Cheng Yongkang <teel4res@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20261022112534.3513745-2-jack@suse.cz Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursfs: skip copy_file_range write limits when there is no dataHungyu Lin
generic_copy_file_checks() reduces count to zero for a source offset at or beyond EOF, but still checks the destination write limits. If pos_out is at RLIMIT_FSIZE, this sends SIGXFSZ and returns -EFBIG even though there is no data to write. For example, GNU cat copying a 1024-byte regular file to another regular file with RLIMIT_FSIZE=1024 copies all bytes and is then killed by its next copy_file_range() call at EOF. A zero-length request can fail in the same way. Check write limits only when count is nonzero, as the ordinary write checks already do. Keep the other copy validation in place. Fixes: 96e6e8f4a68d ("vfs: add missing checks to copy_file_range") Cc: stable@vger.kernel.org Signed-off-by: Hungyu Lin <dennylin0707@gmail.com> Link: https://patch.msgid.link/20261026015738.46230-1-dennylin0707@gmail.com Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursminix: reject rmdir of a directory with a corrupted link countNguyen Ngoc Thang
minix_rmdir() calls minix_unlink(), which drops the victim's link count once, and then drops it a second time for the "." entry. An image where an empty directory has i_nlink < 2 makes the second drop hit drop_nlink() with i_nlink == 0: WARNING: fs/inode.c:408 at drop_nlink minix_rmdir+0xe9/0x150 vfs_rmdir filename_rmdir __do_sys_unlinkat The parent's link count is already validated; do the same for the directory being removed and fail with -EFSCORRUPTED. Reported-by: syzbot+8420e667af06b1709c00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8420e667af06b1709c00 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> Link: https://patch.msgid.link/20261016115851.14276-1-ngocthang2710.1999@gmail.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursfs_pin: do not trust the pin after a spurious wakeup in pin_kill()Nickolai Zeldovich
A task waiting in pin_kill() for another task's ->kill() can take p->wait.lock after the pin has been freed, and can return with its on-stack wait entry still on p->wait. With BSD process accounting this is a use-after-free of the acct structure when umount() of the mount holding the accounting file races with acct(2). pin_kill() takes a still-queued entry as proof that pin_remove() has not run, so p is alive. But autoremove_wake_function() dequeues only when try_to_wake_up() succeeds: if the waiter was already woken spuriously, pin_remove() leaves the entry queued, acct_pin_kill() frees the acct with kfree_rcu(), and the grace period can end while the waiter sits between schedule() and rcu_read_lock(). Dequeue the entry unconditionally in a private wake function; pin_remove() is the only waker and sets p->done first. Reproduced under QEMU with KASAN and test-only delays: a slab-use-after-free in pin_kill() before the patch, no report after. Fixes: 59eda0e07f43 ("new fs_pin killing logics") Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu> Link: https://patch.msgid.link/20261027015813.841821-1-nickolai@csail.mit.edu Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hourssplice: retry tee() instead of returning 0 when it racesNickolai Zeldovich
tee() can return 0 while the input pipe still has writers, when another task reads the input pipe or fills the output pipe at the same time. tee(2) documents 0 as "no data was copied" because the input pipe has no writers, and loops built on it (the man page example breaks out on 0) stop early. In a test with one thread writing 1 byte at a time to the input pipe, one reading it and one draining the output pipe, about one tee() call in 150 returned 0. do_tee() runs ipipe_prep() and opipe_prep() to wait for data and room, each under its own pipe lock, and only then takes both locks in link_pipe(). If the input pipe was emptied or the output pipe filled in between, link_pipe() finds nothing to do and returns 0. splice_pipe_to_pipe(), which was modelled on tee(), handles the same race by dropping both locks and going back to the prep steps ("A zero return value means EOF, so retry instead"), and returns -EAGAIN for SPLICE_F_NONBLOCK. Do the same in link_pipe(): move the prep steps into it and retry when nothing was linked although the input pipe still has writers. Tested under QEMU (x86_64) with the program in the notes: 154 of 22698 tee() calls returned 0 before the change, none of 34429 after it. Fixes: aadd06e5c56b ("[PATCH] splice: fix problems with sys_tee()") Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu> Link: https://patch.msgid.link/20261018025541.799135-1-nickolai@csail.mit.edu Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hourspidfs: do not report fields that do not fit into the caller's structNickolai Zeldovich
The documentation of struct pidfd_info promises that "If the structure size is too small to contain a field (requested or not), to avoid confusion the mask will not contain a bit for that field", and asks userspace to trust the returned mask when deciding which fields hold valid data. pidfd_info() does not keep that promise. It builds kinfo.mask without looking at the size encoded in the ioctl command, and copy_struct_to_user() then truncates the copy to that size. A caller that passes a 64-byte struct (PIDFD_INFO_SIZE_VER0) and requests PIDFD_INFO_COREDUMP or PIDFD_INFO_SUPPORTED_MASK gets a mask with PIDFD_INFO_COREDUMP, PIDFD_INFO_COREDUMP_SIGNAL, PIDFD_INFO_COREDUMP_CODE and PIDFD_INFO_SUPPORTED_MASK set, while the coredump_* and supported_mask fields behind the 64 bytes were never written. Trusting the mask as documented, userspace then reads whatever its own buffer held at those offsets. The same happens for a 72- or 80-byte struct and the fields added after it. Clear the bits of the fields that lie beyond the caller's size before the copy, in the one place that knows both the final mask and the size. A request for a field that cannot be returned is thereby answered the way the header describes: the field is simply absent from the mask. Fixes: 1d8db6fd698d ("pidfs, coredump: add PIDFD_INFO_COREDUMP") Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu> Link: https://patch.msgid.link/20261024041334.831273-2-nickolai@csail.mit.edu Acked-by: Luca Boccassi <luca.boccassi@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursfs: let backing files inherit FMODE_NONOTIFY from the user fileEdvard Conrad
When fanotify reports a permission event, copy_event_to_user() creates the event fd with dentry_open_nonotify(), so that the listener's use of that fd does not generate further events. If the event's path is on a stacked filesystem, the stacked filesystem's ->open() opens the real file with backing_file_open(). Since commit ebe559609d78 ("fs: get rid of __FMODE_NONOTIFY kludge"), FMODE_NONOTIFY lives in f_mode only and the backing file does not inherit it: it is allocated with the default fsnotify mode, and fsnotify_open_perm_and_set_mode() raises FS_OPEN_PERM on the real path if the backing filesystem has permission event watchers. Before that commit __FMODE_NONOTIFY travelled in f_flags, and overlayfs copies the user file's f_flags into the backing open (ovl_open_realfile()), so the backing file was exempt implicitly. Commit bc2473c90fca ("ovl: enable fsnotify events on underlying real files") relied on that when it dropped FMODE_NONOTIFY from OVL_OPEN_FLAGS. The nested event is queued to the same group, from inside the listener's read(2), and can only be answered by another reader thread of that group. A listener holding filesystem marks on both the stacked and the backing filesystem therefore deadlocks as soon as all of its reader threads are inside such a read(2) at the same time, and every other task that touches a marked filesystem queues up behind it. Observed with a commercial anti-malware agent (16 reader threads) on an ostree/composefs host: / is an overlayfs whose data layer is the ostree object store on the same btrfs that holds /etc and /home, and a systemd-sysext overlay sits on /usr. Every on-demand scan of /usr wedged the whole machine until the group was killed. Stack of a blocked reader thread on 7.2.7: fanotify_get_response fanotify_handle_event send_to_group fsnotify __fsnotify_parent do_dentry_open vfs_open backing_file_open ovl_open_realfile [overlay] ovl_open [overlay] do_dentry_open vfs_open backing_file_open ovl_open_realfile [overlay] ovl_open [overlay] do_dentry_open vfs_open dentry_open_nonotify copy_event_to_user fanotify_read vfs_read ksys_read Userspace cannot avoid this: the backing open happens while the kernel builds the fd, before the event is reported, and fid reporting is not available for permission event classes. Make a backing file inherit FMODE_NONOTIFY when the user file it is opened for must not generate events. This restores the pre-6.14 behaviour for the fds that fanotify creates (and for any other FMODE_NONOTIFY file), while ordinary opens through a stacked filesystem keep generating events on the real path, as intended by bc2473c90fca. Verified with a self-contained reproducer (private tmpfs lower layers, an overlayfs over them, FAN_OPEN_PERM filesystem marks on the overlay and on one lower layer, a child opening a file through the overlay) in a qemu VM on this tree built with defconfig plus OVERLAY_FS, FANOTIFY and FANOTIFY_ACCESS_PERMISSIONS: without this patch the listener's read(2) never returns and the child's open is released only by the listener's death; with it read(2) returns, the event is answered and the open completes. backing_tmpfile_open() is left alone: its only caller is ovl_create_tmpfile(), whose user file is a regular overlayfs file. Fixes: ebe559609d78 ("fs: get rid of __FMODE_NONOTIFY kludge") Cc: stable@vger.kernel.org Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Edvard Conrad <edvard@tuta.io> Link: https://patch.msgid.link/P58Wrer--F-9@tuta.io Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hourssplice: avoid stale f_pos writeback on errorDaehyeon Ko
do_splice() snapshots an implicit file position before calling the splice helper. Since splice does not take f_pos_lock, another operation on the same open file description can update f_pos while the helper is blocked. If the helper then fails, the unconditional writeback restores the stale snapshot. For a directory without ->splice_read, a file-to-pipe splice fails with -EINVAL. A concurrent directory mutation and getdents() call can advance f_pos and refresh the filesystem's revalidation cookie before that failure restores only the old position. The next ext2 readdir can then trust an offset inside a directory entry and copy data from the adjacent page to userspace. Only update an implicit file position when splice returns a non-negative result, matching read and write. Keep explicit offset updates unchanged. Fixes: 7995bd287134 ("splice: don't pass the address of ->f_pos to methods") Cc: stable@vger.kernel.org Signed-off-by: Daehyeon Ko <4ncienth@gmail.com> Link: https://patch.msgid.link/20261018051708.2422394-1-4ncienth@gmail.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursbacking-file: always end a queued writeChris Mason
Writes to a loop device with direct I/O on an overlay file make the next freeze of the upper filesystem hang for ever. Every kiocb_start_write() needs a kiocb_end_write(). For a write that is queued, vfs_iocb_iter_write() leaves the end to the completion, and backing_aio_rw_complete() only calls kiocb_end_write() when IOCB_WRITE is set in the flags copied from the submitter. In-kernel submitters such as loop do not set that flag, so each queued write keeps the freeze protection of the backing filesystem. Direct writes to a loop device with direct I/O backed by an overlay file left fsfreeze of the ext4 upper filesystem, and a later touch there, blocked in D state. It takes write access to the node of the loop device, which root has by default, to attach the file and to write. The fix used here is to mark a write in struct backing_aio and to call kiocb_end_write() on completion of every marked write. Reproduced under qemu without KVM, on v7.3-rc6-21-g602042bf29f6 with earlier fixes of this series applied, with and without this change, once each. The kernel was not changed for the run. With this change fsfreeze finished in about a second. Not run: the nvmet and LIO file backends, which do not set IOCB_WRITE either, FUSE passthrough, and an xfs upper filesystem. Fixes: 2406a307ac7d ("ovl: implement async IO routines") Cc: stable@vger.kernel.org Signed-off-by: Chris Mason <mason@kernel.org> [amir: use aio->is_write to explicitly mark a write aio] Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://patch.msgid.link/20261029180319.2852090-1-amir73il@gmail.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
41 hoursiomap: only follow dio alignment requirement if specifiedQu Wenruo
After commit 4025185cf953 ("iomap: follow the alignment requirement for iomap_dio_hole_iter()"), generic/091 fails on both xfs and ext4. The reason is that ext4 and xfs (except COW write) do not require full block alignment for direct IO. They are totally fine reading a sub-block range. That commit fails any direct read of sub-block holes/prealloc, even those filesystems can handle it without any problem. Fix the regression by only follow the block alignment if the IOMAP_DIO_FSBLOCK_ALIGNED flag is set. Fixes: 4025185cf953 ("iomap: follow the alignment requirement for iomap_dio_hole_iter()") Reviewed-by: Pankaj Raghav(Samsung) <pankaj.raghav@linux.dev> Signed-off-by: Qu Wenruo <wqu@suse.com> Link: https://patch.msgid.link/0e89c49b6f7804081f4041007b81ac620a153830.1793307063.git.wqu@suse.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
43 hoursbacking-file: enforce append-only and immutable backing inodesChristian Brauner
FUSE passthrough opens the backing file anew whenever the FUSE file is opened. fuse_passthrough_open() passes the flags of that open to backing_file_open() which opens the backing file with vfs_open() and the credentials of the server. But vfs_open() doesn't go through may_open(). So the backing inode is never checked for S_APPEND and S_IMMUTABLE. The checks that did run were done on the FUSE inode and that one never has either flag. So anyone who may open the FUSE file for writing can overwrite an append-only backing file anywhere or write to an immutable one. The server only has to register the file and a read-only or even an O_PATH file descriptor is enough for that. Registering requires CAP_SYS_ADMIN but the writer can be any user that the server lets open the file. The FUSE inode is checked instead of the backing inode in a few more places: - do_mmap() refuses a shared mapping of an append-only file that was opened for writing. A FUSE file opened with O_RDWR | O_APPEND passes the open check and can then be mapped shared and written to at any offset. - fcntl(F_SETFL) and RWF_NOAPPEND refuse to take append mode away from a file on an append-only inode. On the FUSE file both succeed. A synchronous write still appends because the backing file was opened with O_APPEND. But an asynchronous write is submitted with the flags of the user's kiocb and lands at the given offset. Do the checks on the backing inode. backing_file_open() refuses to open an immutable inode for writing and an append-only inode for writing without O_APPEND, just like may_open(). backing_file_mmap() refuses a shared mapping of an append-only inode, just like do_mmap(). And writes and splices to a backing file in append mode fail if append mode was taken away from the user file. A FUSE file that was opened before the backing file became append-only can still write anywhere. That's what happens on the native filesystem as well and the backing file of such a file isn't in append mode. Two differences remain. F_SETFL succeeds and the next write fails. And FUSE reports EIO for a refused open because it turns every error from opening the backing file into EIO. overlayfs uses the same helpers but it mirrors S_APPEND and S_IMMUTABLE in its own inode and a chattr through the overlay never sets them on the upper inode. So for overlayfs this only changes something if the upper inode is changed behind the overlay's back. Fixes: 4a90451bbc7f ("fuse: implement open in passthrough mode") Reported-by: Chris Mason <mason@kernel.org> Cc: stable@vger.kernel.org # v6.9+ Link: https://patch.msgid.link/20261029-work-fs-ai-fixes-v1-2-88f22792f6f7@kernel.org Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
43 hoursaio: fix NULL deref when a fault races ring truncationChris Mason
The aio ring lives in a file on the aio pseudo filesystem and the ring VMA uses filemap_fault(). aio_ctx_aops doesn't have a ->read_folio because aio_setup_ring() puts all folios of the ring into the page cache. So a fault on the ring only works as long as it finds its folio in the page cache. If it doesn't, filemap_fault() calls ->read_folio without checking and we jump to NULL. We already fixed this twice this year. A forked child could inherit the ring mapping, fixed by commit c03ce4173c7b ("fs: aio: set VMA_DONTCOPY_BIT in mmap to fix NULL-pointer-dereference error"). And a partial mremap() could leave part of the ring mapped, fixed by commit 3adf7ae18bf4 ("fs: aio: reject partial mremap to avoid Null-pointer-dereference error"). Both times a VMA outlived the ring and the ring file was truncated under it. There's a third way to get there. kill_ioctx() and the error path of ioctx_alloc() unmap the ring with vm_munmap() and ignore the return value. If vm_munmap() has to wait for mmap_lock and a fatal signal is pending it returns -EINTR and the VMA stays. free_ioctx() then calls put_aio_ring_file() which truncates the ring file to zero. A fault that passed the i_size check in filemap_fault() before that doesn't find its folio anymore, allocates a new one and calls ->read_folio: fault on the ring io_destroy() with SIGKILL pending ================= ================================= vm_munmap() returns -EINTR filemap_fault() i_size check passes free_ioctx() put_aio_ring_file() truncate_setsize(inode, 0) no folio, allocate a new one filemap_read_folio() ->read_folio == NULL All that's needed is a second process that shares the mm. If a CLONE_VM child calls io_destroy() and gets SIGKILLed while it waits for mmap_lock the ring stays mapped for the threads of the parent. Any user can do that. Instead of plugging the routes one by one give the ring a ->read_folio that unlocks the folio and returns -EIO. All folios of a live ring are in the page cache so a fault can only end up there if the ring was truncated. The fault now gets SIGBUS. Nothing else reads the ring file and the aio filesystem uses noop_backing_dev_info so there's no readahead either. Making vm_munmap() unkillable in those two places would only close this one route and bring back what commit ae7987835643 ("mm: make vm_munmap killable") fixed. Fixes: 36bc08cc0170 ("fs/aio: Add support to aio ring pages migration") Cc: stable@vger.kernel.org Signed-off-by: Chris Mason <mason@kernel.org> Link: https://patch.msgid.link/20261029-work-fs-ai-fixes-v1-1-88f22792f6f7@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 daysMerge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linuxLinus Torvalds
Pull fscrypt fixes from Eric Biggers: - Add more checks to prevent encryption on "large block size" ext4 filesystems (s_blocksize > PAGE_SIZE), which isn't supported yet. There was already a mount-time check, but it wasn't enough. - Add missing memory barrier to fscrypt_find_mode_key() - Add missing zeroization in an error path * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: ext4: reject encrypted inodes when block size > page size ext4: refuse encryption when block size > page size fscrypt: Fix missing barrier in fscrypt_find_mode_key() fscrypt: Explicitly zeroize sw_secret in error path
2 daysMerge tag 'ntfs3_for_7.4' of ↵Linus Torvalds
https://github.com/Paragon-Software-Group/linux-ntfs3 Pull ntfs3 updates from Konstantin Komarov: "The bulk of this cycle is hardening against corrupted or maliciously crafted volumes. Most of these fixes come from fuzzing and KASAN reports. The main areas are: - $LogFile replay, where several unchecked on-disk sizes could make mount write past the MFT record buffer - MFT record and index parsing - extended attributes, where a bad $EA entry could leak up to 64K of kernel heap to userspace through getxattr() Reading a damaged compressed file could also return uninitialized page cache contents to userspace; that is fixed too. A few fixes affect healthy volumes as well: a heap overflow in fallocate(INSERT_RANGE) on small files, a use-after-free when a WOF-compressed file is opened for writing during a concurrent read, a lock-order deadlock in readdir, and stale disk data showing up in newly allocated clusters of compressed files. On the feature side there are new tracepoints covering mount, log replay, lookup, directory index, allocation, iomap and file I/O. There is also a new 'ugm' mount option (on by default): with ugm=0, newly created files don't get the WSL uid/gid/mode extended attributes, which Windows doesn't use. The rest is smaller correctness fixes and cleanups" * tag 'ntfs3_for_7.4' of https://github.com/Paragon-Software-Group/linux-ntfs3: (52 commits) ntfs3: add file I/O tracepoints ntfs3: add iomap tracepoints ntfs3: add allocation tracepoints ntfs3: add directory index tracepoints ntfs3: add create inode tracepoint ntfs3: add namei tracepoints ntfs3: add mount and log replay tracepoints fs/ntfs3: validate the EA value length in ntfs_read_ea() fs/ntfs3: handle partial allocation in attr_data_get_block_locked() ntfs3: fix mapping pairs bounds check for alignment fs/ntfs3: bound DeleteAttribute asize against rec->used in do_action ntfs3: release ni_lock before dir_emit in ntfs_readdir to fix deadlocks fs/ntfs3: bound CreateAttribute asize against record_size in do_action fs/ntfs3: do not mark frame pages uptodate on read error fs/ntfs3: prevent positive E_NTFS_NONRESIDENT from reaching writeback error handling fs/ntfs3: fix ntfs_fnd leak when compare function is missing fs/ntfs3: fix stale attr_b in attr_allocate_frame() fs/ntfs3: reject unaligned hole punching on compressed files fs/ntfs3: take ni_lock() once in ntfs_readdir() fs/ntfs3: reserve a compression unit in maxbytes_sparse ...
3 dayspidfs: don't let PIDFD_GET_INFO miss a reaped taskJosef Bacik
PIDFD_GET_INFO describes the task while there is one, and with PIDFD_INFO_EXIT its exit status once it has been reaped. pidfd_info() looks at the two in the wrong order and can miss both: pidfd_info() release_task() PIDFS_ATTR_BIT_EXIT is not set pidfs_exit() __unhash_process() get_pid_task() == NULL goto copy_out The ioctl succeeds with neither PIDFD_INFO_PID nor PIDFD_INFO_EXIT in the mask. If the task is unhashed a little later, after get_pid_task(), its pid reads as 0 and the ioctl fails with -ESRCH, although the caller asked for the exit information and it is available by now. The second case does not even need an exit. When a sub-thread execs, de_thread() hands the leader's pid over to it and releases the old leader. A caller that got hold of the old leader reports the tid of the sub-thread as the pid, or -ESRCH for a process that is alive. Look up the task first. pidfs_exit() runs before the task is unhashed, so a caller that finds no task finds the exit information; this needs a barrier on both sides because taking tasklist_lock does not order the store in pidfs_exit() against the one in detach_pid(). And start over if the task no longer owns the pid when all the fields have been read: then there is either exit information or another task. Go by the pid for that check and for the pid we report, not by ->thread_pid of the task. exchange_tids() moves the pid to the exec'ing thread before it updates ->thread_pid of either task. A caller that finds the new leader in between would read the old tid of the sub-thread from ->thread_pid, and a check of ->thread_pid would restart until the exec'ing thread gets to its store. On PREEMPT_RT that thread can be preempted with tasklist_lock held and can't move to another CPU. If the RT task that preempted it calls PIDFD_GET_INFO, the ioctl spins until the exec'ing thread gets the CPU back, and that never happens if the exec'ing thread is an RT task of lower priority. Christian Brauner <brauner@kernel.org> says: Go by @pid instead of ->thread_pid of the task for the reported pid and for the restart check. Fixes: 7477d7dce48a ("pidfs: allow to retrieve exit information") Fixes: cdda1f26e74b ("pidfd: add ioctl to retrieve pid info") Cc: stable@vger.kernel.org Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 dayslibfs: hold one mount reference for all pinsChristian Brauner
simple_pin_fs() takes a reference on the internal mount for every pin and simple_release_fs() drops it again. So every debugfs, tracefs, securityfs, configfs, apparmorfs, drm and vfio file that is created and removed costs a mntget() and a mntput() on that mount. The mount comes from vfs_kern_mount() and not from kern_mount(), so it never gets MNT_NS_INTERNAL and mntput_no_expire() can't take the fast path for it. Each of those mntput()s ends up in mntput_no_expire_slowpath(), takes mount_lock and sums the per-cpu counters in mnt_get_count() to find out whether it dropped the last reference. It never did for anything but the last pin, that's what the pin count is for. The reference per pin never bought anything. The pin count under pin_fs_lock is what keeps the mount alive, nothing looks at the mount's refcount to find out how many pins there are and the mount is only torn down once the last pin is gone. Keep the reference vfs_kern_mount() returned as the one reference the pins hold. Further pins only bump the count and the last simple_release_fs() drops the reference. The refcount of a pinned mount now changes when it is first pinned and when the last pin goes away. Everything in between is a spinlock and a counter. Reported-by: kernel test robot <yi1.lai@intel.com> Closes: https://lore.kernel.org/oe-lkp/202610130959.d3ca4cfa-lkp@intel.com Link: https://patch.msgid.link/20261026-work-libfs-pin_fs-v1-1-99ef52ee10a3@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysproc: don't let an entry below /proc/<pid>/net be a mountpointChristian Brauner
proc_net_d_revalidate() always returns 0 so that a dentry below /proc/<pid>/net is never reused after setns(). So lookup_fast() will end up calling d_invalidate(), which unhashes the dentry and detaches every mount on it, in every mount namespace; including locked mounts. Then lookup_slow() creates a new dentry for the same entry. So a mount on /proc/<pid>/net/dev succeeds and goes away with the first lookup of the name by anybody with search permission on the directory. Given it's 0555 that's everyone's grandma. A mask on such a name hides nothing as the repro below shows. Treat those entries like I did fd/, fdinfo/ and map_files/ and refuse to mount on them in the first place. It's nonsensical theater otherwise: procnet net/dev stat // SPDX-License-Identifier: GPL-2.0 /* * procnet: cover an entry of /proc/<pid>/ with a bind mount, lock the mount, * then look the name up. * * The first task stays alive, <pid> is its pid. The "container" task has its * own mount namespace. There it binds a mask on /proc/<pid>/<name>. It drops to * uid 1000 and enters a new user namespace with a new mount namespace, so that * the mask is locked. Then one task looks the name up: * * stat the container calls stat() on the name * umount the container calls umount2(MNT_DETACH) on the name * nobody a task with uid 65534 in the first namespaces calls stat() * * The container lists its mounts before and after (that does not look the * name up) and then reads the name. MASK is fine. Anything else means that * the lookup uncovered the entry. * * usage: procnet <name> stat|umount|nobody * name "status" is the control, "net/dev" is a file below net, "net/stat" is * a directory below net */ #define _GNU_SOURCE #include <dirent.h> #include <errno.h> #include <fcntl.h> #include <sched.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <sys/mount.h> #include <sys/prctl.h> #include <sys/stat.h> #include <sys/wait.h> #define WORK "/run/pn" static char target[128]; static void die(const char *what) { fprintf(stderr, "FATAL %s: %s\n", what, strerror(errno)); exit(2); } static void write_str(const char *path, const char *s, int flags) { int fd = open(path, O_WRONLY | flags, 0644); if (fd < 0 || write(fd, s, strlen(s)) < 0) die(path); close(fd); } /* list the mounts below /proc without a lookup of the target */ static void mounts(const char *when) { char line[512]; FILE *f = fopen("/proc/self/mountinfo", "r"); int n = 0; if (!f) die("mountinfo"); while (fgets(line, sizeof(line), f)) { if (!strstr(line, " /proc/")) continue; printf("container: %s: mount: %s", when, line); n++; } fclose(f); if (!n) printf("container: %s: nothing is mounted below /proc\n", when); } static void show(const char *when, int isdir) { char buf[48] = ""; int fd; if (isdir) { struct dirent *de; DIR *d = opendir(target); int hit = 0; if (!d) { printf("container: %s: opendir(%s) = %s\n", when, target, strerror(errno)); return; } printf("container: %s: readdir(%s) =", when, target); while ((de = readdir(d))) { if (de->d_name[0] == '.') continue; printf(" %s", de->d_name); hit |= strcmp(de->d_name, "MASK"); } closedir(d); printf("%s\n", hit ? " <-- HIT" : ""); return; } fd = open(target, O_RDONLY); if (fd < 0) { printf("container: %s: open(%s) = %s\n", when, target, strerror(errno)); return; } if (read(fd, buf, sizeof(buf) - 1) < 0) die("read"); close(fd); if (strchr(buf, '\n')) *strchr(buf, '\n') = 0; printf("container: %s: read(%s) = \"%s\"%s\n", when, target, buf, strncmp(buf, "MASK", 4) ? " <-- HIT" : ""); } int main(int argc, char **argv) { const char *name = argc > 1 ? argv[1] : "net/dev"; const char *op = argc > 2 ? argv[2] : "stat"; int isdir = !strcmp(name, "net/stat"); int to_host[2], to_cont[2]; struct stat st; pid_t pid; char c; setvbuf(stdout, NULL, _IOLBF, 0); snprintf(target, sizeof(target), "/proc/%d/%s", getpid(), name); if (unshare(CLONE_NEWNS) || mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) die("unshare"); mkdir(WORK, 0755); if (mount("W", WORK, "tmpfs", 0, NULL)) die("mount W"); write_str(WORK "/mask", "MASK", O_CREAT); mkdir(WORK "/maskdir", 0755); write_str(WORK "/maskdir/MASK", "MASK", O_CREAT); if (pipe(to_host) || pipe(to_cont)) die("pipe"); pid = fork(); if (pid < 0) die("fork"); if (!pid) { if (unshare(CLONE_NEWNS)) die("container unshare"); if (mount(isdir ? WORK "/maskdir" : WORK "/mask", target, NULL, MS_BIND, NULL)) { printf("container: bind the mask on %s: %s\n", target, strerror(errno)); exit(0); } printf("container: bind the mask on %s: ok\n", target); if (setgid(1000) || setuid(1000) || prctl(PR_SET_DUMPABLE, 1)) die("setuid"); /* lock the mount: a new user namespace with a copy of the tree */ if (unshare(CLONE_NEWUSER | CLONE_NEWNS)) die("container userns"); write_str("/proc/self/setgroups", "deny", 0); write_str("/proc/self/uid_map", "0 1000 1", 0); write_str("/proc/self/gid_map", "0 1000 1", 0); mounts("before"); errno = 0; if (!strcmp(op, "stat")) { stat(target, &st); printf("container: stat(%s): %s\n", target, strerror(errno)); } else if (!strcmp(op, "umount")) { umount2(target, MNT_DETACH); printf("container: umount2(%s, MNT_DETACH): %s\n", target, strerror(errno)); } else if (write(to_host[1], "g", 1) != 1 || read(to_cont[0], &c, 1) != 1) { die("sync"); } mounts("after"); show("after", isdir); exit(0); } close(to_host[1]); if (read(to_host[0], &c, 1) == 1) { pid_t p2 = fork(); if (!p2) { if (setgid(65534) || setuid(65534)) die("setuid"); errno = 0; stat(target, &st); printf("nobody: uid %u: stat(%s): %s\n", getuid(), target, strerror(errno)); exit(0); } waitpid(p2, NULL, 0); if (write(to_cont[1], "g", 1) != 1) die("sync"); } waitpid(pid, NULL, 0); return 0; } Fixes: 1fde6f21d90f ("proc: fix /proc/net/* after setns(2)") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20261024-work-procfs-fixes-v1-1-46b03c3a8fac@kernel.org Acked-by: Jan Kara <jack@suse.cz> Reviewed-by: Aleksa Sarai <aleksa@amutable.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysmount: refuse setns() with a shared fs_struct againJosef Bacik
mntns_install() refuses to switch the mount namespace of a task that shares its fs_struct, since root and cwd of the others would move to a namespace they are not in. It looks at nsset->fs for that. If more than the mount namespace is asked for, that is a private copy made by prepare_nsset(), which has one user by definition; commit_nsset() then writes root and cwd of the copy to the fs_struct of the task. A thread of a process with two threads, pidfd of a task in another mount namespace: setns(pidfd, CLONE_NEWNS) -EINVAL setns(pidfd, CLONE_NEWNS | CLONE_NEWUTS) 0 and after the second call the other thread, still in the old mount namespace, has lost its cwd (/tmp became /) and sees the mounts of the other namespace under /. Look at the fs_struct that is going to be changed. The second call then fails with -EINVAL like the first one. Fixes: 303cc571d107 ("nsproxy: attach to namespaces via pidfds") Cc: stable@vger.kernel.org # v5.8+ Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysnamei: don't assert S_ISDIR on a stale rcu-walk inodeJosef Bacik
lookup_inode_permission_may_exec() asserts that it is only ever handed a directory, on the grounds that link_path_walk() has already checked d_can_lookup(). In rcu-walk that does not follow. step_into() samples ->d_inode and validates it against ->d_seq, but link_path_walk() loads ->d_flags again afterwards, and nothing orders that load against changes of the dentry: CPU0 (rcu-walk of "x/y") CPU1 step_into(x) inode = x->d_inode // regular file read_seqcount_retry(&x->d_seq) == 0 nd->inode = inode unlink("x") d_delete() // x goes negative mkdir("x") d_instantiate() // same dentry d_can_lookup(x) // true now may_lookup() VFS_BUG_ON_INODE(!S_ISDIR(nd->inode->i_mode)) With CONFIG_PREEMPT_RCU the walker can be preempted in that window, so it is not limited to a few instructions. mkdir() only gets the same dentry back if the filesystem keeps negative dentries around. tmpfs doesn't, ext4 does. Apart from the assertion the stale inode is harmless, and has been there since before the assertion was added: nd->seq no longer matches x->d_seq, so lookup_fast(), follow_dotdot_rcu() and try_to_unlazy() all fail with -ECHILD and the walk is redone in ref-walk, whatever the permission check on the old inode said. Keep the assertion for ref-walk, where the dentry is pinned and can't change type, and skip it for rcu-walk. No change for kernels without CONFIG_DEBUG_VFS. Fixes: e631df89cd5d ("fs: speed up path lookup with cheaper handling of MAY_EXEC") Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysiomap: keep large chunks from defeating the bio capJosef Bacik
For integrity I/O a bio must not grow beyond max_integrity_io_size() because the integrity buffer is a single allocation of at most 2 MiB. Writeback and buffered reads check that before adding to a bio: bio->bi_iter.bi_size > iomap_max_bio_size(iomap) - len The subtraction is done in size_t and wraps if len alone is above the limit. The check then never fires and the bio grows until it runs out of bio_vecs. That's easy to hit. The limit is also capped by the maximum segment size which is 64 KiB for SCSI hosts that don't set it, such as lpfc and qla2xxx, and XFS uses folios of up to 2 MiB. Writeback of a preallocated 300 MiB file then builds a single bio that needs 4.7 MiB of PI with 512 byte sectors and 8 byte tuples. That's more than kmalloc() can do, so bio_integrity_alloc_buf() falls back to a 2 MiB mempool element and generating the PI writes 2.7 MiB past its end. Check the length on its own first. A chunk above the limit still gets a bio of its own which is never larger than a folio. Fixes: 0b10a370529c ("iomap: support T10 protection information") Cc: stable@vger.kernel.org # v7.1+ Signed-off-by: Josef Bacik <josef@toxicpanda.com> Link: https://patch.msgid.link/20261029-work-iomap-ai-fixes-v1-2-7eda63bc1b13@kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysiomap: don't mark unwritten parts of a folio uptodateChristian Brauner
For a buffered write into a hole, an unwritten or new extent, or past EOF __iomap_write_begin() zeroes the parts of the blocks outside of the write and then marks the blocks uptodate. That includes the range of the write itself which still holds whatever was in the folio before. It only becomes valid once the copy from userspace has filled it in. But the copy can come up short and __iomap_write_end() only rejects a short copy if the folio isn't uptodate. If the zeroed blocks were all that was missing the folio is uptodate by then, the short copy is accepted, and the rest of the range is exposed to readers and can end up on disk. A source buffer that ends in an unmapped page is enough: ftruncate(fd, 4096); pwrite(fd, p, 3000, 100); /* 16 bytes at p, then PROT_NONE */ pread(fd, buf, 4096, 0); The write returns 16 and the read returns 2984 bytes of whatever was in that page before. If other blocks of the folio aren't uptodate the short copy is rejected but the zeroed blocks keep their uptodate bits and the retry with the copied length leaves the same bytes behind. Only mark blocks uptodate in __iomap_write_begin() after reading them. __iomap_write_end() marks the zeroed blocks uptodate once the copy has succeeded and rejects a short copy. Willy reported this back in 2024 (cf. [1]) and Zhang Yi posted the same fix (cf. [2]) but it never got merged. [1]: https://lore.kernel.org/all/ZqsN5ouQTEc1KAzV@casper.infradead.org [2]: https://lore.kernel.org/all/20240812121159.3775074-6-yi.zhang@huaweicloud.com Fixes: 9dc55f1389f9 ("iomap: add support for sub-pagesize buffered I/O without buffer heads") Reported-by: Josef Bacik <josef@toxicpanda.com> Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20261029-work-iomap-ai-fixes-v1-1-7eda63bc1b13@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysxattr: always invoke cap_convert_nscap() for security.capability writesDominik Maier
Commit 8db6c34f1dbc ("Introduce v3 namespaced file capabilities") changed cap_inode_setxattr() to return 0 unconditionally for XATTR_NAME_CAPS ("security.capability") and moved capability validation into cap_convert_nscap(), but placed the call inside the "if (size)" block in setxattr(). Commit 7c03e2cda4a5 ("vfs: move cap_convert_nscap() call into vfs_setxattr()") preserved that "size &&" condition in vfs_setxattr(): if (size && strcmp(name, XATTR_NAME_CAPS) == 0) { error = cap_convert_nscap(idmap, dentry, &value, size); ... } For security.* extended attributes, xattr_permission() skips inode_permission(MAY_WRITE) and leaves permission checks to the security module, while cap_inode_setxattr() returns 0 for XATTR_NAME_CAPS assuming cap_convert_nscap() has already validated the write. Because __vfs_setxattr() treats size == 0 as an empty attribute write (setting value = "") rather than a removal, calling setxattr(2) on "security.capability" with size == 0 bypasses cap_convert_nscap() and allows an unprivileged caller without CAP_SETFCAP or write permission on the target inode to write a 0-byte security.capability xattr (or overwrite an existing one). When that binary is subsequently executed, get_vfs_caps_from_disk() reads the 0-byte security.capability xattr and fails the size < sizeof(magic_etc) check with -EINVAL, causing execve(2) to fail with -EINVAL. Always invoke cap_convert_nscap() when strcmp(name, XATTR_NAME_CAPS) == 0 regardless of size, so that 0-byte writes hit the existing !*ivalue / !validheader() checks in cap_convert_nscap() and are rejected with -EINVAL. Fixes: 8db6c34f1dbc ("Introduce v3 namespaced file capabilities") Signed-off-by: Dominik Maier <dmnk@google.com> Link: https://patch.msgid.link/20261022232119.2537209-1-dmnk@google.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 dayswriteback: don't kick a missing wb for dontcache writesJosef Bacik
With CONFIG_CGROUP_WRITEBACK, inode->i_wb stays NULL until the inode is dirtied for the first time (folio_account_dirtied(), __mark_inode_dirty() or wbc_attach_fdatawrite_inode() attach it). generic_write_sync() calls filemap_dontcache_kick_writeback() for every IOCB_DONTCACHE write, including O_DIRECT ones, which never dirty the page cache. The function then passes the NULL returned by unlocked_inode_to_wb_begin() to wb_has_dirty_io(): fd = open("/dev/ram0", O_WRONLY | O_DIRECT); pwritev2(fd, &iov, 1, 0, RWF_DONTCACHE); BUG: KASAN: null-ptr-deref in filemap_dontcache_kick_writeback+0xec Oops: general protection fault, probably for non-canonical address RIP: 0010:filemap_dontcache_kick_writeback+0xfd/0x7a0 The task dies inside rcu_read_lock(). blkdev_write_iter() gets there for any block device whose page cache has not been dirtied yet. nfs_file_direct_write() calls generic_write_sync() the same way. An inode without a wb has never had dirty pages, so there is nothing to flush: skip the kick. Fixes: e1bf79628453 ("mm: kick writeback flusher for IOCB_DONTCACHE with targeted dirty tracking") Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
4 daysfsverity: Set S_VERITY only after rollback is no longer possibleEric Biggers
Commit f77f281b6118 ("fsverity: use a hashtable to find the fsverity_info") changed the implementation of FS_IOC_ENABLE_VERITY to make concurrent reads start going through fsverity verification slightly earlier than they did before. Instead of it happening when enable_verity() calls fsverity_set_info(), it now happens when ->end_enable_verity() sets S_VERITY. However, ext4 and btrfs can roll back verity after they set S_VERITY, causing a use-after-free. Fix that by making ext4 and btrfs set S_VERITY only after rollback is no longer possible. On failure, don't roll back S_VERITY, but do roll back the filesystem-specific verity flag. Also update enable_verity() to handle any future instances of this bug more safely by warning and *not* freeing the fsverity_info. Finally, tweak some comments. Clarify one, and move information from another to its proper place in the comment for ->end_enable_verity(). Fixes: f77f281b6118 ("fsverity: use a hashtable to find the fsverity_info") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/20261025204807.122875-1-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
4 daysfsverity: Tell LSMs about signature only after verity is enabledEric Biggers
FS_IOC_ENABLE_VERITY calls security_inode_setintegrity() before verity has finished being enabled. That's broken because enabling verity can still fail at that point, e.g. due to insufficient xattr space. Afterwards, arbitrary contents can be written to the file, which doesn't actually have verity enabled. The in-core inode stays the same, so the LSM considers it to have verity enabled with a valid signature. (Or rather, in the case of IPE, which is the only LSM that implements security_inode_setintegrity(), it also checks IS_VERITY(), which can be bypassed by enabling verity with no signature after the file writes.) Fix this by moving the call to security_inode_setintegrity() out of fsverity_verify_signature() and into a new function that is called from the appropriate places. Fixes: 7c373e4f1445 ("fsverity: expose verified fsverity built-in signatures to LSMs") Cc: stable@vger.kernel.org Reviewed-by: Fan Wu <wufan@kernel.org> Tested-by: Fan Wu <wufan@kernel.org> Link: https://patch.msgid.link/20261025204534.122506-1-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
4 daysfsverity: Be more careful with return value of ->get_verity_descriptor()Eric Biggers
If fsverity_operations::get_verity_descriptor() returns that the verity descriptor has 0 size, then a zero-size buffer is allocated to hold it, and it's called again with bufsize=0. But bufsize=0 is a special case that says to return the actual size. If in the meantime the filesystem has decided that the size is some actually valid size, it will return that size, and then validate_fsverity_descriptor() will read from ZERO_SIZE_PTR and crash. Of course, for the filesystem to misbehave in that strange way, it generally would require direct writes to the block device. Regardless, fsverity_get_descriptor() might as well guard against it. Make it do so. Specifically, validate that the first call to ->get_verity_descriptor() returns at least the minimum descriptor size, and validate that the second call returns the same size as the first. Fixes: fd2d1acfcadf ("fs-verity: add the hook for file ->open()") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20261025203831.120095-1-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
4 daysfsverity: Explicitly require FMODE_READ to retrieve hashesEric Biggers
The comment in fsverity_ioctl_read_metadata(), which justifies not checking for FMODE_READ, doesn't consider that the nonstandard access mode 3 (ioctl-only) exists. Opening an ioctl-only fd generally requires read (and write) permission. However, there are gaps with certain LSMs: an ioctl-only fd requests read (and write) permission via security_inode_permission, but not security_file_open. With certain LSMs relying on the latter, such as Landlock and AppArmor, an ioctl-only fd can be opened without the LSM granting read (and write) permission. Since FS_IOC_READ_VERITY_METADATA returns hashes of file contents blocks, it should require read permission. This also applies to FS_IOC_MEASURE_VERITY, which returns a hash for the whole file. Meanwhile, ioctl-only fds are a rarely-used feature, not known to be used with either ioctl. Therefore, just disallow these ioctls on ioctl-only file descriptors, similar to what was already done with FS_IOC_ENABLE_VERITY. More specifically, explicitly check for FMODE_READ. This also covers write-only fds to non-verity files which otherwise would have failed with ENODATA. This change in error code for write-only fds should be fine too, as these ioctls cannot be usefully used with write-only fds anyway, but it's worth noting as another technicality. Fixes: 4dd893d832cf ("fs-verity: implement FS_IOC_MEASURE_VERITY ioctl") Fixes: e17fe6579de0 ("fs-verity: add FS_IOC_READ_VERITY_METADATA ioctl") Cc: stable@vger.kernel.org Reviewed-by: Andrey Albershteyn <aalbersh@kernel.org> Link: https://patch.msgid.link/20261022211522.1489943-1-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
4 daysntfs3: add file I/O tracepointsBaolin Liu
Add ntfs3 tracepoints for file I/O operations. This adds trace events for ntfs_file_read_iter() and ntfs_file_write_iter() to help observe file read and write activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add iomap tracepointsBaolin Liu
Add ntfs3 tracepoints for iomap operations. This adds trace events for ntfs_iomap_begin() and ntfs_iomap_end() to help observe iomap mapping activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add allocation tracepointsBaolin Liu
Add ntfs3 tracepoints for allocation operations. This adds trace events for attr_allocate_clusters(), attr_set_size_ex(), and attr_data_get_block() to help observe cluster allocation, size changes, and block mapping activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add directory index tracepointsBaolin Liu
Add ntfs3 tracepoints for directory index operations. This adds trace events for dir_search_u(), indx_find(), indx_insert_entry(), and indx_delete_entry() to help observe directory index lookup, insert, and delete activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add create inode tracepointBaolin Liu
Add an ntfs3 tracepoint for inode creation. This adds a trace event for ntfs_create_inode() to help observe inode creation activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add namei tracepointsBaolin Liu
Add ntfs3 tracepoints for namei operations. This adds trace events for ntfs_lookup() and ntfs_rename() to help observe directory lookup and rename activity. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: add mount and log replay tracepointsBaolin Liu
Add ntfs3 tracepoints for mount and log replay paths. This adds trace events for ntfs_fill_super(), ntfs_init_from_boot(), and log_replay() to help observe mount setup, boot sector parsing, and $LogFile replay results. Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysfs/ntfs3: validate the EA value length in ntfs_read_ea()Yuejie Shi
ntfs_read_ea() checks the $EA list for consistency, but it only recomputes the packed size of an entry when the entry's own size field is zero: for (off = 0; off < size; off += ea_size) { const struct EA_FULL *ef = Add2Ptr(ea_p, off); u32 bytes = size - off; ... if (ef->size) { ea_size = le32_to_cpu(ef->size); if (ea_size > bytes) goto out1; continue; /* <- elength never checked */ } ... ea_size = ALIGN(struct_size(ef, name, 1 + ef->name_len + le16_to_cpu(ef->elength)), 4); if (ea_size > bytes) goto out1; } ef->size is non-zero for every entry except the last one, and it is what ntfs3 itself writes (ntfs_set_ea() stores exactly that aligned packed size), so in practice elength is not validated at all. find_ea() then uses unpacked_ea_size(), which also prefers ea->size when it is set, so it agrees and hands the entry back. ntfs_get_ea() copies elength bytes with no further bound of its own: len = le16_to_cpu(ea->elength); ... if (len > size) { /* size is the *caller's* buffer */ err = -ERANGE; ... } memcpy(buffer, ea->name + ea->name_len + 1, len); so a caller that supplies a large enough buffer receives up to 64 KiB of whatever follows the small $EA allocation -- straight to userspace via getxattr(2). Compute the packed size unconditionally and require it to fit in the entry. Hoist the "bytes < offsetof(struct EA_FULL, name)" test above the ef->size branch as well: name_len and elength were being read there without it, which is itself a small over-read of the kmalloc'd buffer when fewer than 8 bytes are left. The old "bytes < sizeof(ef->size)" test is subsumed by it. # mkntfs image; create /mnt/ntfs/poc with user.ntfs6 set, then rewrite # that EA_FULL's elength from 0xf to 0xff00 on the raw device mount -t ntfs3 -o ro /dev/vda /mnt/ntfs getxattr("/mnt/ntfs/poc", "user.ntfs6", buf, 128 * 1024); BUG: KASAN: slab-out-of-bounds in ntfs_get_ea+0x294/0x3e0 Read of size 65280 at addr ffff0000cca53acf by task xattr_probe/142 __asan_memcpy+0x3c/0xa0 ntfs_get_ea+0x294/0x3e0 ntfs_getxattr+0x284/0x318 __vfs_getxattr+0x104/0x160 vfs_getxattr+0x1b4/0x1e0 do_getxattr+0xcc/0x230 path_getxattrat+0x184/0x270 __arm64_sys_getxattr+0x64/0x80 Allocated by task 142: __kmalloc_noprof+0x294/0x668 ntfs_read_ea+0x1e4/0x420 ntfs_get_ea+0x2c8/0x3e0 The buggy address belongs to the object at ffff0000cca53a80 which belongs to the cache kmalloc-96 of size 96 The object being over-read is the one ntfs_read_ea() just allocated, and it is 96 bytes. Entries written by ntfs3 and by Windows set size to the aligned packed size, so the new test does not reject anything a working filesystem produces. Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") Cc: stable@vger.kernel.org Signed-off-by: Yuejie Shi <syjcnss@gmail.com> [almaz.alexandrovich@paragon-software.com: applied as-is, logic is the same but the code is cleaner] Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysfs/ntfs3: handle partial allocation in attr_data_get_block_locked()Slawomir Stepien
When allocating clusters for a sparse or compressed attribute in attr_data_get_block_locked(), the requested virtual cluster number (vcn0) is aligned down to a frame boundary (vcn). The function then attempts to allocate a full frame of clusters. If the disk is nearly full and highly fragmented, attr_allocate_clusters() might only manage to allocate a small fragment and return success with a partial allocation length. If this partial allocation is so small that it does not even reach the originally requested vcn0 (i.e., end <= vcn0), vcn0 remains unallocated (a sparse hole). When the code subsequently calls run_lookup_entry() for vcn0, it finds the original SPARSE_LCN entry, which triggers a WARN_ON(1). Fix this by adding a check to verify if the partial allocation reached vcn0. If it did not (vcn0 >= end), treat this as an -ENOSPC failure and jump to the undo1 label. This safely rolls back the partial allocation, restores the original size, and repacks the runs, leaving the inode in a consistent state before returning the error to the caller. WARNING: fs/ntfs3/attrib.c:1236 at attr_data_get_block_locked+0x1980/0x25d0 fs/ntfs3/attrib.c:1236 RIP: 0010:attr_data_get_block_locked+0x1980/0x25d0 fs/ntfs3/attrib.c:1236 Call Trace: <TASK> attr_data_get_block+0x1f1/0x2a0 fs/ntfs3/attrib.c:979 ntfs_fallocate+0xd3d/0xf70 fs/ntfs3/file.c:670 vfs_fallocate+0x663/0x7f0 fs/open.c:338 ksys_fallocate fs/open.c:362 [inline] __do_sys_fallocate fs/open.c:367 [inline] __se_sys_fallocate fs/open.c:365 [inline] __x64_sys_fallocate+0xbf/0x110 fs/open.c:365 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK> Fixes: 099ef9ab9203 ("fs/ntfs3: implement iomap-based file operations") Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot Reported-by: syzbot+7be6ad5cb228286af3e3@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7be6ad5cb228286af3e3 Link: https://syzkaller.appspot.com/ai_job?id=3c9dee6e-001d-4972-8bf6-f6c960708246 Signed-off-by: Slawomir Stepien <sst@poczta.fm> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: fix mapping pairs bounds check for alignmentHongling Zeng
In the UpdateMappingPairs action, the expansion check compares the unaligned new attribute size with the available record space. The new size is aligned to an 8-byte boundary before the mapping pairs are updated, so the check can underestimate the required space by up to seven bytes. Use the aligned size in the expansion check to ensure that the subsequent update cannot exceed the available record space. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Cc: stable@vger.kernel.org Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysfs/ntfs3: bound DeleteAttribute asize against rec->used in do_actionHyeontae Lee
In do_action()'s DeleteAttribute case (fslog.c:3316), attr is Add2Ptr(rec, roff) with roff taken from the on-disk lrh->record_off, and asize = le32_to_cpu(attr->size) is read straight out of the MFT record: asize = le32_to_cpu(attr->size); used = le32_to_cpu(rec->used); if (!check_if_attr(rec, lrh)) goto dirty_vol; ... memmove(attr, Add2Ptr(attr, asize), used - asize - roff); check_if_attr() (fslog.c:2869) walks the attribute chain from rec->attr_off and returns o == ro. Its loop breaks on ATTR_END, so ro may legitimately equal the offset of the ATTR_END marker; that is exactly how CreateAttribute appends to a record. But check_file_record()'s walk (fslog.c:2831) also stops at ATTR_END, so check_attr() never inspects the bytes there. When roff is the ATTR_END offset, those never-validated bytes are what gets read as attr->size, and used - asize - roff underflows. The read itself is also unbounded: roff is a u16 and attr->size is dereferenced at fslog.c:3317, before check_if_attr() has constrained roff at all, so it can be up to ~64K past a record_size-sized object. Commit 0ca0485e4b2e ("fs/ntfs3: validate rec->used in journal-replay file record check") added at fslog.c:2844 if (used < PtrOffset(rec, attr) + sizeof(attr->type)) return false; and its changelog names this very memmove. It bounds rec->used against the ATTR_END offset; it does not bound asize. With record_size 0x400, attr_off 0x38, a valid three-attribute chain ending in ATTR_END at 0x158 and used 0x160, a record whose four bytes at 0x15c read 0x100 gives used - asize - roff = 0x160 - 0x100 - 0x158 = 0xffffff08 i.e. a ~4 GiB memmove whose source and destination both run off the end of rec, a kmalloc(sbi->record_size) object (record.c:105). The equivalent non-replay path already refuses this. mi_remove_attr() performs the same removal and starts with (record.c:548): if (aoff + asize > used) return false; Apply the same bound, spelled as a subtraction to match the neighbouring cases, and move the attr->size read after check_if_attr() so that the header is known to lie inside the record before it is dereferenced. Requiring roff + SIZEOF_RESIDENT <= used rejects the ATTR_END offset without rejecting any real attribute: for an attribute the walk validated, roff + asize <= off(ATTR_END) <= used - 4, and any attribute a DeleteAttribute record can legitimately name carries a full resident header, so roff + SIZEOF_RESIDENT <= roff + asize <= used - 4. check_attr() itself imposes no lower bound on asize, so a crafted sub-header asize can still pass the first test; the second test then bounds it and the memmove stays inside the record. Reproduced by mounting a crafted image on v7.2-rc5, which already contains 0ca0485e4b2e, under KASAN. The image is an ordinary mkfs.ntfs volume with four bytes of one MFT record changed and a crafted $LogFile: BUG: KASAN: slab-out-of-bounds in do_action.isra.0+0x3211/0x83c0 Read of size 4294967048 at addr ffff888002423258 by task mount/66 CPU: 1 UID: 0 PID: 66 Comm: mount Not tainted 7.2.0-rc5 #3 Call Trace: kasan_report+0xce/0x100 kasan_check_range+0x105/0x1b0 __asan_memmove+0x23/0x60 do_action.isra.0+0x3211/0x83c0 log_replay+0x920a/0xd300 ntfs_loadlog_and_replay+0x3ef/0x510 ntfs_fill_super+0x1d23/0x4550 get_tree_bdev_flags+0x2ef/0x550 vfs_get_tree+0x82/0x2f0 fc_mount+0x10/0x1b0 path_mount+0x517/0x1df0 __x64_sys_mount+0x20b/0x270 do_syscall_64+0xf9/0x540 entry_SYSCALL_64_after_hwframe+0x77/0x7f Allocated by task 66: __kasan_kmalloc+0x8f/0xa0 __kmalloc_noprof+0x1b4/0x460 mi_init+0x81/0x110 mi_get+0x6a/0x220 do_action.isra.0+0x1dbf/0x83c0 log_replay+0x920a/0xd300 ntfs_loadlog_and_replay+0x3ef/0x510 ntfs_fill_super+0x1d23/0x4550 The buggy address belongs to the object at ffff888002423000 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 600 bytes inside of allocated 1024-byte region [ffff888002423000, ffff888002423400) KASAN reports the source side because __asan_memmove() (mm/kasan/shadow.c:94) validates src before dest and returns without copying. Both ends are out of bounds, and on a kernel built without KASAN the copy is performed. rec->used is also left at used - asize by fslog.c:3323 before the memmove, so the record stays inconsistent even when the copy is suppressed; the same mount goes on to report "ino=1a, mi_enum_attr" and marks the volume dirty. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Hyeontae Lee <wonju345@naver.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysntfs3: release ni_lock before dir_emit in ntfs_readdir to fix deadlocksYun Zhou
ntfs_readdir() holds ni_lock while calling ntfs_read_hdr(), which calls dir_emit() to copy directory entries to userspace. If the user buffer triggers a page fault, the fault handler may need mmap_lock or mapping->invalidate_lock, creating lock-order inversions with paths that acquire those locks before ni_lock (e.g. ntfs_fallocate, mmap). Fix by releasing ni_lock before calling ntfs_read_hdr(): - For non-root index nodes, indx_read_ra() returns data in a kmalloc'd buffer (node->index) that remains valid after ni_unlock. - For the root index header, the data lives in the main MFT record whose lifetime is bound to the inode. i_rwsem shared prevents concurrent directory modifications, so it is safe to access after ni_unlock. Reported-by: syzbot+7736960b837908f3a81d@syzkaller.appspotmail.com Reported-by: syzbot+262a71e9d2faf8747085@syzkaller.appspotmail.com Reported-by: syzbot+cfc6e8106bec1c524f7d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7736960b837908f3a81d Closes: https://syzkaller.appspot.com/bug?extid=262a71e9d2faf8747085 Closes: https://syzkaller.appspot.com/bug?extid=cfc6e8106bec1c524f7d Fixes: d62cf685d12e ("fs/ntfs3: hold ni_lock across readdir metadata walk") Signed-off-by: Yun Zhou <yun.zhou@windriver.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysfs/ntfs3: bound CreateAttribute asize against record_size in do_actionHyeontae Lee
In do_action()'s CreateAttribute case (fslog.c:3286), attr2 points into the on-disk log record and asize = le32_to_cpu(attr2->size) is therefore attacker-controlled on mount. The guard bounds asize only against the log record itself, Add2Ptr(attr2, asize) > Add2Ptr(lrh, rec_len) where rec_len is the client data length, and separately bounds dlen against the MFT record. Nothing bounds asize against record_size, but all three writes that follow are into rec, a kmalloc(sbi->record_size) buffer allocated by mi_init() (record.c:105): memmove(Add2Ptr(attr, asize), attr, used - roff); memcpy(attr, attr2, asize); rec->used = cpu_to_le32(used + asize); With record_size 0x400, roff 0x38, used 0x160 and asize 0x800 the memcpy writes 2048 bytes at rec + 0x38, 0x438 bytes past the allocation, and rec->used is left at 0x960. dlen is 0x18 here, so the existing dlen check passes: dlen bounds nothing about the size of the copy. The equivalent non-replay path already refuses this. mi_insert_attr() performs the same insert and starts with (record.c:488): if (used + asize > sbi->record_size) return NULL; Apply the same bound, spelled as a subtraction to match the neighbouring clause. used <= record_size holds here because check_file_record() validates it (fslog.c:2826) and is called on this record at fslog.c:3172; roff <= used - 4 follows from check_if_attr() together with the ATTR_END check at fslog.c:2844, so bounding used + asize bounds both copies. The sibling WriteEndOfFileRecordSegment case does the equivalent check against record_size at fslog.c:3277. Reproduced by mounting a crafted image on v7.2-rc5 under KASAN: BUG: KASAN: slab-out-of-bounds in do_action.isra.0+0x41f6/0x83a0 Write of size 2048 at addr ffff888005c74838 by task mount/69 CPU: 0 UID: 0 PID: 69 Comm: mount Not tainted 7.2.0-rc5-00300-g8ba098e6b6ff #2 Call Trace: kasan_report+0xce/0x100 kasan_check_range+0x105/0x1b0 __asan_memcpy+0x3c/0x60 do_action.isra.0+0x41f6/0x83a0 log_replay+0x920a/0xd300 ntfs_loadlog_and_replay+0x3ef/0x510 ntfs_fill_super+0x1d23/0x4550 get_tree_bdev_flags+0x2ef/0x550 vfs_get_tree+0x82/0x2f0 fc_mount+0x10/0x1b0 path_mount+0x517/0x1df0 __x64_sys_mount+0x20b/0x270 do_syscall_64+0xf9/0x540 entry_SYSCALL_64_after_hwframe+0x77/0x7f Allocated by task 69: __kasan_kmalloc+0x8f/0xa0 __kmalloc_noprof+0x1b4/0x460 mi_init+0x81/0x110 mi_get+0x6a/0x220 do_action.isra.0+0x1db4/0x83a0 log_replay+0x920a/0xd300 ntfs_loadlog_and_replay+0x3ef/0x510 ntfs_fill_super+0x1d23/0x4550 The buggy address belongs to the object at ffff888005c74800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 56 bytes inside of allocated 1024-byte region [ffff888005c74800, ffff888005c74c00) Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Hyeontae Lee <wonju345@naver.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
4 daysMerge tag 'mm-stable-2026-10-25-19-27' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Pull more MM updates from Andrew Morton: - "mm: make VMA flag semantics explicit, eliminate VM_SPECIAL" (Lorenzo Stoakes): Replace VM_SPECIAL with helpers describing mapping ownership and behavior. Enforce the mmap flag rules and convert affected drivers, removing ambiguous tests shared by driver mappings and ordinary memory. - "support kselftest on nommu platform" (Hajime Tazaki): Add opt-in mmap and mremap tests for NOMMU systems. Teach the runner to avoid its fork-dependent timeout command and document the build and runtime requirements. - "mm/collapse: separate a collapse from its callers" (Kiryl Shutsemau): Separate huge-page collapse from caller policy. Replace khugepaged identity checks with explicit permissions, and separate scanning from collapse with the mmap_lock drop in one place. - "mm: implement and use vma_has_anon_rmap(), silence KCSAN" (Lorenzo Stoakes): Provide a common helper for testing whether a VMA has anonymous reverse mappings. Document the locking rules, annotate intentional concurrent reads for KCSAN, and convert the core MM callers. - "mm/sparse: remove SECTION_MARKED_PRESENT and further cleanups" (David Hildenbrand): Remove SECTION_MARKED_PRESENT in favor of the early-section flag. Simplify sparse memory initialization, section metadata handling and related PFN validity checks. - "sh: remove NUMA and SPARSEMEM support" (Mike Rapoport): Remove SuperH NUMA and SPARSEMEM support. The extra memory banks have been unusable since the NO_BOOTMEM conversion, leaving only the code and data overhead. - "mm: Unify device DAX and HugeTLB vmemmap population paths" (Muchun Song): Unify the generic device DAX and HugeTLB vmemmap population paths and shared tail-page handling. Remove the duplicate DAX machinery while retaining the powerpc radix implementation. - "kselftest: mm: fix some failure of split_huge_page_test" (Yeoreum Yun): Fix huge-page split tests racing with khugepaged recollapse. Use pagemap and page flags instead of VMA-boundary assumptions which fail when glibc has already enabled THP. - "memcg: move memcgid refcount to objcg to unpin dying memcgs" (Bingfang Guo): Let dying memcgs be freed while swapped-out shmem still holds their IDs. Move ID references to reparentable objcgs, with the necessary swap accounting and RCU lifetime changes. - "mm/truncate: fix data loss when truncating straddling large folios" (Zhang Yi): Preserve out-of-range data when truncating straddling large folios. Fix a lookup race and split-failure handling, and handle minimum folio orders for the forthcoming ext4 iomap buffered I/O path. - "mm/damon: introduce damos quota goal target metric complement flag" (SJ Park): Let DAMOS quota goals use a metric's complement, so utilization can also express free-memory goals without adding separate metrics. Add the sysfs interface, documentation and tests. - "arm64/mm: Standardize printing for pgtable entries" (Anshuman Khandual): Use the generic formatter for arm64 page-table entries, ready for future wider entries. Move the safe-PTE-update check out of the header to avoid an include cycle. - "mm: kmsan: fix iounmap metadata teardown" (Dima Koziuk): Fix KMSAN metadata leaks on iounmap and failed ioremap allocations. Free backing pages before removing their mappings, and share the teardown with partial-allocation cleanup. - "mm/damon/core: preserve quota state when constructing schemes" (Karl Mehltretter): Preserve running DAMOS quota state while validating parameter updates. Even rejected updates could reset accounting and exceed the quota window; add tests for both accepted and rejected updates. - "mm/vmalloc: fix vmalloc_dump_obj VA lookup" (Ye Liu): Fix vmalloc_dump_obj() lookups for last-page addresses and allocations spanning vmap zones. These allocations were being missed in diagnostic output. - "mm: various (urgent?) fixes" (David Hildenbrand): Fix mmap charge leaks and hugetlb use-after-free, wrong-address unmapping, stuck locks and endless faults. Also preserve reservations on failed mremap and handle stale userfaultfd bits. - "maple_tree: fix maple_range_64 crashes in RCU mode" (Dimitris Charisis): Fix pointer and metadata confusion during RCU destruction of maple_range_64 nodes, avoiding double frees and invalid accesses. Add a regression test; no in-tree user currently uses this combination. - "mm: fix hugetlb NR_HUGETLB accounting on folio migration" (Hongfu Li): Fix hugetlb migration and preallocation accounting so /proc/vmstat retains the correct count and memory.numa_stat follows the folio to its new node. - "mm/damon: fix a minor bug, clean code, and add a test" (SJ Park): Fix 32-bit DAMON age overflow which made old regions look young. Share hugetlb folio acquisition code and add a regression test for the previously fixed last-region skipping bug. - "mm/damon/core: cleanup code, reduce stack usage, and add kunit" (SJ Park): Reduce kdamond stack usage and remove unused enums. Add deterministic PSI quota-goal tests which do not depend on the machine's current memory pressure. - "mm/damon: fix the temporal goal tuner's size quota conversion" (Donggeun Yoo): Bound the temporal tuner's quota conversion to prevent overflow and zero effective quotas, which could stop schemes making progress. Add boundary tests. - "Don't use GFP_DMA when calling dma_alloc_coherent" (Baoquan He): Remove redundant GFP_DMA flags from coherent DMA allocation calls. The DMA API already selects the zone from device limits and ignores the caller's flag. - "kselftest: mm: fix intermittent failure khugepaged test" (Yeoreum Yun): Propagate child-process failures in the khugepaged tests and prevent background collapse from racing their checks. This removes false passes and intermittent failures. - "MAINTAINERS: cover all hugetlb headers under HUGETLB SUBSYSTEM" (Enze Li): Cover all hugetlb headers in MAINTAINERS so get_maintainer.pl finds the right maintainers. Also label the closing hugetlb_cgroup.h include guard. Summary of the 65 singletons in this merge: The singletons include a few worthwhile performance fixes. Avoiding unnecessary reverse-map tree updates gave a reported 15.9% improvement in UnixBench's execl test on a 192-core x86 system. A reclaim retry fix stops defrag_mode from spinning under memory.low protection; a reported file-creation stress test ran 5.7 times faster, with far less memory pressure. Narrower hugetlb invalidations also spare KVM guests needless refaults: the reported Redis-in-VM P99 QPS penalty while punching holes fell from 7.09% to 1.45%. Several fixes prevent lost data or corrupted memory. Lazyfree huge-page races with mremap()/munmap() could lose data or access freed memory, and MADV_COLD could lose a concurrent write's dirty bit. Another fix prevents stale migration entries from outliving large folios. On filesystems with blocks smaller than a page, extending a file by 4 GiB or more could expose bytes written past the old EOF through mmap instead of zeroes. That is fixed, along with use-after-free races in PAGEMAP_SCAN during process exit and in memory-cgroup accounting on PREEMPT_RT kernels. Other fixes stop UFFDIO_MOVE spinning forever on pinned large folios, which could wedge other memory operations, and stop mremap() leaking commit charges until allocations fail under strict overcommit. A further fix keeps userfaultfd tracking intact on neighboring mappings. NUMA binding no longer prevents long-term pins when the chosen node has only movable memory, fixing QEMU/VFIO startup and io_uring buffer registration failures. MGLRU also gets a fix for early-boot crashes with memory cgroups disabled at boot, notably in small crash kernels. * tag 'mm-stable-2026-10-25-19-27' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (213 commits) mm: multi-gen LRU: fix NULL lruvec->pgdat deref with memcg disabled on cmdline mm/page_counter: use WRITE_ONCE() for emin/elow when parent is the root mm/memcontrol: publish null pointer before dropping css reference test_maple_tree: test maple_range_64 node in RCU mode maple_tree: fix maple_range_64 crashes in RCU mode mm/vma: avoid broken uffd merge on mremap tools/testing/shared: catch a failed posix_memalign() mm/damon/core: remove unreachable damos charge_{target,addr}_from mm/shrinker: allocate shrinker_info_unit from a dedicated kmem_cache riscv: mm: exclude invalid THP PMDs from page table check mm/damon/core: filter out damos address filter-split failed region fs/proc/task_mmu: pin mm_users in do_pagemap_scan() mm/mempolicy: apply bind policies against the scoped allocation zone mm/vmscan: reclaim every zone in per-node proactive reclaim mm/mremap: correctly uncharge accountable VMAs in error path mm/mremap: populate calculated fields in vrm state correctly MAINTAINERS: add an entry for MEMORY MANAGEMENT - MEMORY MAP mm: bdi: reset min_ratio after the sysfs attributes are gone mm/page_vma_mapped: continue past nonmatching huge PMDs selftests/mm: skip hugetlb cgroup v2 tests without the needed controllers ...
4 daysMerge tag 'mm-nonmm-stable-2026-10-25-14-57' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Pull non-MM updates from Andrew Morton: - "ocfs2: exit recovery thread on mount error path" (Joseph Qi): Stop OCFS2 recovery before freeing failed-mount state and replay slots, closing use-after-free and double-free races. Defer suballocator reclaim to break a transaction-lock deadlock with dismount. - "ocfs2: validate suballoc slot and bit of metadata blocks" (Joseph Qi): Validate OCFS2 metadata suballocator slots, bits and directory index block locations. Reject corrupt metadata with filesystem errors instead of BUGs or out-of-bounds accesses. - "ocfs2: deal with legacy signed name hash values" (Joseph Qi): Restore OCFS2 lookups for non-ASCII names stored with legacy signed hashes. Use stored xattr hashes during bucket splits to avoid duplicate entries and spurious ENOSPC failures. - "ocfs2: stabilize dentry names in file and setattr traces" (Cen Zhang): Snapshot OCFS2 names during file and setattr tracing to prevent rename races using freed storage or mismatched names and lengths. Preserve trace formats and the locked release open-count sample. - "panic: fix panic_force_cpu= redirect races and NMI bypass" (Bradley Morgan): Fix panic_force_cpu races and NMI redirection so crash-kernel CPU selection is honored. Preserve variable arguments on failed redirects and use a static message buffer. - "fat: allocate multiple clusters in fallocate" (Matheus Alves de Almeida): Allocate FAT clusters in batches for FALLOC_FL_KEEP_SIZE and batch FAT updates. This removes repeated single-cluster allocation overhead, particularly on synchronous mounts. - "scripts/gdb: fix radix tree lookup and stack depot diagnostic" (Ting-Han Hou): Fix GDB radix-tree lookup and its handling of XArray sibling, retry and zero entries. Also repair the stack-depot diagnostic for an out-of-range pool index. - "hung_task: Improve warning budget handling and task reporting" (Aaron Tomlin): Reset the hung-task warning budget after recovery so later hangs remain visible. Keep the configured limit intact and emit one summary per scan when detailed reports exhaust the budget. - "bootconfig: Reject unexpected data after null character and cleanups" (Masami Hiramatsu): Reject bootconfig data after an embedded null while accepting trailing padding. Validate the full input in the userspace tool, and retain internal tree sanity checks there rather than in the kernel. - "kbuild: GCOV cleanups following the prefer-atomic fix" (Konstantin Khorenko): Use the actual GCOV build flags in the prefer-atomic compiler probe. Move flag setup into scripts/Makefile.gcov and skip the probe when GCOV is disabled. - "ocfs2: xattr bucket validation fixes" (Joseph Qi): Accept valid OCFS2 xattr buckets spanning 512-byte blocks, avoiding false read-only remounts. Reject misaligned buckets and return errors instead of panicking on corrupt defrag metadata. - "ocfs2: fix metadata reservation for xattr value trees" (Joseph Qi): Reserve enough OCFS2 metadata for new and relocated xattr value trees. Fix shortfalls which could cause ENOSPC, dropped entries and leaked clusters on fragmented filesystems; remove duplicate reservations. - "Introduce arch_do_panic" (Mete Durlu): Add arch_do_panic() and move s390 and sparc handling out of generic panic code. The architecture-specific actions now follow the end-of-panic marker. - "checkpatch: userspace improvements" (Petr Vorel): Improve checkpatch's userspace detection and suppress kernel-only checks. Recognize standard inttypes macros and add explicit --userspace and --no-userspace overrides. - "ocfs2: validate dr_fs_generation of dir index root blocks" (Joseph Qi): Check OCFS2 directory index generations and leaf block numbers. Reject stale or misplaced blocks instead of using metadata left by a previously formatted filesystem. - "selftests/membarrier: Skip an unregistered memory barrier test on Musl" (Chris Gellermann): Skip the unregistered membarrier test when libc has already registered the command. Musl does this during thread creation, causing false failures in the multithreaded test. - "init: fix array boundary bugs in boot parameter parsing" (Wilson Felipe Pereira): Fix boot argument boundary cases which leave stale arguments in init's command line or panic when replacing the final environment variable. Clear the last slot and check duplicates before the limit. Summary of the 87 singletons in this merge: The OCFS2 singletons fix deadlocks between xattr updates and inline truncation, and during inode reclaim. Corrupt quota and extent metadata could also crash the kernel or corrupt memory; these paths now check the layout before using it. Other fixes close use-after-free and publication races around cluster reconfiguration, node failure, quota remount errors and shared refcount trees. New files now retain security labels from all stacked LSMs instead of silently dropping all but one. Valid xattr insertions also stop tripping FORTIFY on builds with counted arrays. Elsewhere, a lost wakeup could leave hardware-monitoring reads stuck in unkillable sleep and block further I2C traffic. That is fixed, as are kernel memory leaks in POSIX message-queue notifications and tmpfs casefold setup which could grow until memory is exhausted. A driver removal race which could crash the kernel is fixed too. The hibernation command through reboot() also stops taking the same mutex twice, avoiding a deadlock before suspension. On the boot side, bzip2 decoding now accepts valid full blocks emitted by lbzip2, fixing failures to boot those compressed kernels. Malformed bzip2 streams can no longer overflow the decode buffer, and LZ4 initrds are checked before the decoder can read past their end. FAT rejects geometry which overflows the data-area calculation on 32-bit systems, and rolls back entries when inode setup fails, preventing failed creations from reappearing after remount. The x86 XOR and RAID6 AVX paths also avoid imposing a slowdown on subsequent SSE code. * tag 'mm-nonmm-stable-2026-10-25-14-57' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (134 commits) scripts/gdb: fix stack depot out-of-bounds diagnostic scripts/gdb: fix radix tree lookup pointer handling ocfs2/cluster: remove zero-address nodes from IP tree on teardown ocfs2: snapshot the dentry name while tracing file release ocfs2: snapshot dentry names in file and setattr traces ocfs2/dlm: drain join handlers before releasing module text MAINTAINERS: update Markus's e-mail address mailmap: add entries for Andrew Jones stackdepot: stop preallocating after the final pool ocfs2: drain quorum work before removing the cluster watchdog: force console verbose when reporting lockups profiling: fix sampling step on 64-bit big-endian systems kernel/reboot: avoid potential deadlocks during suspension compat: avoid double rounding in times() ocfs2: pin owning modules for open debugfs files ocfs2/cluster: initialize heartbeat regions before publishing them selftests/proc: proc-pid-vm: fix unused variable warning on non-x86 ocfs2: pin refcount trees before dropping the lookup lock ocfs2: validate the xattr tree root of an indexed xattr block ocfs2/dlm: hold the lookup reference across convert AST enqueue ...
5 daysMerge tag 'erofs-for-7.4-rc1-2' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs Pull erofs fixes from Gao Xiang: "These patches address several new reported issues related to page cache sharing, the new superblock_share feature, and recent metadata path changes for file-backed mounts: - Hold real inodes to fix mmap usage with page cache sharing - Fix metadata reads at the end of file-backed images with sub-page block sizes - Ensure disallowing superblock_share when device= is specified - Drop unnecessary .read_folio() checks for file-backed mounts to allow tmpfs as a backing fs" * tag 'erofs-for-7.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: drop unnecessary .read_folio() checks for file-backed mounts erofs: fix disallowing superblock_share if device= is set erofs: fix metadata reads at the end of file-backed images erofs: hold real inodes for shared files
5 daysMerge tag 'f2fs-for-7.4-rc1' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs Pull f2fs updates from Jaegeuk Kim: "In this round, key enhancements focus on introducing a dedicated metadata cache infrastructure and dynamically parameterizing on-disk block layouts and geometry macros. Moving meta, node, and compress blocks out of the VFS page cache removes the page == block size assumption for metadata, which along with dynamic block layout descriptions paves the way for large folio and page != block support in the future. We also opt in to multigrain timestamps, add bio entry-count throttling for asynchronous write_end_io completion, and expose the resizable_tail feature via sysfs. Alongside these features, critical bug fixes resolve race conditions across compression, mmap write faults, checkpoint/shutdown, and filesystem freeze, prevent write bio splitting and GC holes on sequential zoned devices, and strengthen on-disk sanity checks for SIT/NAT bitmaps, read-only curseg entries, and device aliasing. Additional stability patches address online resize, roll-forward recovery, atomic file operations, quota handling, and dirty inode syncing livelocks. Enhancements: - implement dedicated metadata cache for meta, node, and compress blocks to decouple metadata from page cache for large folio and page != block support - dynamically describe SIT, NAT, orphan, dentry, node, and xattr block layouts and parameterize block/sector/node conversion macros - opt in to multigrain timestamps - introduce max_atc_write_bio_entry_cnt sysfs node - expose resizable_tail feature via sysfs - avoid unnecessary reads in f2fs_update_meta_block() Bug fixes: - compress: force out-place update for all writes, allow pinning empty compressed files, and fix truncate/writeback and cache population races - zone: avoid bio split and GC target block grab failure on sequential zones - quota: convert inline quota files on quotaon, fix flush failure during freeze, and restore empty string mount options - atomic/mmap: disallow mmap write and data-modifying fallocate on atomic files, avoid truncate_inode_pages_final() on live inodes, and fix races in f2fs_vm_page_mkwrite() - resize/alias: refresh pinned allocation boundary and flush SIT journal during resize, and drop pending discards before reserving device alias - sanity check: bound SIT/NAT bitmaps by checkpoint pack, check all cur_*_segno[] on readonly images, and validate multi-device on device alias - recovery/cp: release removed xattr node in roll-forward recovery, invalidate curseg on change_curseg() failure, and return -EIO for lost inode block after cp_error - fix livelock in syncing dirty inodes and preserve APPEND/UPDATE ino entries - use bio_in_atomic() in f2fs_{read,write}_end_io() - fix 32-bit shift truncation in mount option bitmasks and defragment range And a number of minor bug fixes" * tag 'f2fs-for-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (79 commits) f2fs: compress: don't overwrite populated compress cache entry f2fs: fix to update superblock crc in sanity_check_area_boundary() f2fs: fix to fetch ino via ino_of_node() under cache lock f2fs: zone: fix to don't fail to grab GC target block on zoned device f2fs: don't use truncate_inode_pages_final() on live inodes f2fs: expose resizable_tail feature via sysfs f2fs: use BIT_ULL for mount option bitmasks f2fs: fix submit accounting for IPU writeback f2fs: fix to avoid potential reference count leak in do_garbage_collect() f2fs: refresh pinned allocation boundary after resize f2fs: flush SIT journal during filesystem resize f2fs: release a removed xattr node in roll-forward recovery f2fs: quota: fix quota flush failure during filesystem freeze f2fs: return -EIO for a lost inode block after cp_error f2fs: avoid unnecessary reads in f2fs_update_meta_block() f2fs: bound the SIT/NAT bitmaps by the checkpoint pack f2fs: opt in to multigrain timestamps f2fs: fix to use bio_in_atomic() in f2fs_read_end_io() f2fs: fix to use bio_in_atomic() in f2fs_write_end_io() f2fs: fix to invalidate curseg if change_curseg() fails ...