summaryrefslogtreecommitdiff
path: root/fs/kernfs
AgeCommit message (Collapse)Author
10 daysMerge tag 'vfs-7.4-rc1.kernfs' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull kernfs updates from Christian Brauner: "This contains kernfs scalability work from Shakeel driven by what Meta sees in their fleet. kernfs_rwsem is per kernfs root, so sysfs and cgroupfs each have one for the whole machine, and every create, remove and rename takes it for writing. rwsems don't let readers steal the lock once a writer is queued, so one cgroup being created or a device being renamed parks the entire incoming reader stream in uninterruptible sleep. Daemons that poll cgroup files in a loop turn that into a convoy and the two that hurt most, oomd and below, are the ones that are supposed to relieve memory pressure and record what happened. kernfs_dop_revalidate() took kernfs_rwsem for read once per path component of every walk into a kernfs mount. Nothing it reads needs the semaphore. kn->active is an atomic_t, kn->__parent and kn->name are rcu pointers, kn->ns can be compared instead of dereferenced and the directory revision is a plain counter. The callback runs under rcu now. Readers walking cgroupfs and sysfs while another thread churns cgroups, renames netdevs and plugs devices went from 48,593,360 read acquisitions and 1,744,517 contentions to 1,280,280 and 429,846 on an 8-CPU VM and path walk throughput improved 35-53%. LOOKUP_RCU still returns ECHILD because kernfs_iop_permission() forces every walk out of rcu-walk anyway. That is left for later. kernfs_fop_readdir() held the semaphore across dir_emit(). dir_emit() copies to userspace and under memory pressure that fault goes to reclaim with the lock every create, remove and rename needs held for reading. Meta sees 120 second allocation stalls in filldir64() from below and systemd-oomd stuck behind it. The lock is dropped around dir_emit() now. Since the entry the listing stopped on can disappear in that window and two entries can share a hash, readdir resumes on the full (hash, ns, name) key and the fallback search lands after the missing entry instead of repeating or skipping one. The repeat was a pre-existing bug between two getdents(2) calls. Three more lock holds are shortened. kernfs_notify_workfn() no longer holds kernfs_rwsem across fsnotify() which allocates against the memcg of the watching cgroup that is already under pressure. The open node is allocated outside the hashed open file mutex, the most contended lock in kernfs on their fleet with 2.19M waiters over 29 days and a 77ms median hold. A new node is activated without dropping and retaking the write lock, lock_stat says 1200 -> 830 write acquisitions for five dummy netdevs, and kernfs_rename_ns() allocates the new name before and frees the old one after the lock so a rename can't enter reclaim or wait out a grace period with it held. Three standalone fixes come with selftests. Same-parent renames take kernfs_rename_lock too so kernfs_path_from_node() can't build a path that never existed. Decoding a file handle takes the semaphore so a decode racing rmdir() can't hash an inode after the removal's ilookup() pass and lose IN_DELETE_SELF. And kernfs_create_link() reads the target's uid and gid under kernfs_iattr_rwsem so a chown in between can't give the link an owner the target never had. The kernfs selftests grew from two xattr checks to coverage of dentry revalidation, rename, namespace tagging, file handles and readdir under churn" * tag 'vfs-7.4-rc1.kernfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: kernfs: free the old name outside kernfs_rwsem kernfs: allocate the new name outside kernfs_rwsem kernfs: activate a new node without dropping kernfs_rwsem selftests: cover readdir resuming at a removed entry kernfs: don't hold kernfs_rwsem across dir_emit() kernfs: resume readdir on the full entry key kernfs: don't repeat or skip an entry when readdir resumes kernfs: don't hold kernfs_rwsem across notification delivery kernfs: allocate the open node outside the open file mutex kernfs: fix up the unlocked attribute reads on the creation paths kernfs: don't lose IN_DELETE_SELF when decoding a file handle kernfs: take kernfs_rename_lock for same-parent renames too selftests: cover kernfs file handles and same-parent rename selftests: cover kernfs dentry revalidation kernfs: Remove kernfs_rwsem from dentry revalidation kernfs: Avoid namespace dereference in d_revalidate() kernfs: Prepare directory revisions for lockless reads kernfs: Use VFS lookup context in d_revalidate()
10 daysMerge tag 'vfs-7.4-rc1.idmap' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs idmap constification from Christian Brauner: "This makes struct mnt_idmap const throughout the tree. A mount's idmapping is immutable. The only thing modified after alloc_mnt_idmap() is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only reads from it. That is the same model struct cred uses and the idmapping is sensitive enough to deserve it. The conversion goes bottom up through the vfs{g,u}id and fs{g,u}id helpers, the privilege checks, acl, xattr and quota and then every inode operation that takes an idmap, so ->permission(), ->getattr(), ->setattr(), ->create(), ->mkdir(), ->mknod(), ->symlink(), ->rename(), ->tmpfile(), ->get_acl(), ->set_acl() and ->fileattr_set() with their implementations in every filesystem, plus the LSM hooks. struct vfsmount, struct mount_kattr and struct kstatmount store a const pointer and nop_mnt_idmap and invalid_mnt_idmap live in rodata, so anything that tries to modify them faults instead of silently corrupting the initial idmapping" * tag 'vfs-7.4-rc1.idmap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (27 commits) fs: make nop_mnt_idmap and invalid_mnt_idmap const fs: port mnt_idmap() and file_mnt_idmap() to const mnt_idmap fs: port vfs_*() helpers to const mnt_idmap fs: port ->setattr() to pass const mnt_idmap fs: port ->getattr() to pass const mnt_idmap fs: port ->create() to pass const mnt_idmap fs: port ->symlink() to pass const mnt_idmap fs: port ->mkdir() to pass const mnt_idmap fs: port ->rename() to pass const mnt_idmap fs: port ->mknod() to pass const mnt_idmap fs: port ->tmpfile() to pass const mnt_idmap fs: port ->get_acl() to pass const mnt_idmap fs: port ->set_acl() to pass const mnt_idmap fs: port ->fileattr_set() to pass const mnt_idmap fs: port xattr to const mnt_idmap fs: port ->permission() to pass const mnt_idmap fs: port acl to const mnt_idmap fs: port inode_init_owner() to const mnt_idmap fs: port inode_owner_or_capable() to const mnt_idmap fs: port privilege checking helpers to const mnt_idmap ...
2026-09-25Merge patch series "kernfs: do less work under the kernfs_rwsem write lock"Christian Brauner
Shakeel Butt <shakeel.butt@linux.dev> says: kernfs_rwsem is per kernfs root, so sysfs and cgroupfs have one each for the whole machine, and every create, remove and rename takes it for writing. Whatever a writer does while holding it, everyone else waits for. These three patches take work out of that section. Patch 1: kernfs_add_one() links the node in, drops the lock, then calls kernfs_activate(), which takes it again. sysfs does not create nodes deactivated, so it pays two write locks for every file and directory. Activate before dropping the lock. lock_stat says 1200 -> 830 write acquisitions for creating and destroying five dummy netdevs. Patch 2: kernfs_rename_ns() calls kstrdup_const() under the lock. It is the only GFP_KERNEL allocation under the write lock in kernfs, so a rename can enter reclaim with the lock held. Allocate before the lock. Patch 3: kernfs_rename_ns() also frees the old name under the lock with kfree_rcu_mightsleep(). When its batching allocation fails, which is what happens under memory pressure, it falls back to synchronize_rcu(). A rename can then wait out a grace period with the lock held. Free after the unlock. Tested with the kernfs selftests under KASAN and lockdep. * patches from https://patch.msgid.link/20260913021453.21507-1-shakeel.butt@linux.dev: kernfs: free the old name outside kernfs_rwsem kernfs: allocate the new name outside kernfs_rwsem kernfs: activate a new node without dropping kernfs_rwsem Link: https://patch.msgid.link/20260913021453.21507-1-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-25kernfs: free the old name outside kernfs_rwsemShakeel Butt
kernfs_rename_ns() frees the replaced name with kfree_rcu_mightsleep() while still holding the kernfs_rwsem write lock. If the batching allocation fails, which is what happens under memory pressure, kvfree_call_rcu() falls back to a full synchronize_rcu() before freeing. A rename can then wait out a grace period with the write lock held, and every create, remove and rename in the hierarchy waits with it. The name is already unpublished by then, so nothing needs the free to happen under the lock. Move it past the unlock. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260913021453.21507-4-shakeel.butt@linux.dev Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-25kernfs: allocate the new name outside kernfs_rwsemShakeel Butt
kernfs_rename_ns() calls kstrdup_const() while holding the kernfs_rwsem write lock. It is the only GFP_KERNEL allocation under that lock in kernfs, so a rename can enter reclaim while every create, remove and rename in the hierarchy waits behind it. Copy the name before taking the lock and free the copy again if the rename turns out not to need it. A rename that keeps the name, hits a collision or finds the node gone now does one extra kstrdup_const(); renames are rare. -ENOMEM is still reported at the same point as before, so nothing changes about which error a caller sees. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260913021453.21507-3-shakeel.butt@linux.dev Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-25kernfs: activate a new node without dropping kernfs_rwsemShakeel Butt
kernfs_add_one() links the node in, drops the kernfs_rwsem write lock, then calls kernfs_activate(), which takes it again. Roots that do not set KERNFS_ROOT_CREATE_DEACTIVATED, such as sysfs, therefore pay two write locks for every file, directory and symlink created. A new node has no children, so kernfs_activate() would walk only that node. Call kernfs_activate_one() before dropping the lock instead. Its two WARN_ON_ONCE()s still hold: the node was just linked, and nothing can have changed its active count yet. This also closes the window where a node is linked but not yet activated. lock_stat, creating and destroying five dummy netdevs: before after kernfs_rwsem write acquires 1200 830 Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260913021453.21507-2-shakeel.butt@linux.dev Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23super: make iterate_supers_type() deletion-safeChristian Brauner
iterate_supers_type() drops sb_lock while invoking the callback and keeps only a passive reference to the current superblock. That reference keeps the object allocated, but does not keep its s_instances node linked. After the iterator releases s_umount, final teardown can unlink the current s_instances node. The iterator then advances through a reinitialized node. With the current hlist it stops without visiting the remaining superblocks. The unlink moved from generic_shutdown_super() to kill_super_notify(), but the cursor lifetime has been unsafe since the helper was introduced. The CIFS DFS lookup can consequently miss a matching superblock and return -EINVAL. Move removal from fs_supers to put_super(), alongside removal from super_blocks, so a passive reference keeps both list nodes linked. Keep the filesystem module reference until then, since unlinking s_instances may touch type->fs_supers. Make sget_fc() skip SB_DEAD superblocks before invoking test(), and set SB_DEAD under sb_lock to serialize with those callbacks. This allows kernfs to free its private information after kill_anon_super() returns. Keep matching SB_DYING superblocks until SB_DEAD is set so concurrent mounts still wait for teardown before retrying. Fixes: 43e15cdbefea ("new helper: iterate_supers_type()") Reported-by: Karl Mehltretter <kmehltretter@gmail.com> Closes: https://lore.kernel.org/r/20260903013336.92081-1-kmehltretter@gmail.com Suggested-by: Jan Kara <jack@suse.cz> Cc: stable@vger.kernel.org Tested-by: Karl Mehltretter <kmehltretter@gmail.com> [kmehltretter: supplied the commit message] Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com> Link: https://patch.msgid.link/20260909193034.7467-1-kmehltretter@gmail.com Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port ->setattr() to pass const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-24-54ccd48e100b@kernel.org Acked-by: Paul Moore <paul@paul-moore.com> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port ->getattr() to pass const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-23-54ccd48e100b@kernel.org Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port ->mkdir() to pass const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-20-54ccd48e100b@kernel.org Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port ->rename() to pass const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-19-54ccd48e100b@kernel.org Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port xattr to const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-13-54ccd48e100b@kernel.org Acked-by: Paul Moore <paul@paul-moore.com> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-23fs: port ->permission() to pass const mnt_idmapChristian Brauner
Convert to const struct mnt_idmap. A mount's idmapping is immutable. The only thing that is allowed to be modified afterwards is the reference count and that is hidden behind mnt_idmap_get() and mnt_idmap_put(). Everything else only ever reads from the idmapping. This is the same model that struct cred uses and the idmapping is also rather sensitive. So make the idmap argument const wherever we can. The conversion is done from the bottom up so callers can continue to pass a non-const pointer to a const parameter until the conversion is finished. No functional changes. Link: https://patch.msgid.link/20260901-work-idmap-const-v1-12-54ccd48e100b@kernel.org Acked-by: Paul Moore <paul@paul-moore.com> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Seth Forshee <sforshee@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-17kernfs: don't hold kernfs_rwsem across dir_emit()Shakeel Butt
kernfs_fop_readdir() holds kernfs_rwsem for reading across the whole listing, dir_emit() included. dir_emit() copies to userspace, so it can fault into reclaim while holding the lock that every create, remove and rename in the hierarchy needs. sysfs and cgroupfs have one per machine. Under memory pressure the monitoring daemons fault on their own getdents(2) buffer with it held: below: page allocation stall for 120 secs: order:0, mode:0x140dca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO|__GFP_COMP) nodemask=(null),cpuset=hostcritical.slice,mems_allowed=0 Call Trace: <TASK> dump_stack_lvl+0x5d/0x80 __alloc_frozen_pages_noprof+0x5f4d/0x6300 ? memcg_list_lru_alloc+0x73/0x320 ? ima_file_check+0xd0/0x7d0 vma_alloc_folio_noprof+0x145/0x560 handle_mm_fault+0x17c9/0x2720 ? find_vma+0x27/0x30 do_user_addr_fault+0x39f/0x6e0 exc_page_fault+0x8f/0x110 asm_exc_page_fault+0x22/0x30 RIP: 0010:filldir64+0xd7/0x1a0 [Code:/RSP:/RAX:..R15: register block elided] kernfs_fop_readdir+0x2de/0x420 iterate_dir+0x8c/0x1f0 __se_sys_getdents64+0x61/0xe0 ? copy_page_from_iter+0x860/0x860 do_syscall_64+0x6a/0x250 entry_SYSCALL_64_after_hwframe+0x4b/0x53 </TASK> Commit 9aab10a0249e ("kernfs: Don't re-lock kernfs_root::kernfs_rwsem in kernfs_fop_readdir().") took the lock drop out because dir_emit() was handed kernfs_node::name, which a rename can free. The previous patch emits a copy instead, so drop the lock around dir_emit(). A listing is no longer atomic within one getdents(2) call, which for most sysfs and cgroup directories is all of it. POSIX leaves that unspecified for an entry added or removed since opendir(3). Fixes: 9aab10a0249e ("kernfs: Don't re-lock kernfs_root::kernfs_rwsem in kernfs_fop_readdir().") Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260911182815.1992483-4-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-17kernfs: resume readdir on the full entry keyShakeel Butt
readdir resumes at the entry pinned in file->private_data, and falls back to the hash in ctx->pos when that entry is gone. Two entries in one directory can share a hash, so the hash alone does not say where the listing stopped. Copy the name under the lock, emit the copy, and keep it as the resume key. The pinned entry counts as the same entry only while its name still matches, and the fallback search starts after (hash, ns, name) rather than at the first entry with the hash. No behaviour change yet. kernfs_rwsem is held across the loop, so nothing can move between two entries of one call, and a resume across getdents(2) calls has no saved name and keys on the hash as before. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260911182815.1992483-3-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-17kernfs: don't repeat or skip an entry when readdir resumesShakeel Butt
readdir keeps its place as a name hash in ctx->pos and pins the entry in file->private_data. If that entry is gone when the listing comes back, kernfs_dir_pos() searches the rbtree for the hash and keeps whatever node the descent stopped on. That is the entry before or after the missing one, depending on the shape of the tree. Landing before it repeats an entry the previous getdents(2) call already reported. Landing after it, kernfs_dir_next_pos() calls rb_next() and steps over an unreported entry. With children A(10), B(20), C(30): report A, ctx->pos = 10 A removed kernfs_dir_next_pos(10, A) A is gone, the search for 10 stops at B rb_next(B) -> C, so B is never reported Only the repeat happens today, between two getdents(2) calls. The skip needs the pinned entry to go away inside one call, which the next patch allows when it drops kernfs_rwsem around dir_emit(). Before the commit 4e4d6d860b93 the descent kept a node only on the way left, which is a search for the first entry at or after the hash. That commit moved the assignment to the top of the loop, where it runs on right turns too. Restore that search, and step forward only when the pinned entry is still there rather than when the hash matches, since two entries in one directory can share a hash. While here, kernfs_dir_next_pos() called the hash @ino. It is never an inode number, so name it @hash. Fixes: 4e4d6d860b93 ("sysfs: Add s_hash to sysfs_dirent and order directory entries by hash") Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260911182815.1992483-2-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-17kernfs: don't hold kernfs_rwsem across notification deliveryShakeel Butt
Recently at Meta we noticed that on multi-tenant systems, a workload under extreme memory pressure negatively impacts unrelated workloads and system daemons like below [1] and fb-oomd [2]. Mainly we observed that system daemons were stuck on kernfs_rwsem in cgroup-related interfaces for long periods of time. On further inspection, we found that the workload under pressure had registered inotify watches on its memory.events and was continuously receiving limit-hitting notifications. The cgroup notification is done in kernfs_notify_workfn(), which holds kernfs_supers_rwsem and kernfs_rwsem and calls fsnotify(), which allocates the event with kmalloc(GFP_KERNEL_ACCOUNT|__GFP_RETRY_MAYFAIL) charged to the watching cgroup, which is already under memory pressure. So the notify worker ended up in memory reclaim of a cgroup already under pressure, and itself kept triggering the limit notifications. This notification path takes the locks in read mode, but a waiting writer blocks all future readers. That is exactly what is happening in the Meta fleet, and it leaves daemons that are critical to the reliability of the system stuck for long periods of time. Commit 400188ae361a ("kernfs: Acquire kernfs_rwsem in kernfs_notify_workfn().") added kernfs_rwsem just to safely read kernfs_node::name. Let's sample the name once before the loop and drop the lock. kernfs_supers_rwsem still covers the list, and the removal paths take that one for reading too, so a stalled worker can still hold a removal up once a mount or unmount is queued behind it. Two things change for a watcher. A name longer than NAME_MAX now gives an event with no name, where before it gave one with the full name; fsnotify() takes the name as optional, so the event still arrives. And the name and the parent are no longer sampled under one lock, so a rename between the two would name a file against the directory it moved to. That cannot happen today: kernfs_notify() rejects anything that is not a file, and no caller of kernfs_rename_ns() renames one. [1] https://github.com/facebookincubator/below [2] https://github.com/facebookincubator/oomd Fixes: 400188ae361a ("kernfs: Acquire kernfs_rwsem in kernfs_notify_workfn().") Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260910045406.485295-1-shakeel.butt@linux.dev Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-17kernfs: allocate the open node outside the open file mutexShakeel Butt
kernfs_get_open_node() allocates the kernfs_open_node while holding one of the hashed kernfs_open_file mutexes, so opening a file nobody has open yet can enter reclaim with that mutex held. The mutex is shared by every node that hashes to it, so unrelated opens, closes and xattr updates in the same bucket wait. It is the most contended lock in kernfs on our fleet: 2.19M waiters over 29 days, more than two hundred times the waiters on kernfs_rwsem, and the highest median hold of any kernfs lock at 77ms. Most of it is monitoring daemons opening cgroup control files, and the open node is freed once the last descriptor closes, so an open-read-close loop allocates every time. Look at kn->attr.open before taking the mutex, and allocate then if nothing has the file open. Should the peek be wrong, which needs the last descriptor to close inside the window, fall back to allocating under the mutex as before. Eight tasks opening and closing four cgroup files 20000 times each, with lock_stat on the hashed mutex: contentions hold total hold avg before 198 4.19 s 8.67 us after 119 2.31 s 4.78 us and the same number of acquisitions either way. This does not empty the bucket. kernfs_fop_release() and kernfs_xattr_set() still sleep under the same mutex. It stops opens doing it. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260910045433.489413-1-shakeel.butt@linux.dev Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-10kernfs: fix up the unlocked attribute reads on the creation pathsShakeel Butt
Two creation paths read a live node's attributes without holding kernfs_iattr_rwsem, which kernfs_iop_setattr() takes for writing. They need different fixes. kernfs_create_link() copies the target's ia_uid and then its ia_gid into the new link. A chown of the target between the two reads leaves the link with the old uid and the new gid, an owner the target never had. Read both under the rwsem. kernfs_new_node() reads the parent's mode and ia_gid for S_ISGID inheritance. Either value is fine there: the node does not exist yet, so nothing orders a racing chmod or chown against the creation. Taking the rwsem would only pick between two answers that are both right. Mark the reads with READ_ONCE() instead. The pointer that leads to them is already fine: __kernfs_iattrs() publishes kernfs_node::iattr with try_cmpxchg(), and both sides read it with READ_ONCE(), like the rest of fs/kernfs. The Fixes tag is for the symlink half. kernfs_create_link() has read the pair unlocked since it started copying the target's owner; only the name of the lock its writer takes has changed. The READ_ONCE() markings are not a fix. Fixes: 488dee96bb62 ("kernfs: allow creating kernfs objects with arbitrary uid/gid") Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260905191613.3143937-5-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-10kernfs: don't lose IN_DELETE_SELF when decoding a file handleShakeel Butt
__kernfs_remove() clears i_nlink on a node's inodes and finds them with ilookup(). A decode that has pinned the node but not yet hashed its inode is invisible to that pass: CPU0 CPU1 open_by_handle_at() kernfs_find_and_get_node_by_id() pins the node, still active rmdir() marks the subtree removing ilookup() finds no inode kernfs_get_inode() hashes an inode with i_nlink 1 Nothing fixes it later: kernfs_refresh_inode() never touches i_nlink for a file and skips it for a directory being removed. The inode keeps the 1 it was born with, and dentry_unlink_inode() sends IN_DELETE_SELF only at 0, so a watcher never learns the node went away. The other callers of kernfs_get_inode() are safe: those in fs/kernfs hold kernfs_rwsem, and cgroup_may_write() is covered by cgroup_mutex, which cgroup_destroy_locked() holds across kernfs_remove(). __kernfs_fh_to_dentry() has held nothing since exportfs support was added. Take kernfs_rwsem for reading, as ->get_parent already does, and cover the lookup as well as kernfs_get_inode(). __kernfs_remove() deactivates the whole subtree under the write lock, so under the read lock either the lookup refuses the node, or the inode is hashed before the ilookup() pass runs. The same holds for ->fh_to_parent, since a node cannot be active while an ancestor is being removed. Reproduced with a 300ms delay between the lookup and kernfs_get_inode(), decoding a handle for a file in a cgroup directory while another task rmdir()s it: st_nlink is 1 without this patch and 0 with it. ->get_parent still has a window of its own. It takes the same lock but has no active check, so reconnect_path() can build an inode for an ancestor that is already gone. That needs the active test rather than a lock, and changes what ->get_parent returns, so it is left to the series that reworks these paths. Fixes: eea5d2bb34ba ("kernfs: Send IN_DELETE_SELF and IN_IGNORED") Cc: stable@vger.kernel.org Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260905191613.3143937-4-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-10kernfs: take kernfs_rename_lock for same-parent renames tooShakeel Butt
kernfs_rename_ns() takes kernfs_rename_lock only when the rename moves the node to a new parent. A rename that keeps the parent, like renaming a network interface, changes kernfs_node::name under kernfs_rwsem alone. So the lock covers ->__parent but not ->name, and a reader that wants a stable name has to take kernfs_rwsem, the lock every lookup needs. It is also a real bug. kernfs_path_from_node() holds the lock for reading and reads each ancestor's name once. One rename only moves the answer from the old path to the new one, but two renames inside one walk build a path that never existed: CPU0 CPU1 kernfs_path_from_node() on /a/b/c reads the name of a, gets "a" renames a to a2 renames b to b2 reads the name of b, gets "b2" returns "/a/b2/c" Only sysfs can hit this: sysfs_warn_dup() is the one caller on a root without KERNFS_ROOT_INVARIANT_PARENT. The rest are cgroup, which sets the flag, so it skips the lock and reads names under RCU alone. That case needs something else and is left alone here. So take the lock for both kinds of rename, and let kernfs_rcu_name() accept it, like kernfs_parent() already does for ->__parent. Renames are rare, the lock is per filesystem, and the locked section is at most three stores. It also gives a future rename counter one place to sit. Fixes: 741c10b096bc ("kernfs: Use RCU to access kernfs_node::name.") Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260905191613.3143937-3-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-01kernfs: preserve security xattrs without allocating iattrsHengyu Liang
Commit d5e81a5650b5 ("kernfs: avoid iattr allocation in listxattr") made kernfs_iop_listxattr() return an empty list when the kernfs node has no allocated kernfs_iattrs. However, this also skips security xattr names provided by simple_xattr_list(). As of now, applications can retrieve the SELinux label of a sysfs file with getxattr(), but cannot do it through listxattr(). A similar issue happened before in commit b09e0fa4b4ea ("tmpfs: implement generic xattr support"). It was fixed by commit 8b0ba61df5a1c ("fs/xattr.c: fix simple_xattr_list to always include security.* xattrs"). Perhaps this recent commit needs a fix as well. The issue can be reproduced with a simple python program: python3 - <<'PY' import os path = "/sys/kernel/warn_count" print("getxattr:", os.getxattr(path, "security.selinux")) print("listxattr:", os.listxattr(path)) PY Before commit d5e81a5650b5 ("kernfs: avoid iattr allocation in listxattr"), the result is: getxattr: b'system_u:object_r:sysfs_t:s0\x00' listxattr: ['security.selinux'] After that commit, the result is: getxattr: b'system_u:object_r:sysfs_t:s0\x00' listxattr: [] This patch will keep listxattr() consistent with getxattr() when security xattrs are available. Fixes: d5e81a5650b5 ("kernfs: avoid iattr allocation in listxattr") Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu> Acked-by: Tejun Heo <tj@kernel.org> Link: https://patch.msgid.link/20260822051705.1761850-1-hengyul@cs.unc.edu Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2026-08-31kernfs: Remove kernfs_rwsem from dentry revalidationShakeel Butt
kernfs_dop_revalidate() takes kernfs_rwsem for read once per path component of every walk into a kernfs mount. Linux rwsems do not permit reader lock stealing once a writer is queued, so a single writer parks the whole incoming reader stream in uninterruptible sleep, stalling cgroup-polling daemons for minutes. Nothing the callback reads requires the semaphore. kn->active is an atomic_t that kernfs_find_and_get_node_by_id() already tests through __kernfs_active(); kn->__parent and kn->name are RCU pointers whose old values are freed only after a grace period; kn->ns is now compared rather than dereferenced; parent->dir.rev was annotated earlier in this series. What the semaphore does provide is a coherent snapshot, and that is not needed. ->d_revalidate() answers a question about a single instant, and the answer is already stale when it returns: a rename landing just after up_read() gives the same outcome as one observed mid-read. A lockless reader can only return "valid" for the (parent, name, namespace) triple identifying the dentry it was handed, and that triple was true when the dentry was instantiated, so it reports a genuine past state exactly as the locked version did. Removal is backstopped by kernfs_get_active() failing in the subsequent open(). Take an RCU read lock instead. kernfs_parent() and kernfs_rcu_name() work unchanged: the condition in their rcu_dereference_check() is an alternative to holding the RCU read lock, not an extra requirement. The negative dentry path needs nothing, as @dir pins the parent. The namespace check can use @parent directly once the preceding check establishes it equals kernfs_parent(kn), so the kn_parent local and its NULL test go away. kernfs_ns_enabled() reads @parent->flags, which KERNFS_ACTIVATED and KERNFS_REMOVING update as a plain read-modify-write under kernfs_rwsem. Those bits are not read here and KERNFS_NS cannot change once the directory has children, so mark the read data_race() rather than READ_ONCE(), which would not silence KCSAN against the unmarked writers anyway. kernfs_iop_permission() still forces every walk out of RCU-walk before children are revalidated, so lifting the LOOKUP_RCU bail here would have no observable effect; it is left to the series fixing that path. Readers walking cgroupfs and sysfs against concurrent cgroup and netdev churn: kernfs_rwsem read acquisitions drop from 48,593,360 to 1,280,280, and kernfs_dop_revalidate() no longer appears among its contention sites. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260821050507.2161607-5-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-31kernfs: Avoid namespace dereference in d_revalidate()Shakeel Butt
Commit 1fe989e1c42a ("kernfs: use namespace id instead of pointer for hashing and comparison") changed dentry revalidation to compare namespace IDs along with the comparisons that determine visible directory ordering. Dereferencing a namespace tag that kernfs_rename_ns() can replace is not suitable once dentry revalidation stops taking kernfs_rwsem. Use pointer equality for this non-user-visible equality check instead. Namespace IDs uniquely identify namespace objects, so pointer and ID equality cannot disagree for valid tags. Hashing and directory ordering continue to use IDs. kn->ns becomes a lockless read in the next commit, so mark both sides of it now. The read is in kernfs_dop_revalidate(); the stores that can run while the node is visible are the two in kernfs_rename_ns(). The remaining stores, in kernfs_create_dir_ns(), kernfs_create_empty_dir() and kernfs_create_link(), all precede kernfs_add_one() and need no marking. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260821050507.2161607-4-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-31kernfs: Prepare directory revisions for lockless readsShakeel Butt
Negative dentry revalidation only needs to sample the parent directory generation and compare it with the value recorded at lookup time. Annotate those accesses with READ_ONCE() and WRITE_ONCE() so the comparison can safely move outside kernfs_rwsem. Revision updates remain serialized by kernfs_rwsem. Assert that writer contract in kernfs_inc_rev(); the read half of the increment stays plain because the semaphore excludes other writers. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260821050507.2161607-3-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-31kernfs: Use VFS lookup context in d_revalidate()Shakeel Butt
The VFS supplies a stable parent inode and expected name to the revalidation callback. Use them instead of recovering the same information from mutable dentry fields. Compare the name using its explicit length because it may point into the pathname and need not be terminated at name->len. This also prepares the callback for lockless operation. Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Link: https://patch.msgid.link/20260821050507.2161607-2-shakeel.butt@linux.dev Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-15kernfs: avoid iattr allocation in listxattrYichong Chen
kernfs_iop_listxattr() only needs to report existing xattrs, but it uses kernfs_iattrs(), which allocates kernfs_iattrs when the node does not have one yet. This makes a query operation create persistent per-node metadata even when the xattr list is empty. Use kernfs_iattrs_noalloc() instead and return an empty list when no iattrs exist. Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Acked-by: Tejun Heo <tj@kernel.org> Link: https://patch.msgid.link/20260731120554.630147-1-chenyichong@uniontech.com Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2026-07-18kernfs: Replace strcpy(s, "../") with memcpy(s, "../", 4)David Laight
The code has already checked there is enough room. Use memcpy() to avoid compiler warnings from possibly unbounded strcpy(). Signed-off-by: David Laight <david.laight.linux@gmail.com> Link: https://patch.msgid.link/20260606202633.5018-6-david.laight.linux@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-07-18kernfs: simplify kernfs_name_hash()Dmitry Antipov
In 'kernfs_name_hash()', 'name' is NUL-terminated so it may be directly scanned up to end without an extra call to 'strlen()'. Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> Link: https://patch.msgid.link/20260617073941.472337-1-dmantipov@yandex.ru Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-06-15Merge tag 'driver-core-7.2-rc1' of ↵Linus Torvalds
gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core Pull driver core updates from Danilo Krummrich: "Deferred probe: - Fix race where deferred probe timeout work could be permanently canceled by using mod_delayed_work() - Fix missing jiffies conversion in deferred_probe_extend_timeout() - Guard timeout extension with delayed_work_pending() to prevent premature firing - Use system_percpu_wq instead of the deprecated system_wq - Update deferred_probe_timeout documentation device: - Replace direct struct device bitfield access (can_match, dma_iommu, dma_skip_sync, dma_ops_bypass, state_synced, dma_coherent, of_node_reused, offline, offline_disabled) with flag-based accessors using bit operations - Reject devices with unregistered buses - Delete unused DEVICE_ATTR_PREALLOC() - Add low-level device attribute macros with const show/store callbacks, allowing device attributes to reside in read-only memory - Move core device attributes to read-only memory - Constify group array pointers in driver_add_groups() / driver_remove_groups(), struct bus_type, and struct device_driver device property: - Fix fwnode reference leak in fwnode_graph_get_endpoint_by_id() - Initialize all fields of fwnode_handle in fwnode_init() - Provide swnode_get()/swnode_put() wrappers around kobject_get/put() - Allow passing struct software_node_ref_args pointers directly to PROPERTY_ENTRY_REF() driver_override: - Migrate amba, cdx, vmbus, and rpmsg to the generic driver_override infrastructure, fixing a UAF from unsynchronized access to driver_override in bus match() callbacks - Remove the now-unused driver_set_override() firmware loader: - Fix recursive lock deadlock in device_cache_fw_images() when async work falls back to synchronous execution - Fix device reference leak in firmware_upload_register() platform: - Pass KBUILD_MODNAME through the platform driver registration macro to create module symlinks in sysfs for built-in drivers; move module_kset initialization to a pure_initcall and tegra cbb registration to core_initcall to ensure correct ordering - Pass THIS_MODULE implicitly through a coresight_init_driver() macro sysfs: - Upgrade OOB write detection in sysfs_kf_seq_show() from printk to WARN - Add return value clamping to sysfs_kf_read() Rust: - ACPI: Fix missing match data for PRP0001 by exporting acpi_of_match_device() - Auxiliary: Replace drvdata() with dedicated registration data on auxiliary_device. drvdata() exposed the driver's bus device private data beyond the driver's own scope, creating ordering constraints and forcing the data to outlive all registrations that access it. Registration data is instead scoped structurally to the Registration object, making lifecycle ordering enforced by construction rather than convention. - Rust-native device driver lifetimes (HRT): Allow Rust device drivers to carry a lifetime parameter on their bus device private data, tied to the device binding scope -- the interval during which a bus device is bound to a driver. Device resources like pci::Bar<'a> and IoMem<'a> can be stored directly in the driver's bus device private data with a lifetime bounded by the binding scope, so the compiler enforces at build time that they do not outlive the binding. This removes Devres indirection from every access site and eliminates try_access() failure paths in destructors. Bus driver traits use a Generic Associated Type (GAT) Data<'bound> to introduce the lifetime on the private data, rather than parameterizing the Driver trait itself. Auxiliary registration data, where the lifetime is not introduced by a trait callback but must be threaded through Registration, uses the ForLt trait (a type-level abstraction for types generic over a lifetime). Misc: - Fix DT overlayed devices not probing by reverting the broken treewide overlay fix and re-running fw_devlink consumer pickup when an overlay is applied to a bound device - Use root_device_register() for faux bus root device; add sanity check for failed bus init - Fix dev_has_sync_state() data race with READ_ONCE() and move it to base.h - Avoid spurious device_links warning when removing a device while its supplier is unbinding - Switch ISA bus to dynamic root device - Fix suspicious RCU usage in kernfs_put() - Remove devcoredump exit callback - Constify devfreq_event_class" * tag 'driver-core-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core: (81 commits) software node: allow passing reference args to PROPERTY_ENTRY_REF() driver core: platform: set mod_name in driver registration coresight: pass THIS_MODULE implicitly through a macro kernel: param: initialize module_kset in a pure_initcall soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall firmware_loader: Fix recursive lock in device_cache_fw_images() driver core: Use system_percpu_wq instead of system_wq driver core: remove driver_set_override() rpmsg: use generic driver_override infrastructure Drivers: hv: vmbus: use generic driver_override infrastructure cdx: use generic driver_override infrastructure amba: use generic driver_override infrastructure rust: devres: add 'static bound to Devres<T> samples: rust: rust_driver_auxiliary: showcase lifetime-bound registration data rust: auxiliary: generalize Registration over ForLt rust: types: add `ForLt` trait for higher-ranked lifetime support gpu: nova-core: separate driver type from driver data samples: rust: rust_driver_pci: use HRT lifetime for Bar rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized rust: pci: make Bar lifetime-parameterized ...
2026-06-06kernfs: link kn to its parent before the LSM init hookChristian Brauner
After commit 12e9e3cd03b5 ("simpe_xattr: use per-sb cache"), kernfs_xattr_set() and kernfs_xattr_get() compute the cache via kernfs_root(kn) before any other check. kernfs_root(kn) walks kn->__parent first and falls back to kn->dir.root, both of which are NULL on a freshly kmem_cache_zalloc()'d kn. kn->__parent was being set in kernfs_new_node() after __kernfs_new_node() returned, and kn->dir.root is set even later by kernfs_create_dir_ns() / kernfs_create_empty_dir(). The LSM kernfs_init_security hook is invoked from inside __kernfs_new_node(), before either field has been initialized. selinux_kernfs_init_security() ends with kernfs_xattr_set(kn, XATTR_NAME_SELINUX, ...). kernfs_root(kn) then returns NULL, and &((struct kernfs_root *)NULL)->xa_cache evaluates to offsetof(struct kernfs_root, xa_cache) which faults: BUG: kernel NULL pointer dereference, address: 00000000000000e0 RIP: 0010:simple_xattr_set+0x27/0x8b0 Call Trace: kernfs_xattr_set+0x63/0xb0 selinux_kernfs_init_security+0x13b/0x270 security_kernfs_init_security+0x36/0xc0 __kernfs_new_node+0x182/0x290 kernfs_new_node+0x80/0xc0 kernfs_create_dir_ns+0x2b/0xa0 cgroup_create+0x116/0x380 cgroup_mkdir+0x7c/0x1a0 Reproduces deterministically at PID 1 (systemd) on an SELinux-enabled distro. The first cgroup mkdir under /sys/fs/cgroup with a labelled parent panics the kernel. The LSM hook's contract is that the kn_dir argument is the parent of the new kn, so kn->__parent should already point at kn_dir when the hook runs. Move kernfs_get(parent) and rcu_assign_pointer of kn->__parent from kernfs_new_node() into __kernfs_new_node() right before the security hook, and unwind the parent reference on the err_out4 path. kernfs_root(kn) then takes its parent branch during the hook and returns parent->dir.root, which is the correct root. This also closes the same-shape latent bug in kernfs_xattr_get() (which today is hidden only by kernfs_iattrs_noalloc() returning NULL on a fresh kn). Fixes: 12e9e3cd03b5 ("simpe_xattr: use per-sb cache") Reported-by: Calum Mackay <calum.mackay@oracle.com> Closes: https://lore.kernel.org/all/5386153f-9112-4971-98fc-de90d7aae2c6@oracle.com/ Link: https://patch.msgid.link/20260526-ablief-demut-wehen-aef8446ef5c9@brauner Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-06-06simpe_xattr: use per-sb cacheMiklos Szeredi
Move the hash table to the super block to remove excessive overhead in case of small number of xattrs per inode. Add linked list to the inode, used for listxattr and eviction. Listxattr uses rcu protection to iterate the list of xattrs. Before being made per-sb, lazy allocation was protected by inode lock. Now inode lock no longer provides sufficient exclusion, so use cmpxchg() to ensure atomicity. Though I haven't found a description of this pattern, after some research it seems that cmpxchg_release() and READ_ONCE() should provide the necessary memory barriers. Use simple_xattr_free_rcu() in simple_xattrs_free(). This is needed because the hash table is now shared between inodes and lookup on a different inode might be running the compare function on the just freed element within the RCU grace period. Following stats are based on slabinfo diff, after creating 100k empty files, then adding a "user.test=foo" xattr to each: v7.0 (no rhashtable): File creation: 993.40 bytes/file Xattr addition: 79.99 bytes/file v7.1-rc2 (per-inode rhashtable): File creation: 939.73 bytes/file Xattr addition: 1296.08 bytes/file v7.1-rc2 + this patch (per-sb rhashtable) File creation: 946.84 bytes/file Xattr addition: 111.86 bytes/file The overhead of a single xattr is reduced to nearly v7.0 levels. The per xattr overhead is slightly larger due to the addition of three pointers to struct simple_xattr. Fixes: b32c4a213698 ("xattr: add rhashtable-based simple_xattr infrastructure") Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Link: https://patch.msgid.link/20260605135322.2632068-5-mszeredi@redhat.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-06-06simple_xattr: change interface to pass struct simple_xattrs **Miklos Szeredi
Change the simple_xattr API to accept pointer-to-pointer (struct simple_xattrs **) instead of pointer. This allows the functions to handle lazy allocation internally without requiring callers to use simple_xattrs_lazy_alloc(). The simple_xattr_set(), simple_xattr_set_limited() and simple_xattr_add() functions now handle allocation when xattrs is NULL. simple_xattrs_free() now also frees the xattrs structure itself and sets the pointer to NULL. This simplifies callers and removes the need for most callers to explicitly manage xattrs allocation and lifetime. In shmem_initxattrs(), the total required space for all initial xattrs (ispace) is pre-calculated and deducted from sbinfo->free_ispace. Since this patch modifies the function to add new xattrs directly to the inode's &info->xattrs list rather than using a local temporary variable, a failure means that the partially populated info->xattrs list remains attached to the inode. When the VFS caller handles the -ENOMEM error, it drops the newly created inode via iput(), shmem_free_inode() adds freed to sbinfo->free_ispace a second time, permanently inflating the tmpfs free space quota. Fix by substracting already added xattrs from ispace. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Link: https://patch.msgid.link/20260605135322.2632068-4-mszeredi@redhat.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-06-06kernfs: fix xattr race condition with multiple superblocksMiklos Szeredi
Multiple superblocks with different namespaces can share the same kernfs_node when kernfs_test_super() finds a matching root but different namespace. This means multiple inodes from different superblocks can reference the same kernfs_node->iattr->xattrs structure. The VFS layer only holds per-inode locks during xattr operations, which is insufficient to serialize concurrent xattr modifications on the shared kernfs_node. This can lead to race conditions in simple_xattr_set() where the lookup->replace/remove sequence is not atomic with respect to operations from other superblocks. Fix this by protecting xattr operations with the existing hashed kernfs_locks->open_file_mutex[] array, which is already used to protect per-node open file data. The hashed mutex array provides scalable per-node serialization (scaled by CPU count, up to 1024 locks on 32+ CPU systems) with zero memory overhead. Changes: - Rename open_file_mutex[] to node_mutex[] to reflect dual purpose - Add kernfs_node_lock_ptr() and kernfs_node_lock() helpers - Protect simple_xattr_set() calls in kernfs_xattr_set() and kernfs_vfs_user_xattr_set() with the hashed mutex - Update file.c to use new helpers via compatibility wrappers - Update documentation to explain the extended lock usage Fixes: b32c4a213698 ("xattr: add rhashtable-based simple_xattr infrastructure") Reported-by: Sashiko <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/patchset/20260601162454.2116375-1-mszeredi%40redhat.com Assisted-by: Claude:claude-sonnet-4-5 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Link: https://patch.msgid.link/20260605135322.2632068-2-mszeredi@redhat.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-22kernfs: fix suspicious RCU usage in kernfs_put()Conor Kotwasinski
Commit 741c10b096bc ("kernfs: Use RCU to access kernfs_node::name.") converted the WARN_ONCE() in kernfs_put() to read kn->name and parent->name via rcu_dereference(), but kernfs_put() has callers that hold neither kernfs_rwsem nor the RCU read lock. The inode eviction path driven by memory reclaim is one such case: kernfs_put+0x53/0x60 fs/kernfs/dir.c:602 evict+0x3c2/0xad0 fs/inode.c:846 iput_final fs/inode.c:1966 [inline] iput.part.0+0x605/0xf50 fs/inode.c:2015 iput+0x35/0x40 fs/inode.c:1981 dentry_unlink_inode+0x2a1/0x490 fs/dcache.c:467 __dentry_kill+0x1d0/0x600 fs/dcache.c:670 shrink_dentry_list+0x180/0x5e0 fs/dcache.c:1174 prune_dcache_sb+0xea/0x150 fs/dcache.c:1256 super_cache_scan+0x328/0x550 fs/super.c:223 ... kswapd+0x556/0xba0 mm/vmscan.c:7343 lockdep complains with "suspicious RCU usage" whenever the WARN fires from such a context. Wrap the rcu_dereference() calls in an RCU read-side critical section. Gate on the active-ref check so the lock is only taken when the WARN is about to fire. Note that this does not address the underlying imbalance in kn->active that triggers the WARN. Fixes: 741c10b096bc ("kernfs: Use RCU to access kernfs_node::name.") Reported-by: syzbot+0dfe499ea713e0a15bec@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0dfe499ea713e0a15bec Signed-off-by: Conor Kotwasinski <conorkotwasinski2024@u.northwestern.edu> Acked-by: Tejun Heo <tj@kernel.org> Link: https://patch.msgid.link/20260416134315.1474726-1-conorkotwasinski2024@u.northwestern.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-04-13Merge tag 'driver-core-7.1-rc1' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core Pull driver core updates from Danilo Krummrich: "debugfs: - Fix NULL pointer dereference in debugfs_create_str() - Fix misplaced EXPORT_SYMBOL_GPL for debugfs_create_str() - Fix soundwire debugfs NULL pointer dereference from uninitialized firmware_file device property: - Make fwnode flags modifications thread safe; widen the field to unsigned long and use set_bit() / clear_bit() based accessors - Document how to check for the property presence devres: - Separate struct devres_node from its "subclasses" (struct devres, struct devres_group); give struct devres_node its own release and free callbacks for per-type dispatch - Introduce struct devres_action for devres actions, avoiding the ARCH_DMA_MINALIGN alignment overhead of struct devres - Export struct devres_node and its init/add/remove/dbginfo primitives for use by Rust Devres<T> - Fix missing node debug info in devm_krealloc() - Use guard(spinlock_irqsave) where applicable; consolidate unlock paths in devres_release_group() driver_override: - Convert PCI, WMI, vdpa, s390/cio, s390/ap, and fsl-mc to the generic driver_override infrastructure, replacing per-bus driver_override strings, sysfs attributes, and match logic; fixes a potential UAF from unsynchronized access to driver_override in bus match() callbacks - Simplify __device_set_driver_override() logic kernfs: - Send IN_DELETE_SELF and IN_IGNORED inotify events on kernfs file and directory removal - Add corresponding selftests for memcg platform: - Allow attaching software nodes when creating platform devices via a new 'swnode' field in struct platform_device_info - Add kerneldoc for struct platform_device_info software node: - Move software node initialization from postcore_initcall() to driver_init(), making it available early in the boot process - Move kernel_kobj initialization (ksysfs_init) earlier to support the above - Remove software_node_exit(); dead code in a built-in unit SoC: - Introduce of_machine_read_compatible() and of_machine_read_model() OF helpers and export soc_attr_read_machine() to replace direct accesses to of_root from SoC drivers; also enables CONFIG_COMPILE_TEST coverage for these drivers sysfs: - Constify attribute group array pointers to 'const struct attribute_group *const *' in sysfs functions, device_add_groups() / device_remove_groups(), and struct class Rust: - Devres: - Embed struct devres_node directly in Devres<T> instead of going through devm_add_action(), avoiding the extra allocation and the unnecessary ARCH_DMA_MINALIGN alignment - I/O: - Turn IoCapable from a marker trait into a functional trait carrying the raw I/O accessor implementation (io_read / io_write), providing working defaults for the per-type Io methods - Add RelaxedMmio wrapper type, making relaxed accessors usable in code generic over the Io trait - Remove overloaded per-type Io methods and per-backend macros from Mmio and PCI ConfigSpace - I/O (Register): - Add IoLoc trait and generic read/write/update methods to the Io trait, making I/O operations parameterizable by typed locations - Add register! macro for defining hardware register types with typed bitfield accessors backed by Bounded values; supports direct, relative, and array register addressing - Add write_reg() / try_write_reg() and LocatedRegister trait - Update PCI sample driver to demonstrate the register! macro Example: ``` register! { /// UART control register. CTRL(u32) @ 0x18 { /// Receiver enable. 19:19 rx_enable => bool; /// Parity configuration. 14:13 parity ?=> Parity; } /// FIFO watermark and counter register. WATER(u32) @ 0x2c { /// Number of datawords in the receive FIFO. 26:24 rx_count; /// RX interrupt threshold. 17:16 rx_water; } } impl WATER { fn rx_above_watermark(&self) -> bool { self.rx_count() > self.rx_water() } } fn init(bar: &pci::Bar<BAR0_SIZE>) { let water = WATER::zeroed() .with_const_rx_water::<1>(); // > 3 would not compile bar.write_reg(water); let ctrl = CTRL::zeroed() .with_parity(Parity::Even) .with_rx_enable(true); bar.write_reg(ctrl); } fn handle_rx(bar: &pci::Bar<BAR0_SIZE>) { if bar.read(WATER).rx_above_watermark() { // drain the FIFO } } fn set_parity(bar: &pci::Bar<BAR0_SIZE>, parity: Parity) { bar.update(CTRL, |r| r.with_parity(parity)); } ``` - IRQ: - Move 'static bounds from where clauses to trait declarations for IRQ handler traits - Misc: - Enable the generic_arg_infer Rust feature - Extend Bounded with shift operations, single-bit bool conversion, and const get() Misc: - Make deferred_probe_timeout default a Kconfig option - Drop auxiliary_dev_pm_ops; the PM core falls back to driver PM callbacks when no bus type PM ops are set - Add conditional guard support for device_lock() - Add ksysfs.c to the DRIVER CORE MAINTAINERS entry - Fix kernel-doc warnings in base.h - Fix stale reference to memory_block_add_nid() in documentation" * tag 'driver-core-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (67 commits) bus: fsl-mc: use generic driver_override infrastructure s390/ap: use generic driver_override infrastructure s390/cio: use generic driver_override infrastructure vdpa: use generic driver_override infrastructure platform/wmi: use generic driver_override infrastructure PCI: use generic driver_override infrastructure driver core: make software nodes available earlier software node: remove software_node_exit() kernel: ksysfs: initialize kernel_kobj earlier MAINTAINERS: add ksysfs.c to the DRIVER CORE entry drivers/base/memory: fix stale reference to memory_block_add_nid() device property: Document how to check for the property presence soundwire: debugfs: initialize firmware_file to empty string debugfs: fix placement of EXPORT_SYMBOL_GPL for debugfs_create_str() debugfs: check for NULL pointer in debugfs_create_str() driver core: Make deferred_probe_timeout default a Kconfig option driver core: simplify __device_set_driver_override() clearing logic driver core: auxiliary bus: Drop auxiliary_dev_pm_ops device property: Make modifications of fwnode "flags" thread safe rust: devres: embed struct devres_node directly ...
2026-04-13Merge tag 'vfs-7.1-rc1.xattr' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs xattr updates from Christian Brauner: "This reworks the simple_xattr infrastructure and adds support for user.* extended attributes on sockets. The simple_xattr subsystem currently uses an rbtree protected by a reader-writer spinlock. This series replaces the rbtree with an rhashtable giving O(1) average-case lookup with RCU-based lockless reads. This sped up concurrent access patterns on tmpfs quite a bit and it's an overall easy enough conversion to do and gets rid or rwlock_t. The conversion is done incrementally: a new rhashtable path is added alongside the existing rbtree, consumers are migrated one at a time (shmem, kernfs, pidfs), and then the rbtree code is removed. All three consumers switch from embedded structs to pointer-based lazy allocation so the rhashtable overhead is only paid for inodes that actually use xattrs. With this infrastructure in place the series adds support for user.* xattrs on sockets. Path-based AF_UNIX sockets inherit xattr support from the underlying filesystem (e.g. tmpfs) but sockets in sockfs - that is everything created via socket() including abstract namespace AF_UNIX sockets - had no xattr support at all. The xattr_permission() checks are reworked to allow user.* xattrs on S_IFSOCK inodes. Sockfs sockets get per-inode limits of 128 xattrs and 128KB total value size matching the limits already in use for kernfs. The practical motivation comes from several directions. systemd and GNOME are expanding their use of Varlink as an IPC mechanism. For D-Bus there are tools like dbus-monitor that can observe IPC traffic across the system but this only works because D-Bus has a central broker. For Varlink there is no broker and there is currently no way to identify which sockets speak Varlink. With user.* xattrs on sockets a service can label its socket with the IPC protocol it speaks (e.g., user.varlink=1) and an eBPF program can then selectively capture traffic on those sockets. Enumerating bound sockets via netlink combined with these xattr labels gives a way to discover all Varlink IPC entrypoints for debugging and introspection. Similarly, systemd-journald wants to use xattrs on the /dev/log socket for protocol negotiation to indicate whether RFC 5424 structured syslog is supported or whether only the legacy RFC 3164 format should be used. In containers these labels are particularly useful as high-privilege or more complicated solutions for socket identification aren't available. The series comes with comprehensive selftests covering path-based AF_UNIX sockets, sockfs socket operations, per-inode limit enforcement, and xattr operations across multiple address families (AF_INET, AF_INET6, AF_NETLINK, AF_PACKET)" * tag 'vfs-7.1-rc1.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: selftests/xattr: test xattrs on various socket families selftests/xattr: sockfs socket xattr tests selftests/xattr: path-based AF_UNIX socket xattr tests xattr: support extended attributes on sockets xattr,net: support limited amount of extended attributes on sockfs sockets xattr: move user limits for xattrs to generic infra xattr: switch xattr_permission() to switch statement xattr: add xattr_permission_error() xattr: remove rbtree-based simple_xattr infrastructure pidfs: adapt to rhashtable-based simple_xattrs kernfs: adapt to rhashtable-based simple_xattrs with lazy allocation shmem: adapt to rhashtable-based simple_xattrs with lazy allocation xattr: add rhashtable-based simple_xattr infrastructure xattr: add rcu_head and rhash_head to struct simple_xattr
2026-04-09kernfs: make directory seek namespace-awareChristian Brauner
The rbtree backing kernfs directories is ordered by (hash, ns_id, name) but kernfs_dir_pos() only searches by hash when seeking to a position during readdir. When two nodes from different namespaces share the same hash value, the binary search can land on a node in the wrong namespace. The subsequent skip-forward loop walks rb_next() and may overshoot the correct node, silently dropping an entry from the readdir results. With the recent switch from raw namespace pointers to public namespace ids as hash seeds, computing hash collisions became an offline operation. An unprivileged user could unshare into a new network namespace, create a single interface whose name-hash collides with a target entry in init_net, and cause a victim's seekdir/readdir on /sys/class/net to miss that entry. Fix this by extending the rbtree search in kernfs_dir_pos() to also compare namespace ids when hashes match. Since the rbtree is already ordered by (hash, ns_id, name), this makes the seek land directly in the correct namespace's range, eliminating the wrong-namespace overshoot. Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-04-09kernfs: use namespace id instead of pointer for hashing and comparisonChristian Brauner
kernfs uses the namespace tag as both a hash seed (via init_name_hash()) and a comparison key in the rbtree. The resulting hash values are exposed to userspace through directory seek positions (ctx->pos), and the raw pointer comparisons in kernfs_name_compare() encode kernel pointer ordering into the rbtree layout. This constitutes a KASLR information leak since the hash and ordering derived from kernel pointers can be observed from userspace. Fix this by using the 64-bit namespace id (ns_common::ns_id) instead of the raw pointer value for both hashing and comparison. The namespace id is a stable, non-secret identifier that is already exposed to userspace through other interfaces (e.g., /proc/pid/ns/, ioctl NS_GET_NSID). Introduce kernfs_ns_id() as a helper that extracts the namespace id from a potentially-NULL ns_common pointer, returning 0 for the no-namespace case. All namespace equality checks in the directory iteration and dentry revalidation paths are also switched from pointer comparison to ns_id comparison for consistency. Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-04-09kernfs: pass struct ns_common instead of const void * for namespace tagsChristian Brauner
kernfs has historically used const void * to pass around namespace tags used for directory-level namespace filtering. The only current user of this is sysfs network namespace tagging where struct net pointers are cast to void *. Replace all const void * namespace parameters with const struct ns_common * throughout the kernfs, sysfs, and kobject namespace layers. This includes the kobj_ns_type_operations callbacks, kobject_namespace(), and all sysfs/kernfs APIs that accept or return namespace tags. Passing struct ns_common is needed because various codepaths require access to the underlying namespace. A struct ns_common can always be converted back to the concrete namespace type (e.g., struct net) via container_of() or to_ns_common() in the reverse direction. This is a preparatory change for switching to ns_id-based directory iteration to prevent a KASLR pointer leak through the current use of raw namespace pointers as hash seeds and comparison keys. Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-03-14kernfs: Add missing documentation for kernfs_put_active's drop_supers argumentT.J. Mercier
The drop_supers argument was added to kernfs_put_active to control whether the kernfs_supers_rwsem is temporarily dropped along with the kernfs_rwsem, but no documentation was added for it. Fixes: eea5d2bb34ba ("kernfs: Send IN_DELETE_SELF and IN_IGNORED") Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202603130112.2FcCzv1g-lkp@intel.com/ Signed-off-by: T.J. Mercier <tjmercier@google.com> Link: https://patch.msgid.link/20260313175153.235681-1-tjmercier@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-03-12kernfs: Send IN_DELETE_SELF and IN_IGNOREDT.J. Mercier
Currently some kernfs files (e.g. cgroup.events, memory.events) support inotify watches for IN_MODIFY, but unlike with regular filesystems, they do not receive IN_DELETE_SELF or IN_IGNORED events when they are removed. This means inotify watches persist after file deletion until the process exits and the inotify file descriptor is cleaned up, or until inotify_rm_watch is called manually. This creates a problem for processes monitoring cgroups. For example, a service monitoring memory.events for memory.high breaches needs to know when a cgroup is removed to clean up its state. Where it's known that a cgroup is removed when all processes die, without IN_DELETE_SELF the service must resort to inefficient workarounds such as: 1) Periodically scanning procfs to detect process death (wastes CPU and is susceptible to PID reuse). 2) Holding a pidfd for every monitored cgroup (can exhaust file descriptors). This patch enables IN_DELETE_SELF and IN_IGNORED events for kernfs files and directories by clearing inode i_nlink values during removal. This allows VFS to make the necessary fsnotify calls so that userspace receives the inotify events. As a result, applications can rely on a single existing watch on a file of interest (e.g. memory.events) to receive notifications for both modifications and the eventual removal of the file, as well as automatic watch descriptor cleanup, simplifying userspace logic and improving efficiency. There is gap in this implementation for certain file removals due their unique nature in kernfs. Directory removals that trigger file removals occur through vfs_rmdir, which shrinks the dcache and emits fsnotify events after the rmdir operation; there is no issue here. However kernfs writes to particular files (e.g. cgroup.subtree_control) can also cause file removal, but vfs_write does not attempt to emit fsnotify events after the write operation, even if i_nlink counts are 0. As a usecase for monitoring this category of file removals is not known, they are left without having IN_DELETE or IN_DELETE_SELF events generated. Fanotify recursive monitoring also does not work for kernfs nodes that do not have inodes attached, as they are created on-demand in kernfs. Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: T.J. Mercier <tjmercier@google.com> Tested-by: syzbot@syzkaller.appspotmail.com Acked-by: Tejun Heo <tj@kernel.org> Link: https://patch.msgid.link/20260225223404.783173-3-tjmercier@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-03-12kernfs: Don't set_nlink for directories being removedT.J. Mercier
If a directory is already in the process of removal its i_nlink count becomes irrelevant because its contents are also about to be removed and any pending filesystem operations on it or its contents will soon start to fail. So we can avoid setting it for directories already flagged for removal. This avoids a race in the next patch, which adds clearing of the i_nlink count for kernfs nodes being removed to support inotify delete events. Use protection from the kernfs_iattr_rwsem to avoid adding more contention to the kernfs_rwsem for calls to kernfs_refresh_inode. Signed-off-by: T.J. Mercier <tjmercier@google.com> Tested-by: syzbot@syzkaller.appspotmail.com Link: https://patch.msgid.link/20260225223404.783173-2-tjmercier@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-03-02xattr: move user limits for xattrs to generic infraChristian Brauner
Link: https://patch.msgid.link/20260216-work-xattr-socket-v1-9-c2efa4f74cb7@kernel.org Acked-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-03-02kernfs: adapt to rhashtable-based simple_xattrs with lazy allocationChristian Brauner
Adapt kernfs to use the rhashtable-based xattr path and switch from an embedded struct to pointer-based lazy allocation. Change kernfs_iattrs.xattrs from embedded 'struct simple_xattrs' to a pointer 'struct simple_xattrs *', initialized to NULL (zeroed by kmem_cache_zalloc). Since kernfs_iattrs is already lazily allocated itself, this adds a second level of lazy allocation specifically for the xattr store. The xattr store is allocated on first setxattr. Read paths check for NULL and return -ENODATA or empty list. Replaced xattr entries are freed via simple_xattr_free_rcu() to allow concurrent RCU readers to finish. The cleanup paths in kernfs_free_rcu() and __kernfs_new_node() error handling conditionally free the xattr store only when allocated. As Jan noted in [1]: > This is a slight change in the lifetime rules because previously kernfs > xattrs could be safely accessed only under RCU but after this change you > have to hold inode reference *and* RCU to safely access them. I don't think > anybody would be accessing xattrs without holding inode reference so this > should be safe [...]. Link: https://patch.msgid.link/20260216-work-xattr-socket-v1-4-c2efa4f74cb7@kernel.org Link: https://lore.kernel.org/3cnmtqmakpbb2uwhenrj7kdqu3uefykiykjllgfbtpkiwhaa4s@sghkevv7jned [1] Acked-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-02-21Convert 'alloc_obj' family to use the new default GFP_KERNEL argumentLinus Torvalds
This was done entirely with mindless brute force, using git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' | xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/' to convert the new alloc_obj() users that had a simple GFP_KERNEL argument to just drop that argument. Note that due to the extreme simplicity of the scripting, any slightly more complex cases spread over multiple lines would not be triggered: they definitely exist, but this covers the vast bulk of the cases, and the resulting diff is also then easier to check automatically. For the same reason the 'flex' versions will be done as a separate conversion. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-02-21treewide: Replace kmalloc with kmalloc_obj for non-scalar typesKees Cook
This is the result of running the Coccinelle script from scripts/coccinelle/api/kmalloc_objs.cocci. The script is designed to avoid scalar types (which need careful case-by-case checking), and instead replace kmalloc-family calls that allocate struct or union object instances: Single allocations: kmalloc(sizeof(TYPE), ...) are replaced with: kmalloc_obj(TYPE, ...) Array allocations: kmalloc_array(COUNT, sizeof(TYPE), ...) are replaced with: kmalloc_objs(TYPE, COUNT, ...) Flex array allocations: kmalloc(struct_size(PTR, FAM, COUNT), ...) are replaced with: kmalloc_flex(*PTR, FAM, COUNT, ...) (where TYPE may also be *VAR) The resulting allocations no longer return "void *", instead returning "TYPE *". Signed-off-by: Kees Cook <kees@kernel.org>
2025-12-23fs/kernfs: null-ptr deref in simple_xattrs_free()Will Rosenberg
There exists a null pointer dereference in simple_xattrs_free() as part of the __kernfs_new_node() routine. Within __kernfs_new_node(), err_out4 calls simple_xattr_free(), but kn->iattr may be NULL if __kernfs_setattr() was never called. As a result, the first argument to simple_xattrs_free() may be NULL + 0x38, and no NULL check is done internally, causing an incorrect pointer dereference. Add a check to ensure kn->iattr is not NULL, meaning __kernfs_setattr() has been called and kn->iattr is allocated. Note that struct kernfs_node kn is allocated with kmem_cache_zalloc, so we can assume kn->iattr will be NULL if not allocated. An alternative fix could be to not call simple_xattrs_free() at all. As was previously discussed during the initial patch, simple_xattrs_free() is not strictly needed and is included to be consistent with kernfs_free_rcu(), which also helps the function maintain correctness if changes are made in __kernfs_new_node(). Reported-by: syzbot+6aaf7f48ae034ab0ea97@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=6aaf7f48ae034ab0ea97 Fixes: 382b1e8f30f7 ("kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node") Signed-off-by: Will Rosenberg <whrosenb@asu.edu> Link: https://patch.msgid.link/20251217060107.4171558-1-whrosenb@asu.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-12-05Merge tag 'driver-core-6.19-rc1' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core Pull driver core updates from Danilo Krummrich: "Arch Topology: - Move parse_acpi_topology() from arm64 to common code for reuse in RISC-V CPU: - Expose housekeeping CPUs through /sys/devices/system/cpu/housekeeping - Print a newline (or 0x0A) instead of '(null)' reading /sys/devices/system/cpu/nohz_full when nohz_full= is not set debugfs - Remove (broken) 'no-mount' mode - Remove redundant access mode checks in debugfs_get_tree() and debugfs_create_*() functions Devres: - Remove unused devm_free_percpu() helper - Move devm_alloc_percpu() from device.h to devres.h Firmware Loader: - Replace simple_strtol() with kstrtoint() - Do not call cancel_store() when no upload is in progress kernfs: - Increase struct super_block::maxbytes to MAX_LFS_FILESIZE - Fix a missing unwind path in __kernfs_new_node() Misc: - Increase the name size in struct auxiliary_device_id to 40 characters - Replace system_unbound_wq with system_dfl_wq and add WQ_PERCPU to alloc_workqueue() Platform: - Replace ERR_PTR() with IOMEM_ERR_PTR() in platform ioremap functions Rust: - Auxiliary: - Unregister auxiliary device on parent device unbind - Move parent() to impl Device; implement device context aware parent() for Device<Bound> - Illustrate how to safely obtain a driver's device private data when calling from an auxiliary driver into the parant device driver - DebugFs: - Implement support for binary large objects - Device: - Let probe() return the driver's device private data as pinned initializer, i.e. impl PinInit<Self, Error> - Implement safe accessor for a driver's device private data for Device<Bound> (returned reference can't out-live driver binding and guarantees the correct private data type) - Implement AsBusDevice trait, to be used by class device abstractions to derive the bus device type of the parent device - DMA: - Store raw pointer of allocation as NonNull - Use start_ptr() and start_ptr_mut() to inherit correct mutability of self - FS: - Add file::Offset type alias - I2C: - Add abstractions for I2C device / driver infrastructure - Implement abstractions for manual I2C device registrations - I/O: - Use "kernel vertical" style for imports - Define ResourceSize as resource_size_t - Move ResourceSize to top-level I/O module - Add type alias for phys_addr_t - Implement Rust version of read_poll_timeout_atomic() - PCI: - Use "kernel vertical" style for imports - Move I/O and IRQ infrastructure to separate files - Add support for PCI interrupt vectors - Implement TryInto<IrqRequest<'a>> for IrqVector<'a> to convert an IrqVector bound to specific pci::Device into an IrqRequest bound to the same pci::Device's parent Device - Leverage pin_init_scope() to get rid of redundant Result in IRQ methods - PinInit: - Add {pin_}init_scope() to execute code before creating an initializer - Platform: - Leverage pin_init_scope() to get rid of redundant Result in IRQ methods - Timekeeping: - Implement abstraction of udelay() - Uaccess: - Implement read_slice_partial() and read_slice_file() for UserSliceReader - Implement write_slice_partial() and write_slice_file() for UserSliceWriter sysfs: - Prepare the constification of struct attribute" * tag 'driver-core-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (75 commits) rust: pci: fix build failure when CONFIG_PCI_MSI is disabled debugfs: Fix default access mode config check debugfs: Remove broken no-mount mode debugfs: Remove redundant access mode checks driver core: Check drivers_autoprobe for all added devices driver core: WQ_PERCPU added to alloc_workqueue users driver core: replace use of system_unbound_wq with system_dfl_wq tick/nohz: Expose housekeeping CPUs in sysfs tick/nohz: avoid showing '(null)' if nohz_full= not set sysfs/cpu: Use DEVICE_ATTR_RO for nohz_full attribute kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node fs/kernfs: raise sb->maxbytes to MAX_LFS_FILESIZE mod_devicetable: Bump auxiliary_device_id name size sysfs: simplify attribute definition macros samples/kobject: constify 'struct foo_attribute' samples/kobject: add is_visible() callback to attribute group sysfs: attribute_group: enable const variants of is_visible() sysfs: introduce __SYSFS_FUNCTION_ALTERNATIVE() sysfs: transparently handle const pointers in ATTRIBUTE_GROUPS() sysfs: attribute_group: allow registration of const attribute ...
2025-11-26kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_nodeWill Rosenberg
There exists a memory leak of kernfs_iattrs contained as an element of kernfs_node allocated in __kernfs_new_node(). __kernfs_setattr() allocates kernfs_iattrs as a sub-object, and the LSM security check incorrectly errors out and does not free the kernfs_iattrs sub-object. Make an additional error out case that properly frees kernfs_iattrs if security_kernfs_init_security() fails. Fixes: e19dfdc83b60 ("kernfs: initialize security of newly created nodes") Co-developed-by: Oliver Rosenberg <olrose55@gmail.com> Signed-off-by: Oliver Rosenberg <olrose55@gmail.com> Signed-off-by: Will Rosenberg <whrosenb@asu.edu> Link: https://patch.msgid.link/20251125151332.2010687-1-whrosenb@asu.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>