projects/linux·commit fff0150b

Merge tag 'vfs-7.3-rc1.kthread' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

fff0150b · Linus Torvalds <[email protected]> · 2026-08-17 11:35:12 -07:00

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
  ...
Commit
fff0150b0299f834fe2c335ce0eb5c68bb414cbd
Parents
de03b17e · b4343aeb

Merge commit. Changes below are compared with the first parent: de03b17e.

Changes

31 files changed · +311 −116

Only the first 600 diff lines are shown. Download the complete patch.

drivers/base/devtmpfs.c

View file
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index b1c4ceb..aef0fcc 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);

drivers/block/rnbd/rnbd-srv.c

View file
diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
index 10e8c43..79c9a5f 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",

drivers/char/misc_minor_kunit.c

View file
diff --git a/drivers/char/misc_minor_kunit.c b/drivers/char/misc_minor_kunit.c
index e930c78..e85210c 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);
}

drivers/crypto/ccp/sev-dev.c

View file
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index ca473ca..0f72352 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)

drivers/target/target_core_alua.c

View file
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 10250ac..140154d 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;

drivers/target/target_core_pr.c

View file
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 1a77b4b..25b1bca 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);

fs/btrfs/volumes.c

View file
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 6eab4cc..dc5f4a1 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -12,6 +12,7 @@
#include <linux/uuid.h>
#include <linux/list_sort.h>
#include <linux/namei.h>
+#include <linux/fs_struct.h>
#include "misc.h"
#include "disk-io.h"
#include "extent-tree.h"
@@ -2125,8 +2126,16 @@ static int btrfs_add_dev_item(struct btrfs_trans_handle *trans,
static void update_dev_time(const char *device_path)
{
struct path path;
+ int err;
- if (!kern_path(device_path, LOOKUP_FOLLOW, &path)) {
+ if (tsk_is_kthread(current)) {
+ scoped_with_init_fs()
+ err = kern_path(device_path, LOOKUP_FOLLOW, &path);
+ } else {
+ err = kern_path(device_path, LOOKUP_FOLLOW, &path);
+ }
+
+ if (!err) {
vfs_utimes(&path, NULL);
path_put(&path);
}

fs/coredump.c

View file
diff --git a/fs/coredump.c b/fs/coredump.c
index e68a76f..ac3cd74 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -921,15 +921,10 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm,
* with a fully qualified path" rule is to control where
* coredumps may be placed using root privileges,
* current->fs->root must not be used. Instead, use the
- * root directory of init_task.
+ * root directory of PID 1.
*/
- struct path root;
-
- task_lock(&init_task);
- get_fs_root(init_task.fs, &root);
- task_unlock(&init_task);
- file = file_open_root(&root, cn->corename, open_flags, 0600);
- path_put(&root);
+ scoped_with_init_fs()
+ file = filp_open(cn->corename, open_flags, 0600);
} else {
file = filp_open(cn->corename, open_flags, 0600);
}

fs/fs_struct.c

View file
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 394875d..34699f3 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -8,6 +8,7 @@
#include <linux/fs_struct.h>
#include <linux/init_task.h>
#include "internal.h"
+#include "mount.h"
/*
* Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
@@ -60,8 +61,11 @@ void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
read_lock(&tasklist_lock);
for_each_process_thread(g, p) {
+ if (p->flags & (PF_KTHREAD | PF_EXITING | PF_DUMPCORE))
+ continue;
+
task_lock(p);
- fs = p->fs;
+ fs = p->real_fs;
if (fs) {
int hits = 0;
write_seqlock(&fs->seq);
@@ -89,12 +93,13 @@ void free_fs_struct(struct fs_struct *fs)
void exit_fs(struct task_struct *tsk)
{
- struct fs_struct *fs = tsk->fs;
+ struct fs_struct *fs = tsk->real_fs;
if (fs) {
int kill;
task_lock(tsk);
read_seqlock_excl(&fs->seq);
+ tsk->real_fs = NULL;
tsk->fs = NULL;
kill = !--fs->users;
read_sequnlock_excl(&fs->seq);
@@ -126,7 +131,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
int unshare_fs_struct(void)
{
- struct fs_struct *fs = current->fs;
+ struct fs_struct *fs = current->real_fs;
struct fs_struct *new_fs = copy_fs_struct(fs);
int kill;
@@ -135,8 +140,10 @@ int unshare_fs_struct(void)
task_lock(current);
read_seqlock_excl(&fs->seq);
+ VFS_WARN_ON_ONCE(fs != current->fs);
kill = !--fs->users;
current->fs = new_fs;
+ current->real_fs = new_fs;
read_sequnlock_excl(&fs->seq);
task_unlock(current);
@@ -147,9 +154,99 @@ int unshare_fs_struct(void)
}
EXPORT_SYMBOL_GPL(unshare_fs_struct);
+/*
+ * PID 1 may choose to stop sharing fs_struct state with us.
+ * Either via unshare(CLONE_FS) or unshare(CLONE_NEWNS). Of
+ * course, PID 1 could have chosen to create arbitrary process
+ * trees that all share fs_struct state via CLONE_FS. This is a
+ * strong statement: We only care about PID 1 aka the thread-group
+ * leader so subthread's fs_struct state doesn't matter.
+ *
+ * PID 1 unsharing fs_struct state is a bug. PID 1 relies on
+ * various kthreads to be able to perform work based on its
+ * fs_struct state. Breaking that contract sucks for both sides.
+ * So just don't bother with extra work for this. No sane init
+ * system should ever do this.
+ *
+ * On older kernels if PID 1 unshared its filesystem state with us the
+ * kernel simply used the stale fs_struct state implicitly pinning
+ * anything that PID 1 had last used. Even if PID 1 might've moved on to
+ * some completely different fs_struct state and might've even unmounted
+ * the old root.
+ *
+ * This has hilarious consequences: Think continuing to dump coredump
+ * state into an implicitly pinned directory somewhere. Calling random
+ * binaries in the old rootfs via usermodehelpers.
+ *
+ * Be aggressive about this: We simply reject operating on stale
+ * fs_struct state by reverting to nullfs. Every kworker that does
+ * lookups after this point will fail. Every usermodehelper call will
+ * fail. Tough luck but let's be kind and emit a warning to userspace.
+ */
+static inline void validate_fs_switch(struct fs_struct *old_fs)
+{
+ might_sleep();
+
+ if (likely(current->pid != 1))
+ return;
+ /* @old_fs may be dangling but for comparison it's fine */
+ if (old_fs != userspace_init_fs)
+ return;
+ pr_warn("VFS: Pid 1 stopped sharing filesystem state\n");
+ set_fs_root(userspace_init_fs, &init_fs.root);
+ set_fs_pwd(userspace_init_fs, &init_fs.root);
+}
+
+struct fs_struct *switch_fs_struct(struct fs_struct *new_fs)
+{
+ struct fs_struct *fs;
+
+ scoped_guard(task_lock, current) {
+ fs = current->fs;
+ VFS_WARN_ON_ONCE(fs != current->real_fs);
+ read_seqlock_excl(&fs->seq);
+ current->fs = new_fs;
+ current->real_fs = new_fs;
+ if (--fs->users)
+ new_fs = NULL;
+ else
+ new_fs = fs;
+ read_sequnlock_excl(&fs->seq);
+ }
+
+ validate_fs_switch(fs);
+ return new_fs;
+}
+
/* to be mentioned only in INIT_TASK */
struct fs_struct init_fs = {
.users = 1,
.seq = __SEQLOCK_UNLOCKED(init_fs.seq),
.umask = 0022,
};
+
+struct fs_struct *userspace_init_fs __ro_after_init;
+EXPORT_SYMBOL_GPL(userspace_init_fs);
+
+void __init init_userspace_fs(void)
+{
+ struct mount *m;
+ struct path root;
+
+ /* Move PID 1 from nullfs into the initramfs. */
+ m = topmost_overmount(current->nsproxy->mnt_ns->root);
+ root.mnt = &m->mnt;
+ root.dentry = root.mnt->mnt_root;
+
+ VFS_WARN_ON_ONCE(current->pid != 1);
+
+ set_fs_root(current->fs, &root);
+ set_fs_pwd(current->fs, &root);
+
+ /* Hold a reference for the global pointer. */
+ read_seqlock_excl(&current->fs->seq);
+ current->fs->users++;
+ read_sequnlock_excl(&current->fs->seq);
+
+ userspace_init_fs = current->fs;
+}

fs/kernel_read_file.c

View file
diff --git a/fs/kernel_read_file.c b/fs/kernel_read_file.c
index de32c95..9c2ba92 100644
--- a/fs/kernel_read_file.c
+++ b/fs/kernel_read_file.c
@@ -150,18 +150,13 @@ ssize_t kernel_read_file_from_path_initns(const char *path, loff_t offset,
enum kernel_read_file_id id)
{
struct file *file;
- struct path root;
ssize_t ret;
if (!path || !*path)
return -EINVAL;
- task_lock(&init_task);
- get_fs_root(init_task.fs, &root);
- task_unlock(&init_task);
-
- file = file_open_root(&root, path, O_RDONLY, 0);
- path_put(&root);
+ scoped_with_init_fs()
+ file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file))
return PTR_ERR(file);

fs/namespace.c

View file
diff --git a/fs/namespace.c b/fs/namespace.c
index 87c365f..eca22ce 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -6184,12 +6184,14 @@ static void __init init_mount_tree(void)
struct path root;
/*
- * We create two mounts:
+ * We create three mounts:
*
* (1) nullfs with mount id 1
* (2) mutable rootfs with mount id 2
+ * (3) private nullfs for kthreads (SB_KERNMOUNT)
*
- * with (2) mounted on top of (1).
+ * with (2) mounted on top of (1). The init_task's root and pwd
+ * are pointed at (3) so all kthreads start isolated in nullfs.
*/
nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);
if (IS_ERR(nullfs_mnt))
@@ -6229,12 +6231,14 @@ static void __init init_mount_tree(void)
init_mnt_ns.nr_mounts++;
}
+ nullfs_mnt = kern_mount(&nullfs_fs_type);
+ if (IS_ERR(nullfs_mnt))
+ panic("VFS: Failed to create private nullfs instance");
+ root.mnt = nullfs_mnt;
+ root.dentry = nullfs_mnt->mnt_root;
+
init_task.nsproxy->mnt_ns = &init_mnt_ns;
get_mnt_ns(&init_mnt_ns);
-
- /* The root and pwd always point to the mutable rootfs. */
- root.mnt = mnt;
- root.dentry = mnt->mnt_root;
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);

