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
413{413{
414 int err;414 int err;
415 415
416 err = ksys_unshare(CLONE_NEWNS);416 err = ksys_unshare(UNSHARE_EMPTY_MNTNS);
417 if (err)417 if (err)
418 goto out;418 goto out;
419 err = init_mount("devtmpfs", "/", "devtmpfs", DEVTMPFS_MFLAGS, NULL);419 err = init_mount("devtmpfs", "/", "devtmpfs", DEVTMPFS_MFLAGS, NULL);
drivers/block/rnbd/rnbd-srv.c+3−1
@@ -11,6 +11,7 @@ · 10 unmodified lines
11 11
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/blkdev.h>13#include <linux/blkdev.h>
14#include <linux/fs_struct.h>
14 15
15#include "rnbd-srv.h"16#include "rnbd-srv.h"
16#include "rnbd-srv-trace.h"17#include "rnbd-srv-trace.h"
@@ -734,7 +735,8 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, · 717 unmodified lines
734 goto reject;735 goto reject;
735 }736 }
736 737
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);
738 if (IS_ERR(bdev_file)) {740 if (IS_ERR(bdev_file)) {
739 ret = PTR_ERR(bdev_file);741 ret = PTR_ERR(bdev_file);
740 pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %pe\n",742 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
5#include <linux/miscdevice.h>5#include <linux/miscdevice.h>
6#include <linux/fs.h>6#include <linux/fs.h>
7#include <linux/file.h>7#include <linux/file.h>
8#include <linux/fs_struct.h>
8#include <linux/init_syscalls.h>9#include <linux/init_syscalls.h>
9 10
10/* static minor (LCD_MINOR) */11/* static minor (LCD_MINOR) */
@@ -160,18 +161,22 @@ static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice * · 149 unmodified lines
160 char *devname;161 char *devname;
161 162
162 devname = kasprintf(GFP_KERNEL, "/dev/%s", misc->name);163 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");
167 164
168 filp = filp_open(devname, O_RDONLY, 0);165 /* Tests run in a nullfs kthread; borrow the init fs to resolve /dev. */
169 if (IS_ERR(filp))166 scoped_with_init_fs() {
170 KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));167 ret = init_mknod(devname, S_IFCHR | 0600,
171 else168 new_encode_dev(MKDEV(MISC_MAJOR, misc->minor)));
172 fput(filp);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);
173 177
174 init_unlink(devname);178 init_unlink(devname);
179 }
175 kfree(devname);180 kfree(devname);
176}181}
177 182
drivers/crypto/ccp/sev-dev.c+4−8
@@ -260,20 +260,16 @@ static int sev_cmd_buffer_len(int cmd) · 259 unmodified lines
260 260
261static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)261static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
262{262{
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
269 CLASS(prepare_creds, cred)();263 CLASS(prepare_creds, cred)();
270 if (!cred)264 if (!cred)
271 return ERR_PTR(-ENOMEM);265 return ERR_PTR(-ENOMEM);
272 266
273 cred->fsuid = GLOBAL_ROOT_UID;267 cred->fsuid = GLOBAL_ROOT_UID;
274 268
275 scoped_with_creds(cred)269 scoped_with_init_fs() {
276 return file_open_root(&root, filename, flags, mode);270 scoped_with_creds(cred)
271 return filp_open(filename, flags, mode);
272 }
277}273}
278 274
279static int sev_read_init_ex_file(void)275static int sev_read_init_ex_file(void)
drivers/target/target_core_alua.c+10−1
@@ -18,6 +18,8 @@ · 17 unmodified lines
18#include <linux/fcntl.h>18#include <linux/fcntl.h>
19#include <linux/file.h>19#include <linux/file.h>
20#include <linux/fs.h>20#include <linux/fs.h>
21#include <linux/fs_struct.h>
22#include <linux/kthread.h>
21#include <scsi/scsi_proto.h>23#include <scsi/scsi_proto.h>
22#include <linux/unaligned.h>24#include <linux/unaligned.h>
23 25
@@ -856,10 +858,17 @@ static int core_alua_write_tpg_metadata( · 832 unmodified lines
856 unsigned char *md_buf,858 unsigned char *md_buf,
857 u32 md_buf_len)859 u32 md_buf_len)
858{860{
859 struct file *file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600);861 struct file *file;
860 loff_t pos = 0;862 loff_t pos = 0;
861 int ret;863 int ret;
862 864
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
863 if (IS_ERR(file)) {872 if (IS_ERR(file)) {
864 pr_err("filp_open(%s) for ALUA metadata failed\n", path);873 pr_err("filp_open(%s) for ALUA metadata failed\n", path);
865 return -ENODEV;874 return -ENODEV;
drivers/target/target_core_pr.c+3−1
@@ -18,6 +18,7 @@ · 17 unmodified lines
18#include <linux/file.h>18#include <linux/file.h>
19#include <linux/fcntl.h>19#include <linux/fcntl.h>
20#include <linux/fs.h>20#include <linux/fs.h>
21#include <linux/fs_struct.h>
21#include <scsi/scsi_proto.h>22#include <scsi/scsi_proto.h>
22#include <linux/unaligned.h>23#include <linux/unaligned.h>
23 24
@@ -1969,7 +1970,8 @@ static int __core_scsi3_write_aptpl_to_file( · 1945 unmodified lines
1969 if (!path)1970 if (!path)
1970 return -ENOMEM;1971 return -ENOMEM;
1971 1972
1972 file = filp_open(path, flags, 0600);1973 scoped_with_init_fs()
1974 file = filp_open(path, flags, 0600);
1973 if (IS_ERR(file)) {1975 if (IS_ERR(file)) {
1974 pr_err("filp_open(%s) for APTPL metadata"1976 pr_err("filp_open(%s) for APTPL metadata"
1975 " failed\n", path);1977 " failed\n", path);
fs/btrfs/volumes.c+10−1
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <linux/uuid.h>12#include <linux/uuid.h>
13#include <linux/list_sort.h>13#include <linux/list_sort.h>
14#include <linux/namei.h>14#include <linux/namei.h>
15#include <linux/fs_struct.h>
15#include "misc.h"16#include "misc.h"
16#include "disk-io.h"17#include "disk-io.h"
17#include "extent-tree.h"18#include "extent-tree.h"
@@ -2125,8 +2126,16 @@ static int btrfs_add_dev_item(struct btrfs_trans_handle *trans, · 2107 unmodified lines
2125static void update_dev_time(const char *device_path)2126static void update_dev_time(const char *device_path)
2126{2127{
2127 struct path path;2128 struct path path;
2129 int err;
2128 2130
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) {
2130 vfs_utimes(&path, NULL);2139 vfs_utimes(&path, NULL);
2131 path_put(&path);2140 path_put(&path);
2132 }2141 }
fs/coredump.c+3−8
@@ -921,15 +921,10 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm, · 920 unmodified lines
921 * with a fully qualified path" rule is to control where921 * with a fully qualified path" rule is to control where
922 * coredumps may be placed using root privileges,922 * coredumps may be placed using root privileges,
923 * current->fs->root must not be used. Instead, use the923 * current->fs->root must not be used. Instead, use the
924 * root directory of init_task.924 * root directory of PID 1.
925 */925 */
926 struct path root;926 scoped_with_init_fs()
927 927 file = filp_open(cn->corename, open_flags, 0600);
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);
933 } else {928 } else {
934 file = filp_open(cn->corename, open_flags, 0600);929 file = filp_open(cn->corename, open_flags, 0600);
935 }930 }
fs/fs_struct.c+100−3
@@ -8,6 +8,7 @@ · 7 unmodified lines
8#include <linux/fs_struct.h>8#include <linux/fs_struct.h>
9#include <linux/init_task.h>9#include <linux/init_task.h>
10#include "internal.h"10#include "internal.h"
11#include "mount.h"
11 12
12/*13/*
13 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.14 * 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
60 61
61 read_lock(&tasklist_lock);62 read_lock(&tasklist_lock);
62 for_each_process_thread(g, p) {63 for_each_process_thread(g, p) {
64 if (p->flags & (PF_KTHREAD | PF_EXITING | PF_DUMPCORE))
65 continue;
66
63 task_lock(p);67 task_lock(p);
64 fs = p->fs;68 fs = p->real_fs;
65 if (fs) {69 if (fs) {
66 int hits = 0;70 int hits = 0;
67 write_seqlock(&fs->seq);71 write_seqlock(&fs->seq);
@@ -89,12 +93,13 @@ void free_fs_struct(struct fs_struct *fs) · 21 unmodified lines
89 93
90void exit_fs(struct task_struct *tsk)94void exit_fs(struct task_struct *tsk)
91{95{
92 struct fs_struct *fs = tsk->fs;96 struct fs_struct *fs = tsk->real_fs;
93 97
94 if (fs) {98 if (fs) {
95 int kill;99 int kill;
96 task_lock(tsk);100 task_lock(tsk);
97 read_seqlock_excl(&fs->seq);101 read_seqlock_excl(&fs->seq);
102 tsk->real_fs = NULL;
98 tsk->fs = NULL;103 tsk->fs = NULL;
99 kill = !--fs->users;104 kill = !--fs->users;
100 read_sequnlock_excl(&fs->seq);105 read_sequnlock_excl(&fs->seq);
@@ -126,7 +131,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) · 25 unmodified lines
126 131
127int unshare_fs_struct(void)132int unshare_fs_struct(void)
128{133{
129 struct fs_struct *fs = current->fs;134 struct fs_struct *fs = current->real_fs;
130 struct fs_struct *new_fs = copy_fs_struct(fs);135 struct fs_struct *new_fs = copy_fs_struct(fs);
131 int kill;136 int kill;
132 137
@@ -135,8 +140,10 @@ int unshare_fs_struct(void) · 2 unmodified lines
135 140
136 task_lock(current);141 task_lock(current);
137 read_seqlock_excl(&fs->seq);142 read_seqlock_excl(&fs->seq);
143 VFS_WARN_ON_ONCE(fs != current->fs);
138 kill = !--fs->users;144 kill = !--fs->users;
139 current->fs = new_fs;145 current->fs = new_fs;
146 current->real_fs = new_fs;
140 read_sequnlock_excl(&fs->seq);147 read_sequnlock_excl(&fs->seq);
141 task_unlock(current);148 task_unlock(current);
142 149
@@ -147,9 +154,99 @@ int unshare_fs_struct(void) · 4 unmodified lines
147}154}
148EXPORT_SYMBOL_GPL(unshare_fs_struct);155EXPORT_SYMBOL_GPL(unshare_fs_struct);
149 156
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 */
186static 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
200struct 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
150/* to be mentioned only in INIT_TASK */221/* to be mentioned only in INIT_TASK */
151struct fs_struct init_fs = {222struct fs_struct init_fs = {
152 .users = 1,223 .users = 1,
153 .seq = __SEQLOCK_UNLOCKED(init_fs.seq),224 .seq = __SEQLOCK_UNLOCKED(init_fs.seq),
154 .umask = 0022,225 .umask = 0022,
155};226};
227
228struct fs_struct *userspace_init_fs __ro_after_init;
229EXPORT_SYMBOL_GPL(userspace_init_fs);
230
231void __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
150 enum kernel_read_file_id id)150 enum kernel_read_file_id id)
151{151{
152 struct file *file;152 struct file *file;
153 struct path root;
154 ssize_t ret;153 ssize_t ret;
155 154
156 if (!path || !*path)155 if (!path || !*path)
157 return -EINVAL;156 return -EINVAL;
158 157
159 task_lock(&init_task);158 scoped_with_init_fs()
160 get_fs_root(init_task.fs, &root);159 file = filp_open(path, O_RDONLY, 0);
161 task_unlock(&init_task);
162
163 file = file_open_root(&root, path, O_RDONLY, 0);
164 path_put(&root);
165 if (IS_ERR(file))160 if (IS_ERR(file))
166 return PTR_ERR(file);161 return PTR_ERR(file);
167 162
fs/namespace.c+10−6
@@ -6184,12 +6184,14 @@ static void __init init_mount_tree(void) · 6183 unmodified lines
6184 struct path root;6184 struct path root;
6185 6185
6186 /*6186 /*
6187 * We create two mounts:6187 * We create three mounts:
6188 *6188 *
6189 * (1) nullfs with mount id 16189 * (1) nullfs with mount id 1
6190 * (2) mutable rootfs with mount id 26190 * (2) mutable rootfs with mount id 2
6191 * (3) private nullfs for kthreads (SB_KERNMOUNT)
6191 *6192 *
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.
6193 */6195 */
6194 nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);6196 nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);
6195 if (IS_ERR(nullfs_mnt))6197 if (IS_ERR(nullfs_mnt))
@@ -6229,12 +6231,14 @@ static void __init init_mount_tree(void) · 33 unmodified lines
6229 init_mnt_ns.nr_mounts++;6231 init_mnt_ns.nr_mounts++;
6230 }6232 }
6231 6233
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
6232 init_task.nsproxy->mnt_ns = &init_mnt_ns;6240 init_task.nsproxy->mnt_ns = &init_mnt_ns;
6233 get_mnt_ns(&init_mnt_ns);6241 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;
6238 set_fs_pwd(current->fs, &root);6242 set_fs_pwd(current->fs, &root);
6239 set_fs_root(current->fs, &root);6243 set_fs_root(current->fs, &root);
6240 6244
fs/nfs/blocklayout/dev.c+11−4
@@ -4,6 +4,7 @@ · 3 unmodified lines
4 */4 */
5#include <linux/sunrpc/svc.h>5#include <linux/sunrpc/svc.h>
6#include <linux/blkdev.h>6#include <linux/blkdev.h>
7#include <linux/fs_struct.h>
7#include <linux/nfs4.h>8#include <linux/nfs4.h>
8#include <linux/nfs_fs.h>9#include <linux/nfs_fs.h>
9#include <linux/nfs_xdr.h>10#include <linux/nfs_xdr.h>
@@ -363,15 +364,22 @@ static struct file * · 353 unmodified lines
363bl_open_path(struct pnfs_block_volume *v, const char *prefix)364bl_open_path(struct pnfs_block_volume *v, const char *prefix)
364{365{
365 struct file *bdev_file;366 struct file *bdev_file;
366 const char *devname;367 const char *devname __free(kfree) = NULL;
367 368
368 devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",369 devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",
369 prefix, v->scsi.designator_len, v->scsi.designator);370 prefix, v->scsi.designator_len, v->scsi.designator);
370 if (!devname)371 if (!devname)
371 return ERR_PTR(-ENOMEM);372 return ERR_PTR(-ENOMEM);
372 373
373 bdev_file = bdev_file_open_by_path(devname,374 if (tsk_is_kthread(current)) {
374 BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);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 }
375 if (IS_ERR(bdev_file)) {383 if (IS_ERR(bdev_file)) {
376 dprintk("failed to open device %s (%ld)\n",384 dprintk("failed to open device %s (%ld)\n",
377 devname, PTR_ERR(bdev_file));385 devname, PTR_ERR(bdev_file));
@@ -380,7 +388,6 @@ bl_open_path(struct pnfs_block_volume *v, const char *prefix) · 2 unmodified lines
380 file_bdev(bdev_file)->bd_disk->disk_name);388 file_bdev(bdev_file)->bd_disk->disk_name);
381 }389 }
382 390
383 kfree(devname);
384 return bdev_file;391 return bdev_file;
385}392}
386 393
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
40 return 0;40 return 0;
41}41}
42 42
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 */
48static int nullfs_fs_get_tree(struct fs_context *fc)43static int nullfs_fs_get_tree(struct fs_context *fc)
49{44{
50 return get_tree_single(fc, nullfs_fs_fill_super);45 return get_tree_nodev(fc, nullfs_fs_fill_super);
51}46}
52 47
53static const struct fs_context_operations nullfs_fs_context_ops = {48static 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
57static int nullfs_init_fs_context(struct fs_context *fc)52static int nullfs_init_fs_context(struct fs_context *fc)
58{53{
59 fc->ops = &nullfs_fs_context_ops;54 fc->ops = &nullfs_fs_context_ops;
60 fc->global = true;55 fc->sb_flags |= SB_NOUSER;
61 fc->sb_flags = SB_NOUSER;56 fc->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
62 fc->s_iflags = SB_I_NOEXEC | SB_I_NODEV;
63 return 0;57 return 0;
64}58}
65 59
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
168 cred = get_task_cred(p);168 cred = get_task_cred(p);
169 169
170 task_lock(p);170 task_lock(p);
171 if (p->fs)171 if (p->real_fs)
172 umask = p->fs->umask;172 umask = p->real_fs->umask;
173 if (p->files)173 if (p->files)
174 max_fds = files_fdtable(p->files)->max_fds;174 max_fds = files_fdtable(p->files)->max_fds;
175 task_unlock(p);175 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
211 int result = -ENOENT;211 int result = -ENOENT;
212 212
213 task_lock(task);213 task_lock(task);
214 if (task->fs) {214 if (task->real_fs) {
215 get_fs_root(task->fs, root);215 get_fs_root(task->real_fs, root);
216 result = 0;216 result = 0;
217 }217 }
218 task_unlock(task);218 task_unlock(task);
@@ -225,8 +225,8 @@ static int proc_cwd_link(struct dentry *dentry, struct path *path, · 6 unmodified lines
225 int result = -ENOENT;225 int result = -ENOENT;
226 226
227 task_lock(task);227 task_lock(task);
228 if (task->fs) {228 if (task->real_fs) {
229 get_fs_pwd(task->fs, path);229 get_fs_pwd(task->real_fs, path);
230 result = 0;230 result = 0;
231 }231 }
232 task_unlock(task);232 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
254 }254 }
255 ns = nsp->mnt_ns;255 ns = nsp->mnt_ns;
256 get_mnt_ns(ns);256 get_mnt_ns(ns);
257 if (!task->fs) {257 if (!task->real_fs) {
258 task_unlock(task);258 task_unlock(task);
259 put_task_struct(task);259 put_task_struct(task);
260 ret = -ENOENT;260 ret = -ENOENT;
261 goto err_put_ns;261 goto err_put_ns;
262 }262 }
263 get_fs_root(task->fs, &root);263 get_fs_root(task->real_fs, &root);
264 task_unlock(task);264 task_unlock(task);
265 put_task_struct(task);265 put_task_struct(task);
266 266
fs/smb/server/mgmt/share_config.c+3−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/rwsem.h>9#include <linux/rwsem.h>
10#include <linux/parser.h>10#include <linux/parser.h>
11#include <linux/namei.h>11#include <linux/namei.h>
12#include <linux/fs_struct.h>
12#include <linux/sched.h>13#include <linux/sched.h>
13#include <linux/mm.h>14#include <linux/mm.h>
14 15
@@ -193,7 +194,8 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work, · 178 unmodified lines
193 goto out;194 goto out;
194 }195 }
195 196
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);
197 ksmbd_revert_fsids(work);199 ksmbd_revert_fsids(work);
198 if (ret) {200 if (ret) {
199 ksmbd_debug(SMB, "failed to access '%s'\n",201 ksmbd_debug(SMB, "failed to access '%s'\n",
fs/smb/server/smb2pdu.c+3−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <net/addrconf.h>9#include <net/addrconf.h>
10#include <linux/syscalls.h>10#include <linux/syscalls.h>
11#include <linux/namei.h>11#include <linux/namei.h>
12#include <linux/fs_struct.h>
12#include <linux/statfs.h>13#include <linux/statfs.h>
13#include <linux/ethtool.h>14#include <linux/ethtool.h>
14#include <linux/falloc.h>15#include <linux/falloc.h>
@@ -5949,7 +5950,8 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 5934 unmodified lines
5949 if (!share->path)5950 if (!share->path)
5950 return -EIO;5951 return -EIO;
5951 5952
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);
5953 if (rc) {5955 if (rc) {
5954 pr_err("cannot create vfs path\n");5956 pr_err("cannot create vfs path\n");
5955 return -EIO;5957 return -EIO;
fs/smb/server/vfs.c+6−3
@@ -7,6 +7,7 @@ · 6 unmodified lines
7#include <crypto/sha2.h>7#include <crypto/sha2.h>
8#include <linux/kernel.h>8#include <linux/kernel.h>
9#include <linux/fs.h>9#include <linux/fs.h>
10#include <linux/fs_struct.h>
10#include <linux/filelock.h>11#include <linux/filelock.h>
11#include <linux/uaccess.h>12#include <linux/uaccess.h>
12#include <linux/backing-dev.h>13#include <linux/backing-dev.h>
@@ -67,8 +68,9 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf, · 54 unmodified lines
67 }68 }
68 69
69 CLASS(filename_kernel, filename)(pathname);70 CLASS(filename_kernel, filename)(pathname);
70 err = vfs_path_parent_lookup(filename, flags, path, &last,71 scoped_with_init_fs()
71 root_share_path);72 err = vfs_path_parent_lookup(filename, flags, path, &last,
73 root_share_path);
72 if (err)74 if (err)
73 return err;75 return err;
74 76
@@ -623,7 +625,8 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname, · 548 unmodified lines
623 if (ksmbd_override_fsids(work))625 if (ksmbd_override_fsids(work))
624 return -ENOMEM;626 return -ENOMEM;
625 627
626 err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);628 scoped_with_init_fs()
629 err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);
627 if (err) {630 if (err) {
628 pr_err("cannot get linux path for %s, err = %d\n",631 pr_err("cannot get linux path for %s, err = %d\n",
629 oldname, err);632 oldname, err);
include/linux/fs_struct.h+34−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/path.h>6#include <linux/path.h>
7#include <linux/spinlock.h>7#include <linux/spinlock.h>
8#include <linux/seqlock.h>8#include <linux/seqlock.h>
9#include <linux/vfsdebug.h>
9 10
10struct fs_struct {11struct fs_struct {
11 int users;12 int users;
@@ -16,6 +17,7 @@ struct fs_struct { · 4 unmodified lines
16} __randomize_layout;17} __randomize_layout;
17 18
18extern struct kmem_cache *fs_cachep;19extern struct kmem_cache *fs_cachep;
20extern struct fs_struct *userspace_init_fs;
19 21
20extern void exit_fs(struct task_struct *);22extern void exit_fs(struct task_struct *);
21extern void set_fs_root(struct fs_struct *, const struct path *);23extern 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
40 read_sequnlock_excl(&fs->seq);42 read_sequnlock_excl(&fs->seq);
41}43}
42 44
45struct fs_struct *switch_fs_struct(struct fs_struct *new_fs);
46
43extern bool current_chrooted(void);47extern bool current_chrooted(void);
44 48
45static inline int current_umask(void)49static inline int current_umask(void)
@@ -47,4 +51,34 @@ static inline int current_umask(void) · 1 unmodified line
47 return current->fs->umask;51 return current->fs->umask;
48}52}
49 53
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 */
59static 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
68static 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
74DEFINE_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
82void __init init_userspace_fs(void);
83
50#endif /* _LINUX_FS_STRUCT_H */84#endif /* _LINUX_FS_STRUCT_H */
include/linux/init_task.h+1−0
@@ -24,6 +24,7 @@ · 23 unmodified lines
24 24
25extern struct files_struct init_files;25extern struct files_struct init_files;
26extern struct fs_struct init_fs;26extern struct fs_struct init_fs;
27extern struct fs_struct *userspace_init_fs;
27extern struct nsproxy init_nsproxy;28extern struct nsproxy init_nsproxy;
28 29
29#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE30#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
include/linux/sched.h+1−0
@@ -1191,6 +1191,7 @@ struct task_struct { · 1190 unmodified lines
1191 unsigned long last_switch_time;1191 unsigned long last_switch_time;
1192#endif1192#endif
1193 /* Filesystem information: */1193 /* Filesystem information: */
1194 struct fs_struct *real_fs;
1194 struct fs_struct *fs;1195 struct fs_struct *fs;
1195 1196
1196 /* Open file information: */1197 /* Open file information: */
include/linux/sched/task.h+1−0
@@ -31,6 +31,7 @@ struct kernel_clone_args { · 30 unmodified lines
31 u32 io_thread:1;31 u32 io_thread:1;
32 u32 user_worker:1;32 u32 user_worker:1;
33 u32 no_files:1;33 u32 no_files:1;
34 u32 umh:1;
34 unsigned long stack;35 unsigned long stack;
35 unsigned long stack_size;36 unsigned long stack_size;
36 unsigned long tls;37 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
162 RCU_POINTER_INITIALIZER(cred, &init_cred),162 RCU_POINTER_INITIALIZER(cred, &init_cred),
163 .comm = INIT_TASK_COMM,163 .comm = INIT_TASK_COMM,
164 .thread = INIT_THREAD,164 .thread = INIT_THREAD,
165 .real_fs = &init_fs,
165 .fs = &init_fs,166 .fs = &init_fs,
166 .files = &init_files,167 .files = &init_files,
167#ifdef CONFIG_IO_URING168#ifdef CONFIG_IO_URING
init/initramfs.c+10−4
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/fcntl.h>6#include <linux/fcntl.h>
7#include <linux/file.h>7#include <linux/file.h>
8#include <linux/fs.h>8#include <linux/fs.h>
9#include <linux/fs_struct.h>
9#include <linux/hex.h>10#include <linux/hex.h>
10#include <linux/init.h>11#include <linux/init.h>
11#include <linux/init_syscalls.h>12#include <linux/init_syscalls.h>
@@ -716,7 +717,7 @@ static void __init populate_initrd_image(char *err) · 704 unmodified lines
716}717}
717#endif /* CONFIG_BLK_DEV_RAM */718#endif /* CONFIG_BLK_DEV_RAM */
718 719
719static void __init do_populate_rootfs(void *unused, async_cookie_t cookie)720static void __init unpack_initramfs(async_cookie_t cookie)
720{721{
721 /* Load the built in initramfs */722 /* Load the built in initramfs */
722 char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);723 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
724 panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */725 panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */
725 726
726 if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))727 if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
727 goto done;728 return;
728 729
729 if (IS_ENABLED(CONFIG_BLK_DEV_RAM))730 if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
730 printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");731 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
739 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);740 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
740#endif741#endif
741 }742 }
743}
742 744
743done:745static void __init do_populate_rootfs(void *unused, async_cookie_t cookie)
744 security_initramfs_populated();746{
747 scoped_with_init_fs() {
748 unpack_initramfs(cookie);
749 security_initramfs_populated();
750 }
745 751
746 /*752 /*
747 * If the initrd region is overlapped with crashkernel reserved region,753 * If the initrd region is overlapped with crashkernel reserved region,
init/initramfs_test.c+17−2
@@ -3,6 +3,7 @@ · 2 unmodified lines
3#include <linux/fcntl.h>3#include <linux/fcntl.h>
4#include <linux/file.h>4#include <linux/file.h>
5#include <linux/fs.h>5#include <linux/fs.h>
6#include <linux/fs_struct.h>
6#include <linux/init.h>7#include <linux/init.h>
7#include <linux/init_syscalls.h>8#include <linux/init_syscalls.h>
8#include <linux/initrd.h>9#include <linux/initrd.h>
@@ -562,7 +563,7 @@ static struct kunit_case __refdata initramfs_test_cases[] = { · 553 unmodified lines
562 {},563 {},
563};564};
564 565
565static int __init initramfs_test_init(struct kunit_suite *suite)566static int __init initramfs_suite_init(struct kunit_suite *suite)
566{567{
567 /*568 /*
568 * unpack_to_rootfs() uses module-static state (victim, byte_count,569 * 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
574 return 0;575 return 0;
575}576}
576 577
578/* Tests run in a nullfs kthread; always use the init fs for path resolution. */
579static int __init initramfs_test_init(struct kunit *test)
580{
581 test->priv = __override_init_fs();
582 return 0;
583}
584
585static void __init initramfs_test_exit(struct kunit *test)
586{
587 __revert_init_fs(test->priv);
588}
589
577static struct kunit_suite __refdata initramfs_test_suite = {590static struct kunit_suite __refdata initramfs_test_suite = {
578 .name = "initramfs",591 .name = "initramfs",
579 .suite_init = initramfs_test_init,592 .suite_init = initramfs_suite_init,
593 .init = initramfs_test_init,
594 .exit = initramfs_test_exit,
580 .test_cases = initramfs_test_cases,595 .test_cases = initramfs_test_cases,
581};596};
582kunit_test_init_section_suites(&initramfs_test_suite);597kunit_test_init_section_suites(&initramfs_test_suite);
init/main.c+9−1
@@ -103,6 +103,7 @@ · 102 unmodified lines
103#include <linux/stackdepot.h>103#include <linux/stackdepot.h>
104#include <linux/randomize_kstack.h>104#include <linux/randomize_kstack.h>
105#include <linux/pidfs.h>105#include <linux/pidfs.h>
106#include <linux/fs_struct.h>
106#include <linux/ptdump.h>107#include <linux/ptdump.h>
107#include <linux/time_namespace.h>108#include <linux/time_namespace.h>
108#include <linux/unaligned.h>109#include <linux/unaligned.h>
@@ -670,6 +671,11 @@ static __initdata DECLARE_COMPLETION(kthreadd_done); · 561 unmodified lines
670 671
671static noinline void __ref __noreturn rest_init(void)672static noinline void __ref __noreturn rest_init(void)
672{673{
674 struct kernel_clone_args init_args = {
675 .flags = (CLONE_VM | CLONE_UNTRACED),
676 .fn = kernel_init,
677 .fn_arg = NULL,
678 };
673 struct task_struct *tsk;679 struct task_struct *tsk;
674 int pid;680 int pid;
675 681
@@ -679,7 +685,7 @@ static noinline void __ref __noreturn rest_init(void) · 3 unmodified lines
679 * the init task will end up wanting to create kthreads, which, if685 * the init task will end up wanting to create kthreads, which, if
680 * we schedule it before we create kthreadd, will OOPS.686 * we schedule it before we create kthreadd, will OOPS.
681 */687 */
682 pid = user_mode_thread(kernel_init, NULL, CLONE_FS);688 pid = kernel_clone(&init_args);
683 /*689 /*
684 * Pin init on the boot CPU. Task migration is not properly working690 * Pin init on the boot CPU. Task migration is not properly working
685 * until sched_init_smp() has been run. It will set the allowed691 * 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
1540{1546{
1541 int ret;1547 int ret;
1542 1548
1549 init_userspace_fs();
1550
1543 /*1551 /*
1544 * Wait until kthreadd is all set-up.1552 * Wait until kthreadd is all set-up.
1545 */1553 */
kernel/fork.c+33−20
@@ -1618,9 +1618,27 @@ static int copy_exec_state(u64 clone_flags, struct task_struct *tsk) · 1617 unmodified lines
1618 return task_exec_state_copy(tsk);1618 return task_exec_state_copy(tsk);
1619}1619}
1620 1620
1621static int copy_fs(u64 clone_flags, struct task_struct *tsk)1621static int copy_fs(u64 clone_flags, struct task_struct *tsk, bool umh)
1622{1622{
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
1624 if (clone_flags & CLONE_FS) {1642 if (clone_flags & CLONE_FS) {
1625 /* tsk->fs is already what we want */1643 /* tsk->fs is already what we want */
1626 read_seqlock_excl(&fs->seq);1644 read_seqlock_excl(&fs->seq);
@@ -1633,7 +1651,7 @@ static int copy_fs(u64 clone_flags, struct task_struct *tsk) · 6 unmodified lines
1633 read_sequnlock_excl(&fs->seq);1651 read_sequnlock_excl(&fs->seq);
1634 return 0;1652 return 0;
1635 }1653 }
1636 tsk->fs = copy_fs_struct(fs);1654 tsk->real_fs = tsk->fs = copy_fs_struct(fs);
1637 if (!tsk->fs)1655 if (!tsk->fs)
1638 return -ENOMEM;1656 return -ENOMEM;
1639 return 0;1657 return 0;
@@ -2277,7 +2295,7 @@ __latent_entropy struct task_struct *copy_process( · 637 unmodified lines
2277 retval = copy_files(clone_flags, p, args->no_files);2295 retval = copy_files(clone_flags, p, args->no_files);
2278 if (retval)2296 if (retval)
2279 goto bad_fork_cleanup_semundo;2297 goto bad_fork_cleanup_semundo;
2280 retval = copy_fs(clone_flags, p);2298 retval = copy_fs(clone_flags, p, args->umh);
2281 if (retval)2299 if (retval)
2282 goto bad_fork_cleanup_files;2300 goto bad_fork_cleanup_files;
2283 retval = copy_sighand(clone_flags, p);2301 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
2819 .exit_signal = (flags & CSIGNAL),2837 .exit_signal = (flags & CSIGNAL),
2820 .fn = fn,2838 .fn = fn,
2821 .fn_arg = arg,2839 .fn_arg = arg,
2840 .umh = 1,
2822 };2841 };
2823 2842
2824 return kernel_clone(&args);2843 return kernel_clone(&args);
@@ -3216,7 +3235,7 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp · 391 unmodified lines
3216 */3235 */
3217int ksys_unshare(unsigned long unshare_flags)3236int ksys_unshare(unsigned long unshare_flags)
3218{3237{
3219 struct fs_struct *fs, *new_fs = NULL;3238 struct fs_struct *new_fs = NULL;
3220 struct files_struct *new_fd = NULL;3239 struct files_struct *new_fd = NULL;
3221 struct cred *new_cred = NULL;3240 struct cred *new_cred = NULL;
3222 struct nsproxy *new_nsproxy = NULL;3241 struct nsproxy *new_nsproxy = NULL;
@@ -3247,6 +3266,10 @@ int ksys_unshare(unsigned long unshare_flags) · 24 unmodified lines
3247 if (unshare_flags & CLONE_NEWNS)3266 if (unshare_flags & CLONE_NEWNS)
3248 unshare_flags |= CLONE_FS;3267 unshare_flags |= CLONE_FS;
3249 3268
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
3250 err = check_unshare_flags(unshare_flags);3273 err = check_unshare_flags(unshare_flags);
3251 if (err)3274 if (err)
3252 goto bad_unshare_out;3275 goto bad_unshare_out;
@@ -3294,23 +3317,13 @@ int ksys_unshare(unsigned long unshare_flags) · 41 unmodified lines
3294 new_nsproxy = NULL;3317 new_nsproxy = NULL;
3295 }3318 }
3296 3319
3297 task_lock(current);3320 if (new_fs)
3321 new_fs = switch_fs_struct(new_fs);
3298 3322
3299 if (new_fs) {3323 if (new_fd) {
3300 fs = current->fs;3324 guard(task_lock)(current);
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)
3311 swap(current->files, new_fd);3325 swap(current->files, new_fd);
3312 3326 }
3313 task_unlock(current);
3314 3327
3315 if (new_cred) {3328 if (new_cred) {
3316 /* Install the new user namespace */3329 /* 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
186 ret = kcmp_ptr(task1->files, task2->files, KCMP_FILES);186 ret = kcmp_ptr(task1->files, task2->files, KCMP_FILES);
187 break;187 break;
188 case KCMP_FS:188 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);
190 break;190 break;
191 case KCMP_SIGHAND:191 case KCMP_SIGHAND:
192 ret = kcmp_ptr(task1->sighand, task2->sighand, KCMP_SIGHAND);192 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
71 spin_unlock_irq(&current->sighand->siglock);71 spin_unlock_irq(&current->sighand->siglock);
72 72
73 /*73 /*
74 * Initial kernel threads share ther FS with init, in order to74 * Usermodehelper threads get a copy of userspace init's
75 * get the init root directory. But we've now created a new75 * fs_struct. Reset umask to the default.
76 * thread that is going to execve a user process and has its own
77 * 'struct fs_struct'. Reset umask to the default.
78 */76 */
79 current->fs->umask = 0022;77 current->fs->umask = 0022;
80 78
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
1197 unix_mkname_bsd(sunaddr, addr_len);1197 unix_mkname_bsd(sunaddr, addr_len);
1198 1198
1199 if (flags & SOCK_COREDUMP) {1199 if (flags & SOCK_COREDUMP) {
1200 struct path root;1200 scoped_with_init_fs() {
1201 1201 scoped_with_kernel_creds()
1202 task_lock(&init_task);1202 err = kern_path(sunaddr->sun_path,
1203 get_fs_root(init_task.fs, &root);1203 LOOKUP_NO_SYMLINKS |
1204 task_unlock(&init_task);1204 LOOKUP_NO_MAGICLINKS, &path);
1205 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);
1211 if (err)1206 if (err)
1212 goto fail;1207 goto fail;
1213 } else {1208 } 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