History

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 ...

Linus Torvalds committed 2 months ago

Commit fff01502 parents de03b17 b4343ae31 files · +311 −116Browse files

Unified · Split

31 files
  1. drivers/base/devtmpfs.c +1 −1
  2. drivers/block/rnbd/rnbd-srv.c +3 −1
  3. drivers/char/misc_minor_kunit.c +15 −10
  4. drivers/crypto/ccp/sev-dev.c +4 −8
  5. drivers/target/target_core_alua.c +10 −1
  6. drivers/target/target_core_pr.c +3 −1
  7. fs/btrfs/volumes.c +10 −1
  8. fs/coredump.c +3 −8
  9. fs/fs_struct.c +100 −3
  10. fs/kernel_read_file.c +2 −7
  11. fs/namespace.c +10 −6
  12. fs/nfs/blocklayout/dev.c +11 −4
  13. fs/nullfs.c +3 −9
  14. fs/proc/array.c +2 −2
  15. fs/proc/base.c +4 −4
  16. fs/proc_namespace.c +2 −2
  17. fs/smb/server/mgmt/share_config.c +3 −1
  18. fs/smb/server/smb2pdu.c +3 −1
  19. fs/smb/server/vfs.c +6 −3
  20. include/linux/fs_struct.h +34 −0
  21. include/linux/init_task.h +1 −0
  22. include/linux/sched.h +1 −0
  23. include/linux/sched/task.h +1 −0
  24. init/init_task.c +1 −0
  25. init/initramfs.c +10 −4
  26. init/initramfs_test.c +17 −2
  27. init/main.c +9 −1
  28. kernel/fork.c +33 −20
  29. kernel/kcmp.c +1 −1
  30. kernel/umh.c +2 −4
  31. net/unix/af_unix.c +6 −11
