1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2630d9c47SPaul Gortmaker #include <linux/export.h>
33f07c014SIngo Molnar #include <linux/sched/signal.h>
429930025SIngo Molnar #include <linux/sched/task.h>
53e93cd67SAl Viro #include <linux/fs.h>
63e93cd67SAl Viro #include <linux/path.h>
73e93cd67SAl Viro #include <linux/slab.h>
85ad4e53bSAl Viro #include <linux/fs_struct.h>
9f03c6599SAl Viro #include "internal.h"
10f03c6599SAl Viro
113e93cd67SAl Viro /*
123e93cd67SAl Viro * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
133e93cd67SAl Viro * It can block.
143e93cd67SAl Viro */
set_fs_root(struct fs_struct * fs,const struct path * path)15dcf787f3SAl Viro void set_fs_root(struct fs_struct *fs, const struct path *path)
163e93cd67SAl Viro {
173e93cd67SAl Viro struct path old_root;
183e93cd67SAl Viro
19f7a99c5bSAl Viro path_get(path);
202a4419b5SNick Piggin spin_lock(&fs->lock);
21c28cc364SNick Piggin write_seqcount_begin(&fs->seq);
223e93cd67SAl Viro old_root = fs->root;
233e93cd67SAl Viro fs->root = *path;
24c28cc364SNick Piggin write_seqcount_end(&fs->seq);
252a4419b5SNick Piggin spin_unlock(&fs->lock);
263e93cd67SAl Viro if (old_root.dentry)
27f7a99c5bSAl Viro path_put(&old_root);
283e93cd67SAl Viro }
293e93cd67SAl Viro
303e93cd67SAl Viro /*
313e93cd67SAl Viro * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
323e93cd67SAl Viro * It can block.
333e93cd67SAl Viro */
set_fs_pwd(struct fs_struct * fs,const struct path * path)34dcf787f3SAl Viro void set_fs_pwd(struct fs_struct *fs, const struct path *path)
353e93cd67SAl Viro {
363e93cd67SAl Viro struct path old_pwd;
373e93cd67SAl Viro
38f7a99c5bSAl Viro path_get(path);
392a4419b5SNick Piggin spin_lock(&fs->lock);
40c28cc364SNick Piggin write_seqcount_begin(&fs->seq);
413e93cd67SAl Viro old_pwd = fs->pwd;
423e93cd67SAl Viro fs->pwd = *path;
43c28cc364SNick Piggin write_seqcount_end(&fs->seq);
442a4419b5SNick Piggin spin_unlock(&fs->lock);
453e93cd67SAl Viro
463e93cd67SAl Viro if (old_pwd.dentry)
47f7a99c5bSAl Viro path_put(&old_pwd);
483e93cd67SAl Viro }
493e93cd67SAl Viro
replace_path(struct path * p,const struct path * old,const struct path * new)5082234e61SAl Viro static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
5182234e61SAl Viro {
5282234e61SAl Viro if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
5382234e61SAl Viro return 0;
5482234e61SAl Viro *p = *new;
5582234e61SAl Viro return 1;
5682234e61SAl Viro }
5782234e61SAl Viro
chroot_fs_refs(const struct path * old_root,const struct path * new_root)58dcf787f3SAl Viro void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
593e93cd67SAl Viro {
603e93cd67SAl Viro struct task_struct *g, *p;
613e93cd67SAl Viro struct fs_struct *fs;
623e93cd67SAl Viro int count = 0;
633e93cd67SAl Viro
643e93cd67SAl Viro read_lock(&tasklist_lock);
65*5ffd2c37SOleg Nesterov for_each_process_thread(g, p) {
663e93cd67SAl Viro task_lock(p);
673e93cd67SAl Viro fs = p->fs;
683e93cd67SAl Viro if (fs) {
6982234e61SAl Viro int hits = 0;
702a4419b5SNick Piggin spin_lock(&fs->lock);
71c28cc364SNick Piggin write_seqcount_begin(&fs->seq);
7282234e61SAl Viro hits += replace_path(&fs->root, old_root, new_root);
7382234e61SAl Viro hits += replace_path(&fs->pwd, old_root, new_root);
74c28cc364SNick Piggin write_seqcount_end(&fs->seq);
7582234e61SAl Viro while (hits--) {
7682234e61SAl Viro count++;
77f7a99c5bSAl Viro path_get(new_root);
7882234e61SAl Viro }
792a4419b5SNick Piggin spin_unlock(&fs->lock);
803e93cd67SAl Viro }
813e93cd67SAl Viro task_unlock(p);
82*5ffd2c37SOleg Nesterov }
833e93cd67SAl Viro read_unlock(&tasklist_lock);
843e93cd67SAl Viro while (count--)
85f7a99c5bSAl Viro path_put(old_root);
863e93cd67SAl Viro }
873e93cd67SAl Viro
free_fs_struct(struct fs_struct * fs)88498052bbSAl Viro void free_fs_struct(struct fs_struct *fs)
893e93cd67SAl Viro {
90f7a99c5bSAl Viro path_put(&fs->root);
91f7a99c5bSAl Viro path_put(&fs->pwd);
923e93cd67SAl Viro kmem_cache_free(fs_cachep, fs);
933e93cd67SAl Viro }
943e93cd67SAl Viro
exit_fs(struct task_struct * tsk)953e93cd67SAl Viro void exit_fs(struct task_struct *tsk)
963e93cd67SAl Viro {
973e93cd67SAl Viro struct fs_struct *fs = tsk->fs;
983e93cd67SAl Viro
993e93cd67SAl Viro if (fs) {
100498052bbSAl Viro int kill;
1013e93cd67SAl Viro task_lock(tsk);
1022a4419b5SNick Piggin spin_lock(&fs->lock);
1033e93cd67SAl Viro tsk->fs = NULL;
104498052bbSAl Viro kill = !--fs->users;
1052a4419b5SNick Piggin spin_unlock(&fs->lock);
1063e93cd67SAl Viro task_unlock(tsk);
107498052bbSAl Viro if (kill)
108498052bbSAl Viro free_fs_struct(fs);
1093e93cd67SAl Viro }
1103e93cd67SAl Viro }
1113e93cd67SAl Viro
copy_fs_struct(struct fs_struct * old)1123e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old)
1133e93cd67SAl Viro {
1143e93cd67SAl Viro struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
1153e93cd67SAl Viro /* We don't need to lock fs - think why ;-) */
1163e93cd67SAl Viro if (fs) {
117498052bbSAl Viro fs->users = 1;
118498052bbSAl Viro fs->in_exec = 0;
1192a4419b5SNick Piggin spin_lock_init(&fs->lock);
12026475371SAhmed S. Darwish seqcount_spinlock_init(&fs->seq, &fs->lock);
1213e93cd67SAl Viro fs->umask = old->umask;
122b3e19d92SNick Piggin
123b3e19d92SNick Piggin spin_lock(&old->lock);
124b3e19d92SNick Piggin fs->root = old->root;
125f7a99c5bSAl Viro path_get(&fs->root);
126b3e19d92SNick Piggin fs->pwd = old->pwd;
127f7a99c5bSAl Viro path_get(&fs->pwd);
128b3e19d92SNick Piggin spin_unlock(&old->lock);
1293e93cd67SAl Viro }
1303e93cd67SAl Viro return fs;
1313e93cd67SAl Viro }
1323e93cd67SAl Viro
unshare_fs_struct(void)1333e93cd67SAl Viro int unshare_fs_struct(void)
1343e93cd67SAl Viro {
135498052bbSAl Viro struct fs_struct *fs = current->fs;
136498052bbSAl Viro struct fs_struct *new_fs = copy_fs_struct(fs);
137498052bbSAl Viro int kill;
138498052bbSAl Viro
139498052bbSAl Viro if (!new_fs)
1403e93cd67SAl Viro return -ENOMEM;
141498052bbSAl Viro
142498052bbSAl Viro task_lock(current);
1432a4419b5SNick Piggin spin_lock(&fs->lock);
144498052bbSAl Viro kill = !--fs->users;
145498052bbSAl Viro current->fs = new_fs;
1462a4419b5SNick Piggin spin_unlock(&fs->lock);
147498052bbSAl Viro task_unlock(current);
148498052bbSAl Viro
149498052bbSAl Viro if (kill)
150498052bbSAl Viro free_fs_struct(fs);
151498052bbSAl Viro
1523e93cd67SAl Viro return 0;
1533e93cd67SAl Viro }
1543e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct);
1553e93cd67SAl Viro
current_umask(void)156ce3b0f8dSAl Viro int current_umask(void)
157ce3b0f8dSAl Viro {
158ce3b0f8dSAl Viro return current->fs->umask;
159ce3b0f8dSAl Viro }
160ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask);
161ce3b0f8dSAl Viro
1623e93cd67SAl Viro /* to be mentioned only in INIT_TASK */
1633e93cd67SAl Viro struct fs_struct init_fs = {
164498052bbSAl Viro .users = 1,
1652a4419b5SNick Piggin .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock),
16626475371SAhmed S. Darwish .seq = SEQCNT_SPINLOCK_ZERO(init_fs.seq, &init_fs.lock),
1673e93cd67SAl Viro .umask = 0022,
1683e93cd67SAl Viro };
169