diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-17 11:35:12 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-17 11:35:12 -0700 |
| commit | fff0150b0299f834fe2c335ce0eb5c68bb414cbd (patch) | |
| tree | 87b252e40d51b3d033926fee45cea2220fcb87f7 /drivers | |
| parent | de03b17ec046d81c4713bc54306579b9024fc513 (diff) | |
| parent | b4343aebd3a4dd255b15b2e5b1363d6399da302f (diff) | |
Merge tag 'vfs-7.3-rc1.kthread' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull kthread vfs updates from Christian Brauner:
"This stops kernel threads from sharing filesystem state with
userspace. This work is about 3 cycles old and has been in -next
for about that time.
When the kernel boots init_task creates PID 1 and then kthreadd. From
that point every kthread and PID 1 share the same fs_struct. That is
why pivot_root() has to rewrite the fs_struct of all kthreads. The
rewriting exists so that kthreads can use init's filesystem state when
they want to. It also means userspace can move the ground out from
under the kernel.
PID 1 now gets a completely separate fs_struct. All kthreads are
anchored in a private SB_KERNMOUNT instance of nullfs that cannot be
mounted on and cannot be used to follow other mounts. Userspace init
can no longer affect kthread filesystem state and kthreads can no
longer affect userspace fs state without explicit opting in to that.
Path lookup from a kthread now fails by default. It makes it
deliberately hard to offload security sensitive operations into init's
filesystem state from a kthread.
Places that legitimately need to look something up there opt in
through the new scoped_with_init_fs() which temporarily overrides the
caller's fs_struct with init's. usermodehelpers remain the only kernel
tasks that genuinely share init's filesystem state, since they execute
random binaries in the root filesystem (excellent...).
The visible result is that /proc/2/root is a nullfs with an empty
mountinfo while /proc/1/root is the real root"
* tag 'vfs-7.3-rc1.kthread' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (26 commits)
initramfs_test: use test init/exit hooks to override init fs
fs: stop rewriting paths for PF_EXITING | PF_DUMPCORE
fs: stop rewriting kthread fs structs
fs: start all kthreads in nullfs
nullfs: make nullfs multi-instance
devtmpfs: create private mount namespace
fs: add umh argument to struct kernel_clone_args
fs: stop sharing fs_struct between init_task and pid 1
af_unix: use scoped_with_init_fs() for coredump socket lookup
initramfs: use scoped_with_init_fs() for rootfs unpacking
pnfs/blocklayout: use scoped_with_init_fs() for SCSI device lookup
ksmbd: use scoped_with_init_fs() for VFS path operations
ksmbd: use scoped_with_init_fs() for filesystem info path lookup
ksmbd: use scoped_with_init_fs() for share path resolution
fs: use scoped_with_init_fs() for kernel_read_file_from_path_initns()
coredump: use scoped_with_init_fs() for coredump path resolution
btrfs: use scoped_with_init_fs() for update_dev_time()
scsi: target: use scoped_with_init_fs() for APTPL metadata
scsi: target: use scoped_with_init_fs() for ALUA metadata
crypto: ccp: use scoped_with_init_fs() for SEV file access
...
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/devtmpfs.c | 2 | ||||
| -rw-r--r-- | drivers/block/rnbd/rnbd-srv.c | 4 | ||||
| -rw-r--r-- | drivers/char/misc_minor_kunit.c | 25 | ||||
| -rw-r--r-- | drivers/crypto/ccp/sev-dev.c | 12 | ||||
| -rw-r--r-- | drivers/target/target_core_alua.c | 11 | ||||
| -rw-r--r-- | drivers/target/target_core_pr.c | 4 |
6 files changed, 36 insertions, 22 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index b1c4ceb65026..aef0fcc6aba1 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -413,7 +413,7 @@ static noinline int __init devtmpfs_setup(void *p) { int err; - err = ksys_unshare(CLONE_NEWNS); + err = ksys_unshare(UNSHARE_EMPTY_MNTNS); if (err) goto out; err = init_mount("devtmpfs", "/", "devtmpfs", DEVTMPFS_MFLAGS, NULL); diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c index 10e8c438bb43..79c9a5fb418f 100644 --- a/drivers/block/rnbd/rnbd-srv.c +++ b/drivers/block/rnbd/rnbd-srv.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/blkdev.h> +#include <linux/fs_struct.h> #include "rnbd-srv.h" #include "rnbd-srv-trace.h" @@ -734,7 +735,8 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, goto reject; } - bdev_file = bdev_file_open_by_path(full_path, open_flags, NULL, NULL); + scoped_with_init_fs() + bdev_file = bdev_file_open_by_path(full_path, open_flags, NULL, NULL); if (IS_ERR(bdev_file)) { ret = PTR_ERR(bdev_file); pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %pe\n", diff --git a/drivers/char/misc_minor_kunit.c b/drivers/char/misc_minor_kunit.c index e930c78e1ef9..e85210cbb640 100644 --- a/drivers/char/misc_minor_kunit.c +++ b/drivers/char/misc_minor_kunit.c @@ -5,6 +5,7 @@ #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/file.h> +#include <linux/fs_struct.h> #include <linux/init_syscalls.h> /* static minor (LCD_MINOR) */ @@ -160,18 +161,22 @@ static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice * char *devname; devname = kasprintf(GFP_KERNEL, "/dev/%s", misc->name); - ret = init_mknod(devname, S_IFCHR | 0600, - new_encode_dev(MKDEV(MISC_MAJOR, misc->minor))); - if (ret != 0) - KUNIT_FAIL(test, "failed to create node\n"); - filp = filp_open(devname, O_RDONLY, 0); - if (IS_ERR(filp)) - KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp)); - else - fput(filp); + /* Tests run in a nullfs kthread; borrow the init fs to resolve /dev. */ + scoped_with_init_fs() { + ret = init_mknod(devname, S_IFCHR | 0600, + new_encode_dev(MKDEV(MISC_MAJOR, misc->minor))); + if (ret != 0) + KUNIT_FAIL(test, "failed to create node\n"); + + filp = filp_open(devname, O_RDONLY, 0); + if (IS_ERR(filp)) + KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp)); + else + fput(filp); - init_unlink(devname); + init_unlink(devname); + } kfree(devname); } diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index ca473ca198b8..0f72352030ba 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -260,20 +260,16 @@ static int sev_cmd_buffer_len(int cmd) static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) { - struct path root __free(path_put) = {}; - - task_lock(&init_task); - get_fs_root(init_task.fs, &root); - task_unlock(&init_task); - CLASS(prepare_creds, cred)(); if (!cred) return ERR_PTR(-ENOMEM); cred->fsuid = GLOBAL_ROOT_UID; - scoped_with_creds(cred) - return file_open_root(&root, filename, flags, mode); + scoped_with_init_fs() { + scoped_with_creds(cred) + return filp_open(filename, flags, mode); + } } static int sev_read_init_ex_file(void) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 10250aca5a81..140154d93c43 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -18,6 +18,8 @@ #include <linux/fcntl.h> #include <linux/file.h> #include <linux/fs.h> +#include <linux/fs_struct.h> +#include <linux/kthread.h> #include <scsi/scsi_proto.h> #include <linux/unaligned.h> @@ -856,10 +858,17 @@ static int core_alua_write_tpg_metadata( unsigned char *md_buf, u32 md_buf_len) { - struct file *file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); + struct file *file; loff_t pos = 0; int ret; + if (tsk_is_kthread(current)) { + scoped_with_init_fs() + file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); + } else { + file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); + } + if (IS_ERR(file)) { pr_err("filp_open(%s) for ALUA metadata failed\n", path); return -ENODEV; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1a77b4bb62b0..25b1bcacc0c8 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -18,6 +18,7 @@ #include <linux/file.h> #include <linux/fcntl.h> #include <linux/fs.h> +#include <linux/fs_struct.h> #include <scsi/scsi_proto.h> #include <linux/unaligned.h> @@ -1969,7 +1970,8 @@ static int __core_scsi3_write_aptpl_to_file( if (!path) return -ENOMEM; - file = filp_open(path, flags, 0600); + scoped_with_init_fs() + file = filp_open(path, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) for APTPL metadata" " failed\n", path); |
