457c899653991 (Thomas Gleixner 2019-05-19 13:08:55 +0100 1) // SPDX-License-Identifier: GPL-2.0-only
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 2) #include <linux/export.h>
3f07c0144132e (Ingo Molnar 2017-02-08 18:51:30 +0100 3) #include <linux/sched/signal.h>
299300258d1bc (Ingo Molnar 2017-02-08 18:51:36 +0100 4) #include <linux/sched/task.h>
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 5) #include <linux/fs.h>
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 6) #include <linux/path.h>
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 7) #include <linux/slab.h>
5ad4e53bd5406 (Al Viro 2009-03-29 19:50:06 -0400 8) #include <linux/fs_struct.h>
f03c65993b98e (Al Viro 2011-01-14 22:30:21 -0500 9) #include "internal.h"
f03c65993b98e (Al Viro 2011-01-14 22:30:21 -0500 10)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 11) /*
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 12) * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 13) * It can block.
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 14) */
dcf787f39162c (Al Viro 2013-03-01 23:51:07 -0500 15) void set_fs_root(struct fs_struct *fs, const struct path *path)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 16) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 17) struct path old_root;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 18)
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 19) path_get(path);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 20) spin_lock(&fs->lock);
c28cc36469554 (Nicholas Piggin 2011-01-07 17:49:53 +1100 21) write_seqcount_begin(&fs->seq);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 22) old_root = fs->root;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 23) fs->root = *path;
c28cc36469554 (Nicholas Piggin 2011-01-07 17:49:53 +1100 24) write_seqcount_end(&fs->seq);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 25) spin_unlock(&fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 26) if (old_root.dentry)
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 27) path_put(&old_root);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 28) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 29)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 30) /*
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 31) * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 32) * It can block.
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 33) */
dcf787f39162c (Al Viro 2013-03-01 23:51:07 -0500 34) void set_fs_pwd(struct fs_struct *fs, const struct path *path)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 35) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 36) struct path old_pwd;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 37)
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 38) path_get(path);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 39) spin_lock(&fs->lock);
c28cc36469554 (Nicholas Piggin 2011-01-07 17:49:53 +1100 40) write_seqcount_begin(&fs->seq);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 41) old_pwd = fs->pwd;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 42) fs->pwd = *path;
c28cc36469554 (Nicholas Piggin 2011-01-07 17:49:53 +1100 43) write_seqcount_end(&fs->seq);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 44) spin_unlock(&fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 45)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 46) if (old_pwd.dentry)
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 47) path_put(&old_pwd);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 48) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 49)
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 50) static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 51) {
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 52) if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 53) return 0;
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 54) *p = *new;
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 55) return 1;
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 56) }
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 57)
dcf787f39162c (Al Viro 2013-03-01 23:51:07 -0500 58) void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 59) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 60) struct task_struct *g, *p;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 61) struct fs_struct *fs;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 62) int count = 0;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 63)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 64) read_lock(&tasklist_lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 65) do_each_thread(g, p) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 66) task_lock(p);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 67) fs = p->fs;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 68) if (fs) {
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 69) int hits = 0;
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 70) spin_lock(&fs->lock);
c28cc36469554 (Nicholas Piggin 2011-01-07 17:49:53 +1100 71) write_seqcount_begin(&fs->seq);
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 72) hits += replace_path(&fs->root, old_root, new_root);
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 73) hits += replace_path(&fs->pwd, old_root, new_root);
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 74) write_seqcount_end(&fs->seq);
82234e61a8fc7 (Al Viro 2012-03-15 14:48:55 -0400 75) while (hits--) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 76) count++;
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 77) path_get(new_root);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 78) }
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 79) spin_unlock(&fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 80) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 81) task_unlock(p);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 82) } while_each_thread(g, p);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 83) read_unlock(&tasklist_lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 84) while (count--)
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 85) path_put(old_root);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 86) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 87)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 88) void free_fs_struct(struct fs_struct *fs)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 89) {
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 90) path_put(&fs->root);
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 91) path_put(&fs->pwd);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 92) kmem_cache_free(fs_cachep, fs);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 93) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 94)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 95) void exit_fs(struct task_struct *tsk)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 96) {
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 97) struct fs_struct *fs = tsk->fs;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 98)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 99) if (fs) {
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 100) int kill;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 101) task_lock(tsk);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 102) spin_lock(&fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 103) tsk->fs = NULL;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 104) kill = !--fs->users;
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 105) spin_unlock(&fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 106) task_unlock(tsk);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 107) if (kill)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 108) free_fs_struct(fs);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 109) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 110) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 111)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 112) struct fs_struct *copy_fs_struct(struct fs_struct *old)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 113) {
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 114) struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 115) /* We don't need to lock fs - think why ;-) */
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 116) if (fs) {
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 117) fs->users = 1;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 118) fs->in_exec = 0;
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 119) spin_lock_init(&fs->lock);
26475371976c6 (Ahmed S. Darwish 2020-07-20 17:55:24 +0200 120) seqcount_spinlock_init(&fs->seq, &fs->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 121) fs->umask = old->umask;
b3e19d924b6ea (Nicholas Piggin 2011-01-07 17:50:11 +1100 122)
b3e19d924b6ea (Nicholas Piggin 2011-01-07 17:50:11 +1100 123) spin_lock(&old->lock);
b3e19d924b6ea (Nicholas Piggin 2011-01-07 17:50:11 +1100 124) fs->root = old->root;
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 125) path_get(&fs->root);
b3e19d924b6ea (Nicholas Piggin 2011-01-07 17:50:11 +1100 126) fs->pwd = old->pwd;
f7a99c5b7c8bd (Al Viro 2012-06-09 00:59:08 -0400 127) path_get(&fs->pwd);
b3e19d924b6ea (Nicholas Piggin 2011-01-07 17:50:11 +1100 128) spin_unlock(&old->lock);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 129) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 130) return fs;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 131) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 132)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 133) int unshare_fs_struct(void)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 134) {
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 135) struct fs_struct *fs = current->fs;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 136) struct fs_struct *new_fs = copy_fs_struct(fs);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 137) int kill;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 138)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 139) if (!new_fs)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 140) return -ENOMEM;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 141)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 142) task_lock(current);
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 143) spin_lock(&fs->lock);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 144) kill = !--fs->users;
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 145) current->fs = new_fs;
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 146) spin_unlock(&fs->lock);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 147) task_unlock(current);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 148)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 149) if (kill)
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 150) free_fs_struct(fs);
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 151)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 152) return 0;
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 153) }
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 154) EXPORT_SYMBOL_GPL(unshare_fs_struct);
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 155)
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 156) int current_umask(void)
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 157) {
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 158) return current->fs->umask;
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 159) }
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 160) EXPORT_SYMBOL(current_umask);
ce3b0f8d5c220 (Al Viro 2009-03-29 19:08:22 -0400 161)
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 162) /* to be mentioned only in INIT_TASK */
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 163) struct fs_struct init_fs = {
498052bba55ec (Al Viro 2009-03-30 07:20:30 -0400 164) .users = 1,
2a4419b5b2a77 (Nicholas Piggin 2010-08-18 04:37:33 +1000 165) .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock),
26475371976c6 (Ahmed S. Darwish 2020-07-20 17:55:24 +0200 166) .seq = SEQCNT_SPINLOCK_ZERO(init_fs.seq, &init_fs.lock),
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 167) .umask = 0022,
3e93cd671813e (Al Viro 2009-03-29 19:00:13 -0400 168) };