fs/nfs/blocklayout/dev.c

View file
diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c
index bb35f88..368d20d 100644
--- a/fs/nfs/blocklayout/dev.c
+++ b/fs/nfs/blocklayout/dev.c
@@ -4,6 +4,7 @@
*/
#include <linux/sunrpc/svc.h>
#include <linux/blkdev.h>
+#include <linux/fs_struct.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_xdr.h>
@@ -363,15 +364,22 @@ static struct file *
bl_open_path(struct pnfs_block_volume *v, const char *prefix)
{
struct file *bdev_file;
- const char *devname;
+ const char *devname __free(kfree) = NULL;
devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",
prefix, v->scsi.designator_len, v->scsi.designator);
if (!devname)
return ERR_PTR(-ENOMEM);
- bdev_file = bdev_file_open_by_path(devname,
- BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
+ if (tsk_is_kthread(current)) {
+ scoped_with_init_fs()
+ bdev_file = bdev_file_open_by_path(devname,
+ BLK_OPEN_READ | BLK_OPEN_WRITE,
+ NULL, NULL);
+ } else {
+ bdev_file = bdev_file_open_by_path(devname,
+ BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
+ }
if (IS_ERR(bdev_file)) {
dprintk("failed to open device %s (%ld)\n",
devname, PTR_ERR(bdev_file));
@@ -380,7 +388,6 @@ bl_open_path(struct pnfs_block_volume *v, const char *prefix)
file_bdev(bdev_file)->bd_disk->disk_name);
}
- kfree(devname);
return bdev_file;
}

