| Age | Commit message (Collapse) | Author |
|
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>
|
|
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
|
|
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
|
|
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()
...
|
|
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
...
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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
|
|
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
...
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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
...
|
|
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
...
|
|
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
|
|
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
...
|