drivers/base/devtmpfs.c+1−1
@@ -413,7 +413,7 @@ static noinline int __init devtmpfs_setup(void *p) · 412 unmodified lines
413413 {
414414 int err;
415415
416− err = ksys_unshare(CLONE_NEWNS);
416+ err = ksys_unshare(UNSHARE_EMPTY_MNTNS);
417417 if (err)
418418 goto out;
419419 err = init_mount("devtmpfs", "/", "devtmpfs", DEVTMPFS_MFLAGS, NULL);
drivers/block/rnbd/rnbd-srv.c+3−1
@@ -11,6 +11,7 @@ · 10 unmodified lines
1111
1212 #include <linux/module.h>
1313 #include <linux/blkdev.h>
14+#include <linux/fs_struct.h>
1415
1516 #include "rnbd-srv.h"
1617 #include "rnbd-srv-trace.h"
@@ -734,7 +735,8 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, · 717 unmodified lines
734735 goto reject;
735736 }
736737
737− bdev_file = bdev_file_open_by_path(full_path, open_flags, NULL, NULL);
738+ scoped_with_init_fs()
739+ bdev_file = bdev_file_open_by_path(full_path, open_flags, NULL, NULL);
738740 if (IS_ERR(bdev_file)) {
739741 ret = PTR_ERR(bdev_file);
740742 pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %pe\n",
drivers/char/misc_minor_kunit.c+15−10
@@ -5,6 +5,7 @@ · 4 unmodified lines
55 #include <linux/miscdevice.h>
66 #include <linux/fs.h>
77 #include <linux/file.h>
8+#include <linux/fs_struct.h>
89 #include <linux/init_syscalls.h>
910
1011 /* static minor (LCD_MINOR) */
@@ -160,18 +161,22 @@ static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice * · 149 unmodified lines
160161 char *devname;
161162
162163 devname = kasprintf(GFP_KERNEL, "/dev/%s", misc->name);
163− ret = init_mknod(devname, S_IFCHR | 0600,
164− new_encode_dev(MKDEV(MISC_MAJOR, misc->minor)));
165− if (ret != 0)
166− KUNIT_FAIL(test, "failed to create node\n");
167164
168− filp = filp_open(devname, O_RDONLY, 0);
169− if (IS_ERR(filp))
170− KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));
171− else
172− fput(filp);
165+ /* Tests run in a nullfs kthread; borrow the init fs to resolve /dev. */
166+ scoped_with_init_fs() {
167+ ret = init_mknod(devname, S_IFCHR | 0600,
168+ new_encode_dev(MKDEV(MISC_MAJOR, misc->minor)));
169+ if (ret != 0)
170+ KUNIT_FAIL(test, "failed to create node\n");
171+
172+ filp = filp_open(devname, O_RDONLY, 0);
173+ if (IS_ERR(filp))
174+ KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));
175+ else
176+ fput(filp);
173177
174− init_unlink(devname);
178+ init_unlink(devname);
179+ }
175180 kfree(devname);
176181 }
177182
drivers/crypto/ccp/sev-dev.c+4−8
@@ -260,20 +260,16 @@ static int sev_cmd_buffer_len(int cmd) · 259 unmodified lines
260260
261261 static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
262262 {
263− struct path root __free(path_put) = {};
264−
265− task_lock(&init_task);
266− get_fs_root(init_task.fs, &root);
267− task_unlock(&init_task);
268−
269263 CLASS(prepare_creds, cred)();
270264 if (!cred)
271265 return ERR_PTR(-ENOMEM);
272266
273267 cred->fsuid = GLOBAL_ROOT_UID;
274268
275− scoped_with_creds(cred)
276− return file_open_root(&root, filename, flags, mode);
269+ scoped_with_init_fs() {
270+ scoped_with_creds(cred)
271+ return filp_open(filename, flags, mode);
272+ }
277273 }
278274
279275 static int sev_read_init_ex_file(void)
drivers/target/target_core_alua.c+10−1
@@ -18,6 +18,8 @@ · 17 unmodified lines
1818 #include <linux/fcntl.h>
1919 #include <linux/file.h>
2020 #include <linux/fs.h>
21+#include <linux/fs_struct.h>
22+#include <linux/kthread.h>
2123 #include <scsi/scsi_proto.h>
2224 #include <linux/unaligned.h>
2325
@@ -856,10 +858,17 @@ static int core_alua_write_tpg_metadata( · 832 unmodified lines
856858 unsigned char *md_buf,
857859 u32 md_buf_len)
858860 {
859− struct file *file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600);
861+ struct file *file;
860862 loff_t pos = 0;
861863 int ret;
862864
865+ if (tsk_is_kthread(current)) {
866+ scoped_with_init_fs()
867+ file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600);
868+ } else {
869+ file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600);
870+ }
871+
863872 if (IS_ERR(file)) {
864873 pr_err("filp_open(%s) for ALUA metadata failed\n", path);
865874 return -ENODEV;
drivers/target/target_core_pr.c+3−1
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <linux/file.h>
1919 #include <linux/fcntl.h>
2020 #include <linux/fs.h>
21+#include <linux/fs_struct.h>
2122 #include <scsi/scsi_proto.h>
2223 #include <linux/unaligned.h>
2324
@@ -1969,7 +1970,8 @@ static int __core_scsi3_write_aptpl_to_file( · 1945 unmodified lines
19691970 if (!path)
19701971 return -ENOMEM;
19711972
1972− file = filp_open(path, flags, 0600);
1973+ scoped_with_init_fs()
1974+ file = filp_open(path, flags, 0600);
19731975 if (IS_ERR(file)) {
19741976 pr_err("filp_open(%s) for APTPL metadata"
19751977 " failed\n", path);
fs/btrfs/volumes.c+10−1
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #include <linux/uuid.h>
1313 #include <linux/list_sort.h>
1414 #include <linux/namei.h>
15+#include <linux/fs_struct.h>
1516 #include "misc.h"
1617 #include "disk-io.h"
1718 #include "extent-tree.h"
@@ -2125,8 +2126,16 @@ static int btrfs_add_dev_item(struct btrfs_trans_handle *trans, · 2107 unmodified lines
21252126 static void update_dev_time(const char *device_path)
21262127 {
21272128 struct path path;
2129+ int err;
21282130
2129− if (!kern_path(device_path, LOOKUP_FOLLOW, &path)) {
2131+ if (tsk_is_kthread(current)) {
2132+ scoped_with_init_fs()
2133+ err = kern_path(device_path, LOOKUP_FOLLOW, &path);
2134+ } else {
2135+ err = kern_path(device_path, LOOKUP_FOLLOW, &path);
2136+ }
2137+
2138+ if (!err) {
21302139 vfs_utimes(&path, NULL);
21312140 path_put(&path);
21322141 }
fs/coredump.c+3−8
@@ -921,15 +921,10 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm, · 920 unmodified lines
921921 * with a fully qualified path" rule is to control where
922922 * coredumps may be placed using root privileges,
923923 * current->fs->root must not be used. Instead, use the
924− * root directory of init_task.
924+ * root directory of PID 1.
925925 */
926− struct path root;
927−
928− task_lock(&init_task);
929− get_fs_root(init_task.fs, &root);
930− task_unlock(&init_task);
931− file = file_open_root(&root, cn->corename, open_flags, 0600);
932− path_put(&root);
926+ scoped_with_init_fs()
927+ file = filp_open(cn->corename, open_flags, 0600);
933928 } else {
934929 file = filp_open(cn->corename, open_flags, 0600);
935930 }
fs/fs_struct.c+100−3
@@ -8,6 +8,7 @@ · 7 unmodified lines
88 #include <linux/fs_struct.h>
99 #include <linux/init_task.h>
1010 #include "internal.h"
11+#include "mount.h"
1112
1213 /*
1314 * 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) · 46 unmodified lines
6061
6162 read_lock(&tasklist_lock);
6263 for_each_process_thread(g, p) {
64+ if (p->flags & (PF_KTHREAD | PF_EXITING | PF_DUMPCORE))
65+ continue;
66+
6367 task_lock(p);
64− fs = p->fs;
68+ fs = p->real_fs;
6569 if (fs) {
6670 int hits = 0;
6771 write_seqlock(&fs->seq);
@@ -89,12 +93,13 @@ void free_fs_struct(struct fs_struct *fs) · 21 unmodified lines
8993
9094 void exit_fs(struct task_struct *tsk)
9195 {
92− struct fs_struct *fs = tsk->fs;
96+ struct fs_struct *fs = tsk->real_fs;
9397
9498 if (fs) {
9599 int kill;
96100 task_lock(tsk);
97101 read_seqlock_excl(&fs->seq);
102+ tsk->real_fs = NULL;
98103 tsk->fs = NULL;
99104 kill = !--fs->users;
100105 read_sequnlock_excl(&fs->seq);
@@ -126,7 +131,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) · 25 unmodified lines
126131
127132 int unshare_fs_struct(void)
128133 {
129− struct fs_struct *fs = current->fs;
134+ struct fs_struct *fs = current->real_fs;
130135 struct fs_struct *new_fs = copy_fs_struct(fs);
131136 int kill;
132137
@@ -135,8 +140,10 @@ int unshare_fs_struct(void) · 2 unmodified lines
135140
136141 task_lock(current);
137142 read_seqlock_excl(&fs->seq);
143+ VFS_WARN_ON_ONCE(fs != current->fs);
138144 kill = !--fs->users;
139145 current->fs = new_fs;
146+ current->real_fs = new_fs;
140147 read_sequnlock_excl(&fs->seq);
141148 task_unlock(current);
142149
@@ -147,9 +154,99 @@ int unshare_fs_struct(void) · 4 unmodified lines
147154 }
148155 EXPORT_SYMBOL_GPL(unshare_fs_struct);
149156
157+/*
158+ * PID 1 may choose to stop sharing fs_struct state with us.
159+ * Either via unshare(CLONE_FS) or unshare(CLONE_NEWNS). Of
160+ * course, PID 1 could have chosen to create arbitrary process
161+ * trees that all share fs_struct state via CLONE_FS. This is a
162+ * strong statement: We only care about PID 1 aka the thread-group
163+ * leader so subthread's fs_struct state doesn't matter.
164+ *
165+ * PID 1 unsharing fs_struct state is a bug. PID 1 relies on
166+ * various kthreads to be able to perform work based on its
167+ * fs_struct state. Breaking that contract sucks for both sides.
168+ * So just don't bother with extra work for this. No sane init
169+ * system should ever do this.
170+ *
171+ * On older kernels if PID 1 unshared its filesystem state with us the
172+ * kernel simply used the stale fs_struct state implicitly pinning
173+ * anything that PID 1 had last used. Even if PID 1 might've moved on to
174+ * some completely different fs_struct state and might've even unmounted
175+ * the old root.
176+ *
177+ * This has hilarious consequences: Think continuing to dump coredump
178+ * state into an implicitly pinned directory somewhere. Calling random
179+ * binaries in the old rootfs via usermodehelpers.
180+ *
181+ * Be aggressive about this: We simply reject operating on stale
182+ * fs_struct state by reverting to nullfs. Every kworker that does
183+ * lookups after this point will fail. Every usermodehelper call will
184+ * fail. Tough luck but let's be kind and emit a warning to userspace.
185+ */
186+static inline void validate_fs_switch(struct fs_struct *old_fs)
187+{
188+ might_sleep();
189+
190+ if (likely(current->pid != 1))
191+ return;
192+ /* @old_fs may be dangling but for comparison it's fine */
193+ if (old_fs != userspace_init_fs)
194+ return;
195+ pr_warn("VFS: Pid 1 stopped sharing filesystem state\n");
196+ set_fs_root(userspace_init_fs, &init_fs.root);
197+ set_fs_pwd(userspace_init_fs, &init_fs.root);
198+}
199+
200+struct fs_struct *switch_fs_struct(struct fs_struct *new_fs)
201+{
202+ struct fs_struct *fs;
203+
204+ scoped_guard(task_lock, current) {
205+ fs = current->fs;
206+ VFS_WARN_ON_ONCE(fs != current->real_fs);
207+ read_seqlock_excl(&fs->seq);
208+ current->fs = new_fs;
209+ current->real_fs = new_fs;
210+ if (--fs->users)
211+ new_fs = NULL;
212+ else
213+ new_fs = fs;
214+ read_sequnlock_excl(&fs->seq);
215+ }
216+
217+ validate_fs_switch(fs);
218+ return new_fs;
219+}
220+
150221 /* to be mentioned only in INIT_TASK */
151222 struct fs_struct init_fs = {
152223 .users = 1,
153224 .seq = __SEQLOCK_UNLOCKED(init_fs.seq),
154225 .umask = 0022,
155226 };
227+
228+struct fs_struct *userspace_init_fs __ro_after_init;
229+EXPORT_SYMBOL_GPL(userspace_init_fs);
230+
231+void __init init_userspace_fs(void)
232+{
233+ struct mount *m;
234+ struct path root;
235+
236+ /* Move PID 1 from nullfs into the initramfs. */
237+ m = topmost_overmount(current->nsproxy->mnt_ns->root);
238+ root.mnt = &m->mnt;
239+ root.dentry = root.mnt->mnt_root;
240+
241+ VFS_WARN_ON_ONCE(current->pid != 1);
242+
243+ set_fs_root(current->fs, &root);
244+ set_fs_pwd(current->fs, &root);
245+
246+ /* Hold a reference for the global pointer. */
247+ read_seqlock_excl(&current->fs->seq);
248+ current->fs->users++;
249+ read_sequnlock_excl(&current->fs->seq);
250+
251+ userspace_init_fs = current->fs;
252+}
fs/kernel_read_file.c+2−7
@@ -150,18 +150,13 @@ ssize_t kernel_read_file_from_path_initns(const char *path, loff_t offset, · 149 unmodified lines
150150 enum kernel_read_file_id id)
151151 {
152152 struct file *file;
153− struct path root;
154153 ssize_t ret;
155154
156155 if (!path || !*path)
157156 return -EINVAL;
158157
159− task_lock(&init_task);
160− get_fs_root(init_task.fs, &root);
161− task_unlock(&init_task);
162−
163− file = file_open_root(&root, path, O_RDONLY, 0);
164− path_put(&root);
158+ scoped_with_init_fs()
159+ file = filp_open(path, O_RDONLY, 0);
165160 if (IS_ERR(file))
166161 return PTR_ERR(file);
167162
fs/namespace.c+10−6
@@ -6184,12 +6184,14 @@ static void __init init_mount_tree(void) · 6183 unmodified lines
61846184 struct path root;
61856185
61866186 /*
6187− * We create two mounts:
6187+ * We create three mounts:
61886188 *
61896189 * (1) nullfs with mount id 1
61906190 * (2) mutable rootfs with mount id 2
6191+ * (3) private nullfs for kthreads (SB_KERNMOUNT)
61916192 *
6192− * with (2) mounted on top of (1).
6193+ * with (2) mounted on top of (1). The init_task's root and pwd
6194+ * are pointed at (3) so all kthreads start isolated in nullfs.
61936195 */
61946196 nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);
61956197 if (IS_ERR(nullfs_mnt))
@@ -6229,12 +6231,14 @@ static void __init init_mount_tree(void) · 33 unmodified lines
62296231 init_mnt_ns.nr_mounts++;
62306232 }
62316233
6234+ nullfs_mnt = kern_mount(&nullfs_fs_type);
6235+ if (IS_ERR(nullfs_mnt))
6236+ panic("VFS: Failed to create private nullfs instance");
6237+ root.mnt = nullfs_mnt;
6238+ root.dentry = nullfs_mnt->mnt_root;
6239+
62326240 init_task.nsproxy->mnt_ns = &init_mnt_ns;
62336241 get_mnt_ns(&init_mnt_ns);
6234−
6235− /* The root and pwd always point to the mutable rootfs. */
6236− root.mnt = mnt;
6237− root.dentry = mnt->mnt_root;
62386242 set_fs_pwd(current->fs, &root);
62396243 set_fs_root(current->fs, &root);
62406244
fs/nfs/blocklayout/dev.c+11−4
@@ -4,6 +4,7 @@ · 3 unmodified lines
44 */
55 #include <linux/sunrpc/svc.h>
66 #include <linux/blkdev.h>
7+#include <linux/fs_struct.h>
78 #include <linux/nfs4.h>
89 #include <linux/nfs_fs.h>
910 #include <linux/nfs_xdr.h>
@@ -363,15 +364,22 @@ static struct file * · 353 unmodified lines
363364 bl_open_path(struct pnfs_block_volume *v, const char *prefix)
364365 {
365366 struct file *bdev_file;
366− const char *devname;
367+ const char *devname __free(kfree) = NULL;
367368
368369 devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",
369370 prefix, v->scsi.designator_len, v->scsi.designator);
370371 if (!devname)
371372 return ERR_PTR(-ENOMEM);
372373
373− bdev_file = bdev_file_open_by_path(devname,
374− BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
374+ if (tsk_is_kthread(current)) {
375+ scoped_with_init_fs()
376+ bdev_file = bdev_file_open_by_path(devname,
377+ BLK_OPEN_READ | BLK_OPEN_WRITE,
378+ NULL, NULL);
379+ } else {
380+ bdev_file = bdev_file_open_by_path(devname,
381+ BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
382+ }
375383 if (IS_ERR(bdev_file)) {
376384 dprintk("failed to open device %s (%ld)\n",
377385 devname, PTR_ERR(bdev_file));
@@ -380,7 +388,6 @@ bl_open_path(struct pnfs_block_volume *v, const char *prefix) · 2 unmodified lines
380388 file_bdev(bdev_file)->bd_disk->disk_name);
381389 }
382390
383− kfree(devname);
384391 return bdev_file;
385392 }
386393
fs/nullfs.c+3−9
@@ -40,14 +40,9 @@ static int nullfs_fs_fill_super(struct super_block *s, struct fs_context *fc) · 39 unmodified lines
4040 return 0;
4141 }
4242
43−/*
44− * For now this is a single global instance. If needed we can make it
45− * mountable by userspace at which point we will need to make it
46− * multi-instance.
47− */
4843 static int nullfs_fs_get_tree(struct fs_context *fc)
4944 {
50− return get_tree_single(fc, nullfs_fs_fill_super);
45+ return get_tree_nodev(fc, nullfs_fs_fill_super);
5146 }
5247
5348 static const struct fs_context_operations nullfs_fs_context_ops = {
@@ -57,9 +52,8 @@ static const struct fs_context_operations nullfs_fs_context_ops = { · 3 unmodified lines
5752 static int nullfs_init_fs_context(struct fs_context *fc)
5853 {
5954 fc->ops = &nullfs_fs_context_ops;
60− fc->global = true;
61− fc->sb_flags = SB_NOUSER;
62− fc->s_iflags = SB_I_NOEXEC | SB_I_NODEV;
55+ fc->sb_flags |= SB_NOUSER;
56+ fc->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
6357 return 0;
6458 }
6559
fs/proc/array.c+2−2
@@ -168,8 +168,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, · 167 unmodified lines
168168 cred = get_task_cred(p);
169169
170170 task_lock(p);
171− if (p->fs)
172− umask = p->fs->umask;
171+ if (p->real_fs)
172+ umask = p->real_fs->umask;
173173 if (p->files)
174174 max_fds = files_fdtable(p->files)->max_fds;
175175 task_unlock(p);
fs/proc/base.c+4−4
@@ -211,8 +211,8 @@ static int get_task_root(struct task_struct *task, struct path *root) · 210 unmodified lines
211211 int result = -ENOENT;
212212
213213 task_lock(task);
214− if (task->fs) {
215− get_fs_root(task->fs, root);
214+ if (task->real_fs) {
215+ get_fs_root(task->real_fs, root);
216216 result = 0;
217217 }
218218 task_unlock(task);
@@ -225,8 +225,8 @@ static int proc_cwd_link(struct dentry *dentry, struct path *path, · 6 unmodified lines
225225 int result = -ENOENT;
226226
227227 task_lock(task);
228− if (task->fs) {
229− get_fs_pwd(task->fs, path);
228+ if (task->real_fs) {
229+ get_fs_pwd(task->real_fs, path);
230230 result = 0;
231231 }
232232 task_unlock(task);
fs/proc_namespace.c+2−2
@@ -254,13 +254,13 @@ static int mounts_open_common(struct inode *inode, struct file *file, · 253 unmodified lines
254254 }
255255 ns = nsp->mnt_ns;
256256 get_mnt_ns(ns);
257− if (!task->fs) {
257+ if (!task->real_fs) {
258258 task_unlock(task);
259259 put_task_struct(task);
260260 ret = -ENOENT;
261261 goto err_put_ns;
262262 }
263− get_fs_root(task->fs, &root);
263+ get_fs_root(task->real_fs, &root);
264264 task_unlock(task);
265265 put_task_struct(task);
266266
fs/smb/server/mgmt/share_config.c+3−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <linux/rwsem.h>
1010 #include <linux/parser.h>
1111 #include <linux/namei.h>
12+#include <linux/fs_struct.h>
1213 #include <linux/sched.h>
1314 #include <linux/mm.h>
1415
@@ -193,7 +194,8 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work, · 178 unmodified lines
193194 goto out;
194195 }
195196
196− ret = kern_path(share->path, 0, &share->vfs_path);
197+ scoped_with_init_fs()
198+ ret = kern_path(share->path, 0, &share->vfs_path);
197199 ksmbd_revert_fsids(work);
198200 if (ret) {
199201 ksmbd_debug(SMB, "failed to access '%s'\n",
fs/smb/server/smb2pdu.c+3−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <net/addrconf.h>
1010 #include <linux/syscalls.h>
1111 #include <linux/namei.h>
12+#include <linux/fs_struct.h>
1213 #include <linux/statfs.h>
1314 #include <linux/ethtool.h>
1415 #include <linux/falloc.h>
@@ -5949,7 +5950,8 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 5934 unmodified lines
59495950 if (!share->path)
59505951 return -EIO;
59515952
5952− rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path);
5953+ scoped_with_init_fs()
5954+ rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path);
59535955 if (rc) {
59545956 pr_err("cannot create vfs path\n");
59555957 return -EIO;
fs/smb/server/vfs.c+6−3
@@ -7,6 +7,7 @@ · 6 unmodified lines
77 #include <crypto/sha2.h>
88 #include <linux/kernel.h>
99 #include <linux/fs.h>
10+#include <linux/fs_struct.h>
1011 #include <linux/filelock.h>
1112 #include <linux/uaccess.h>
1213 #include <linux/backing-dev.h>
@@ -67,8 +68,9 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf, · 54 unmodified lines
6768 }
6869
6970 CLASS(filename_kernel, filename)(pathname);
70− err = vfs_path_parent_lookup(filename, flags, path, &last,
71− root_share_path);
71+ scoped_with_init_fs()
72+ err = vfs_path_parent_lookup(filename, flags, path, &last,
73+ root_share_path);
7274 if (err)
7375 return err;
7476
@@ -623,7 +625,8 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname, · 548 unmodified lines
623625 if (ksmbd_override_fsids(work))
624626 return -ENOMEM;
625627
626− err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);
628+ scoped_with_init_fs()
629+ err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);
627630 if (err) {
628631 pr_err("cannot get linux path for %s, err = %d\n",
629632 oldname, err);
include/linux/fs_struct.h+34−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 #include <linux/path.h>
77 #include <linux/spinlock.h>
88 #include <linux/seqlock.h>
9+#include <linux/vfsdebug.h>
910
1011 struct fs_struct {
1112 int users;
@@ -16,6 +17,7 @@ struct fs_struct { · 4 unmodified lines
1617 } __randomize_layout;
1718
1819 extern struct kmem_cache *fs_cachep;
20+extern struct fs_struct *userspace_init_fs;
1921
2022 extern void exit_fs(struct task_struct *);
2123 extern void set_fs_root(struct fs_struct *, const struct path *);
@@ -40,6 +42,8 @@ static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd) · 18 unmodified lines
4042 read_sequnlock_excl(&fs->seq);
4143 }
4244
45+struct fs_struct *switch_fs_struct(struct fs_struct *new_fs);
46+
4347 extern bool current_chrooted(void);
4448
4549 static inline int current_umask(void)
@@ -47,4 +51,34 @@ static inline int current_umask(void) · 1 unmodified line
4751 return current->fs->umask;
4852 }
4953
54+/*
55+ * Temporarily use userspace_init_fs for path resolution in kthreads.
56+ * Callers should use scoped_with_init_fs() which automatically
57+ * restores the original fs_struct at scope exit.
58+ */
59+static inline struct fs_struct *__override_init_fs(void)
60+{
61+ struct fs_struct *old_fs;
62+
63+ old_fs = current->fs;
64+ WRITE_ONCE(current->fs, userspace_init_fs);
65+ return old_fs;
66+}
67+
68+static inline void __revert_init_fs(struct fs_struct *old_fs)
69+{
70+ VFS_WARN_ON_ONCE(current->fs != userspace_init_fs);
71+ WRITE_ONCE(current->fs, old_fs);
72+}
73+
74+DEFINE_CLASS(__override_init_fs,
75+ struct fs_struct *,
76+ __revert_init_fs(_T),
77+ __override_init_fs(), void)
78+
79+#define scoped_with_init_fs() \
80+ scoped_class(__override_init_fs, __UNIQUE_ID(label))
81+
82+void __init init_userspace_fs(void);
83+
5084 #endif /* _LINUX_FS_STRUCT_H */
include/linux/init_task.h+1−0
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424
2525 extern struct files_struct init_files;
2626 extern struct fs_struct init_fs;
27+extern struct fs_struct *userspace_init_fs;
2728 extern struct nsproxy init_nsproxy;
2829
2930 #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
include/linux/sched.h+1−0
@@ -1191,6 +1191,7 @@ struct task_struct { · 1190 unmodified lines
11911191 unsigned long last_switch_time;
11921192 #endif
11931193 /* Filesystem information: */
1194+ struct fs_struct *real_fs;
11941195 struct fs_struct *fs;
11951196
11961197 /* Open file information: */
include/linux/sched/task.h+1−0
@@ -31,6 +31,7 @@ struct kernel_clone_args { · 30 unmodified lines
3131 u32 io_thread:1;
3232 u32 user_worker:1;
3333 u32 no_files:1;
34+ u32 umh:1;
3435 unsigned long stack;
3536 unsigned long stack_size;
3637 unsigned long tls;
init/init_task.c+1−0
@@ -162,6 +162,7 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = { · 161 unmodified lines
162162 RCU_POINTER_INITIALIZER(cred, &init_cred),
163163 .comm = INIT_TASK_COMM,
164164 .thread = INIT_THREAD,
165+ .real_fs = &init_fs,
165166 .fs = &init_fs,
166167 .files = &init_files,
167168 #ifdef CONFIG_IO_URING
init/initramfs.c+10−4
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 #include <linux/fcntl.h>
77 #include <linux/file.h>
88 #include <linux/fs.h>
9+#include <linux/fs_struct.h>
910 #include <linux/hex.h>
1011 #include <linux/init.h>
1112 #include <linux/init_syscalls.h>
@@ -716,7 +717,7 @@ static void __init populate_initrd_image(char *err) · 704 unmodified lines
716717 }
717718 #endif /* CONFIG_BLK_DEV_RAM */
718719
719−static void __init do_populate_rootfs(void *unused, async_cookie_t cookie)
720+static void __init unpack_initramfs(async_cookie_t cookie)
720721 {
721722 /* Load the built in initramfs */
722723 char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
@@ -724,7 +725,7 @@ static void __init do_populate_rootfs(void *unused, async_cookie_t cookie) · 1 unmodified line
724725 panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */
725726
726727 if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
727− goto done;
728+ return;
728729
729730 if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
730731 printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
@@ -739,9 +740,14 @@ static void __init do_populate_rootfs(void *unused, async_cookie_t cookie) · 8 unmodified lines
739740 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
740741 #endif
741742 }
743+}
742744
743−done:
744− security_initramfs_populated();
745+static void __init do_populate_rootfs(void *unused, async_cookie_t cookie)
746+{
747+ scoped_with_init_fs() {
748+ unpack_initramfs(cookie);
749+ security_initramfs_populated();
750+ }
745751
746752 /*
747753 * If the initrd region is overlapped with crashkernel reserved region,
init/initramfs_test.c+17−2
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 #include <linux/fcntl.h>
44 #include <linux/file.h>
55 #include <linux/fs.h>
6+#include <linux/fs_struct.h>
67 #include <linux/init.h>
78 #include <linux/init_syscalls.h>
89 #include <linux/initrd.h>
@@ -562,7 +563,7 @@ static struct kunit_case __refdata initramfs_test_cases[] = { · 553 unmodified lines
562563 {},
563564 };
564565
565−static int __init initramfs_test_init(struct kunit_suite *suite)
566+static int __init initramfs_suite_init(struct kunit_suite *suite)
566567 {
567568 /*
568569 * unpack_to_rootfs() uses module-static state (victim, byte_count,
@@ -574,9 +575,23 @@ static int __init initramfs_test_init(struct kunit_suite *suite) · 5 unmodified lines
574575 return 0;
575576 }
576577
578+/* Tests run in a nullfs kthread; always use the init fs for path resolution. */
579+static int __init initramfs_test_init(struct kunit *test)
580+{
581+ test->priv = __override_init_fs();
582+ return 0;
583+}
584+
585+static void __init initramfs_test_exit(struct kunit *test)
586+{
587+ __revert_init_fs(test->priv);
588+}
589+
577590 static struct kunit_suite __refdata initramfs_test_suite = {
578591 .name = "initramfs",
579− .suite_init = initramfs_test_init,
592+ .suite_init = initramfs_suite_init,
593+ .init = initramfs_test_init,
594+ .exit = initramfs_test_exit,
580595 .test_cases = initramfs_test_cases,
581596 };
582597 kunit_test_init_section_suites(&initramfs_test_suite);
init/main.c+9−1
@@ -103,6 +103,7 @@ · 102 unmodified lines
103103 #include <linux/stackdepot.h>
104104 #include <linux/randomize_kstack.h>
105105 #include <linux/pidfs.h>
106+#include <linux/fs_struct.h>
106107 #include <linux/ptdump.h>
107108 #include <linux/time_namespace.h>
108109 #include <linux/unaligned.h>
@@ -670,6 +671,11 @@ static __initdata DECLARE_COMPLETION(kthreadd_done); · 561 unmodified lines
670671
671672 static noinline void __ref __noreturn rest_init(void)
672673 {
674+ struct kernel_clone_args init_args = {
675+ .flags = (CLONE_VM | CLONE_UNTRACED),
676+ .fn = kernel_init,
677+ .fn_arg = NULL,
678+ };
673679 struct task_struct *tsk;
674680 int pid;
675681
@@ -679,7 +685,7 @@ static noinline void __ref __noreturn rest_init(void) · 3 unmodified lines
679685 * the init task will end up wanting to create kthreads, which, if
680686 * we schedule it before we create kthreadd, will OOPS.
681687 */
682− pid = user_mode_thread(kernel_init, NULL, CLONE_FS);
688+ pid = kernel_clone(&init_args);
683689 /*
684690 * Pin init on the boot CPU. Task migration is not properly working
685691 * until sched_init_smp() has been run. It will set the allowed
@@ -1540,6 +1546,8 @@ static int __ref kernel_init(void *unused) · 854 unmodified lines
15401546 {
15411547 int ret;
15421548
1549+ init_userspace_fs();
1550+
15431551 /*
15441552 * Wait until kthreadd is all set-up.
15451553 */
kernel/fork.c+33−20
@@ -1618,9 +1618,27 @@ static int copy_exec_state(u64 clone_flags, struct task_struct *tsk) · 1617 unmodified lines
16181618 return task_exec_state_copy(tsk);
16191619 }
16201620
1621−static int copy_fs(u64 clone_flags, struct task_struct *tsk)
1621+static int copy_fs(u64 clone_flags, struct task_struct *tsk, bool umh)
16221622 {
1623− struct fs_struct *fs = current->fs;
1623+ struct fs_struct *fs;
1624+
1625+ /*
1626+ * Usermodehelper may copy userspace_init_fs filesystem state but
1627+ * they don't get to create mount namespaces, share the
1628+ * filesystem state, or be started from a non-initial mount
1629+ * namespace.
1630+ */
1631+ if (umh) {
1632+ if (clone_flags & (CLONE_NEWNS | CLONE_FS))
1633+ return -EINVAL;
1634+ if (current->nsproxy->mnt_ns != &init_mnt_ns)
1635+ return -EINVAL;
1636+ fs = userspace_init_fs;
1637+ } else {
1638+ fs = current->fs;
1639+ VFS_WARN_ON_ONCE(current->fs != current->real_fs);
1640+ }
1641+
16241642 if (clone_flags & CLONE_FS) {
16251643 /* tsk->fs is already what we want */
16261644 read_seqlock_excl(&fs->seq);
@@ -1633,7 +1651,7 @@ static int copy_fs(u64 clone_flags, struct task_struct *tsk) · 6 unmodified lines
16331651 read_sequnlock_excl(&fs->seq);
16341652 return 0;
16351653 }
1636− tsk->fs = copy_fs_struct(fs);
1654+ tsk->real_fs = tsk->fs = copy_fs_struct(fs);
16371655 if (!tsk->fs)
16381656 return -ENOMEM;
16391657 return 0;
@@ -2277,7 +2295,7 @@ __latent_entropy struct task_struct *copy_process( · 637 unmodified lines
22772295 retval = copy_files(clone_flags, p, args->no_files);
22782296 if (retval)
22792297 goto bad_fork_cleanup_semundo;
2280− retval = copy_fs(clone_flags, p);
2298+ retval = copy_fs(clone_flags, p, args->umh);
22812299 if (retval)
22822300 goto bad_fork_cleanup_files;
22832301 retval = copy_sighand(clone_flags, p);
@@ -2819,6 +2837,7 @@ pid_t user_mode_thread(int (*fn)(void *), void *arg, unsigned long flags) · 535 unmodified lines
28192837 .exit_signal = (flags & CSIGNAL),
28202838 .fn = fn,
28212839 .fn_arg = arg,
2840+ .umh = 1,
28222841 };
28232842
28242843 return kernel_clone(&args);
@@ -3216,7 +3235,7 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp · 391 unmodified lines
32163235 */
32173236 int ksys_unshare(unsigned long unshare_flags)
32183237 {
3219− struct fs_struct *fs, *new_fs = NULL;
3238+ struct fs_struct *new_fs = NULL;
32203239 struct files_struct *new_fd = NULL;
32213240 struct cred *new_cred = NULL;
32223241 struct nsproxy *new_nsproxy = NULL;
@@ -3247,6 +3266,10 @@ int ksys_unshare(unsigned long unshare_flags) · 24 unmodified lines
32473266 if (unshare_flags & CLONE_NEWNS)
32483267 unshare_flags |= CLONE_FS;
32493268
3269+ /* No unsharing with overriden fs state */
3270+ VFS_WARN_ON_ONCE(unshare_flags & (CLONE_NEWNS | CLONE_FS) &&
3271+ current->fs != current->real_fs);
3272+
32503273 err = check_unshare_flags(unshare_flags);
32513274 if (err)
32523275 goto bad_unshare_out;
@@ -3294,23 +3317,13 @@ int ksys_unshare(unsigned long unshare_flags) · 41 unmodified lines
32943317 new_nsproxy = NULL;
32953318 }
32963319
3297− task_lock(current);
3320+ if (new_fs)
3321+ new_fs = switch_fs_struct(new_fs);
32983322
3299− if (new_fs) {
3300− fs = current->fs;
3301− read_seqlock_excl(&fs->seq);
3302− current->fs = new_fs;
3303− if (--fs->users)
3304− new_fs = NULL;
3305− else
3306− new_fs = fs;
3307− read_sequnlock_excl(&fs->seq);
3308− }
3309−
3310− if (new_fd)
3323+ if (new_fd) {
3324+ guard(task_lock)(current);
33113325 swap(current->files, new_fd);
3312−
3313− task_unlock(current);
3326+ }
33143327
33153328 if (new_cred) {
33163329 /* Install the new user namespace */
kernel/kcmp.c+1−1
@@ -186,7 +186,7 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type, · 185 unmodified lines
186186 ret = kcmp_ptr(task1->files, task2->files, KCMP_FILES);
187187 break;
188188 case KCMP_FS:
189− ret = kcmp_ptr(task1->fs, task2->fs, KCMP_FS);
189+ ret = kcmp_ptr(task1->real_fs, task2->real_fs, KCMP_FS);
190190 break;
191191 case KCMP_SIGHAND:
192192 ret = kcmp_ptr(task1->sighand, task2->sighand, KCMP_SIGHAND);
kernel/umh.c+2−4
@@ -71,10 +71,8 @@ static int call_usermodehelper_exec_async(void *data) · 70 unmodified lines
7171 spin_unlock_irq(&current->sighand->siglock);
7272
7373 /*
74− * Initial kernel threads share ther FS with init, in order to
75− * get the init root directory. But we've now created a new
76− * thread that is going to execve a user process and has its own
77− * 'struct fs_struct'. Reset umask to the default.
74+ * Usermodehelper threads get a copy of userspace init's
75+ * fs_struct. Reset umask to the default.
7876 */
7977 current->fs->umask = 0022;
8078
net/unix/af_unix.c+6−11
@@ -1197,17 +1197,12 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len, · 1196 unmodified lines
11971197 unix_mkname_bsd(sunaddr, addr_len);
11981198
11991199 if (flags & SOCK_COREDUMP) {
1200− struct path root;
1201−
1202− task_lock(&init_task);
1203− get_fs_root(init_task.fs, &root);
1204− task_unlock(&init_task);
1205−
1206− scoped_with_kernel_creds()
1207− err = vfs_path_lookup(root.dentry, root.mnt, sunaddr->sun_path,
1208− LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS |
1209− LOOKUP_NO_MAGICLINKS, &path);
1210− path_put(&root);
1200+ scoped_with_init_fs() {
1201+ scoped_with_kernel_creds()
1202+ err = kern_path(sunaddr->sun_path,
1203+ LOOKUP_NO_SYMLINKS |
1204+ LOOKUP_NO_MAGICLINKS, &path);
1205+ }
12111206 if (err)
12121207 goto fail;
12131208 } else {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t