fs/nullfs.c

View file
diff --git a/fs/nullfs.c b/fs/nullfs.c
index fdbd3e5..c6f5b94 100644
--- a/fs/nullfs.c
+++ b/fs/nullfs.c
@@ -40,14 +40,9 @@ static int nullfs_fs_fill_super(struct super_block *s, struct fs_context *fc)
return 0;
}
-/*
- * For now this is a single global instance. If needed we can make it
- * mountable by userspace at which point we will need to make it
- * multi-instance.
- */
static int nullfs_fs_get_tree(struct fs_context *fc)
{
- return get_tree_single(fc, nullfs_fs_fill_super);
+ return get_tree_nodev(fc, nullfs_fs_fill_super);
}
static const struct fs_context_operations nullfs_fs_context_ops = {
@@ -57,9 +52,8 @@ static const struct fs_context_operations nullfs_fs_context_ops = {
static int nullfs_init_fs_context(struct fs_context *fc)
{
fc->ops = &nullfs_fs_context_ops;
- fc->global = true;
- fc->sb_flags = SB_NOUSER;
- fc->s_iflags = SB_I_NOEXEC | SB_I_NODEV;
+ fc->sb_flags |= SB_NOUSER;
+ fc->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
return 0;
}

fs/proc/array.c

View file
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 479ea8c..f6f75d2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -168,8 +168,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
cred = get_task_cred(p);
task_lock(p);
- if (p->fs)
- umask = p->fs->umask;
+ if (p->real_fs)
+ umask = p->real_fs->umask;
if (p->files)
max_fds = files_fdtable(p->files)->max_fds;
task_unlock(p);

fs/proc/base.c

View file
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 780f812..6a39de4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -211,8 +211,8 @@ static int get_task_root(struct task_struct *task, struct path *root)
int result = -ENOENT;
task_lock(task);
- if (task->fs) {
- get_fs_root(task->fs, root);
+ if (task->real_fs) {
+ get_fs_root(task->real_fs, root);
result = 0;
}
task_unlock(task);
@@ -225,8 +225,8 @@ static int proc_cwd_link(struct dentry *dentry, struct path *path,
int result = -ENOENT;
task_lock(task);
- if (task->fs) {
- get_fs_pwd(task->fs, path);
+ if (task->real_fs) {
+ get_fs_pwd(task->real_fs, path);
result = 0;
}
task_unlock(task);

fs/proc_namespace.c

View file
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index 5c555db..036356c 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -254,13 +254,13 @@ static int mounts_open_common(struct inode *inode, struct file *file,
}
ns = nsp->mnt_ns;
get_mnt_ns(ns);
- if (!task->fs) {
+ if (!task->real_fs) {
task_unlock(task);
put_task_struct(task);
ret = -ENOENT;
goto err_put_ns;
}
- get_fs_root(task->fs, &root);
+ get_fs_root(task->real_fs, &root);
task_unlock(task);
put_task_struct(task);

fs/smb/server/mgmt/share_config.c

View file
diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
index 6f97f8d..e00aee1 100644
--- a/fs/smb/server/mgmt/share_config.c
+++ b/fs/smb/server/mgmt/share_config.c
@@ -9,6 +9,7 @@
#include <linux/rwsem.h>
#include <linux/parser.h>
#include <linux/namei.h>
+#include <linux/fs_struct.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -193,7 +194,8 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
goto out;
}
- ret = kern_path(share->path, 0, &share->vfs_path);
+ scoped_with_init_fs()
+ ret = kern_path(share->path, 0, &share->vfs_path);
ksmbd_revert_fsids(work);

This diff is incomplete. Download the complete patch.

fs/smb/server/smb2pdu.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/server/vfs.c

View file

This diff is incomplete. Download the complete patch.

include/linux/fs_struct.h

View file

This diff is incomplete. Download the complete patch.

include/linux/init_task.h

View file

This diff is incomplete. Download the complete patch.

include/linux/sched.h

View file

This diff is incomplete. Download the complete patch.

include/linux/sched/task.h

View file

This diff is incomplete. Download the complete patch.

init/init_task.c

View file

This diff is incomplete. Download the complete patch.

init/initramfs.c

View file

This diff is incomplete. Download the complete patch.

init/initramfs_test.c

View file

This diff is incomplete. Download the complete patch.

init/main.c

View file

This diff is incomplete. Download the complete patch.

kernel/fork.c

View file

This diff is incomplete. Download the complete patch.

kernel/kcmp.c

View file

This diff is incomplete. Download the complete patch.

kernel/umh.c

View file

This diff is incomplete. Download the complete patch.

net/unix/af_unix.c

View file

This diff is incomplete. Download the complete patch.