Blame view
fs/fs_struct.c
3.39 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
630d9c472 fs: reduce the us... |
2 |
#include <linux/export.h> |
3f07c0144 sched/headers: Pr... |
3 |
#include <linux/sched/signal.h> |
299300258 sched/headers: Pr... |
4 |
#include <linux/sched/task.h> |
3e93cd671 Take fs_struct ha... |
5 6 7 |
#include <linux/fs.h> #include <linux/path.h> #include <linux/slab.h> |
5ad4e53bd Get rid of indire... |
8 |
#include <linux/fs_struct.h> |
f03c65993 sanitize vfsmount... |
9 |
#include "internal.h" |
3e93cd671 Take fs_struct ha... |
10 11 12 13 |
/* * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. * It can block. */ |
dcf787f39 constify path_get... |
14 |
void set_fs_root(struct fs_struct *fs, const struct path *path) |
3e93cd671 Take fs_struct ha... |
15 16 |
{ struct path old_root; |
f7a99c5b7 get rid of ->mnt_... |
17 |
path_get(path); |
2a4419b5b fs: fs_struct rwl... |
18 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
19 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
20 21 |
old_root = fs->root; fs->root = *path; |
c28cc3646 fs: fs_struct use... |
22 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
23 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
24 |
if (old_root.dentry) |
f7a99c5b7 get rid of ->mnt_... |
25 |
path_put(&old_root); |
3e93cd671 Take fs_struct ha... |
26 27 28 29 30 31 |
} /* * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. * It can block. */ |
dcf787f39 constify path_get... |
32 |
void set_fs_pwd(struct fs_struct *fs, const struct path *path) |
3e93cd671 Take fs_struct ha... |
33 34 |
{ struct path old_pwd; |
f7a99c5b7 get rid of ->mnt_... |
35 |
path_get(path); |
2a4419b5b fs: fs_struct rwl... |
36 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
37 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
38 39 |
old_pwd = fs->pwd; fs->pwd = *path; |
c28cc3646 fs: fs_struct use... |
40 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
41 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
42 43 |
if (old_pwd.dentry) |
f7a99c5b7 get rid of ->mnt_... |
44 |
path_put(&old_pwd); |
3e93cd671 Take fs_struct ha... |
45 |
} |
82234e61a vfs: take path_ge... |
46 47 48 49 50 51 52 |
static inline int replace_path(struct path *p, const struct path *old, const struct path *new) { if (likely(p->dentry != old->dentry || p->mnt != old->mnt)) return 0; *p = *new; return 1; } |
dcf787f39 constify path_get... |
53 |
void chroot_fs_refs(const struct path *old_root, const struct path *new_root) |
3e93cd671 Take fs_struct ha... |
54 55 56 57 58 59 60 61 62 63 |
{ struct task_struct *g, *p; struct fs_struct *fs; int count = 0; read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); fs = p->fs; if (fs) { |
82234e61a vfs: take path_ge... |
64 |
int hits = 0; |
2a4419b5b fs: fs_struct rwl... |
65 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
66 |
write_seqcount_begin(&fs->seq); |
82234e61a vfs: take path_ge... |
67 68 69 70 |
hits += replace_path(&fs->root, old_root, new_root); hits += replace_path(&fs->pwd, old_root, new_root); write_seqcount_end(&fs->seq); while (hits--) { |
3e93cd671 Take fs_struct ha... |
71 |
count++; |
f7a99c5b7 get rid of ->mnt_... |
72 |
path_get(new_root); |
3e93cd671 Take fs_struct ha... |
73 |
} |
2a4419b5b fs: fs_struct rwl... |
74 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
75 76 77 78 79 |
} task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); while (count--) |
f7a99c5b7 get rid of ->mnt_... |
80 |
path_put(old_root); |
3e93cd671 Take fs_struct ha... |
81 |
} |
498052bba New locking/refco... |
82 |
void free_fs_struct(struct fs_struct *fs) |
3e93cd671 Take fs_struct ha... |
83 |
{ |
f7a99c5b7 get rid of ->mnt_... |
84 85 |
path_put(&fs->root); path_put(&fs->pwd); |
498052bba New locking/refco... |
86 |
kmem_cache_free(fs_cachep, fs); |
3e93cd671 Take fs_struct ha... |
87 88 89 90 |
} void exit_fs(struct task_struct *tsk) { |
498052bba New locking/refco... |
91 |
struct fs_struct *fs = tsk->fs; |
3e93cd671 Take fs_struct ha... |
92 93 |
if (fs) { |
498052bba New locking/refco... |
94 |
int kill; |
3e93cd671 Take fs_struct ha... |
95 |
task_lock(tsk); |
2a4419b5b fs: fs_struct rwl... |
96 |
spin_lock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
97 |
tsk->fs = NULL; |
498052bba New locking/refco... |
98 |
kill = !--fs->users; |
2a4419b5b fs: fs_struct rwl... |
99 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
100 |
task_unlock(tsk); |
498052bba New locking/refco... |
101 102 |
if (kill) free_fs_struct(fs); |
3e93cd671 Take fs_struct ha... |
103 104 105 106 107 108 109 110 |
} } struct fs_struct *copy_fs_struct(struct fs_struct *old) { struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); /* We don't need to lock fs - think why ;-) */ if (fs) { |
498052bba New locking/refco... |
111 112 |
fs->users = 1; fs->in_exec = 0; |
2a4419b5b fs: fs_struct rwl... |
113 |
spin_lock_init(&fs->lock); |
264753719 vfs: Use sequence... |
114 |
seqcount_spinlock_init(&fs->seq, &fs->lock); |
3e93cd671 Take fs_struct ha... |
115 |
fs->umask = old->umask; |
b3e19d924 fs: scale mntget/... |
116 117 118 |
spin_lock(&old->lock); fs->root = old->root; |
f7a99c5b7 get rid of ->mnt_... |
119 |
path_get(&fs->root); |
b3e19d924 fs: scale mntget/... |
120 |
fs->pwd = old->pwd; |
f7a99c5b7 get rid of ->mnt_... |
121 |
path_get(&fs->pwd); |
b3e19d924 fs: scale mntget/... |
122 |
spin_unlock(&old->lock); |
3e93cd671 Take fs_struct ha... |
123 124 125 126 127 128 |
} return fs; } int unshare_fs_struct(void) { |
498052bba New locking/refco... |
129 130 131 132 133 |
struct fs_struct *fs = current->fs; struct fs_struct *new_fs = copy_fs_struct(fs); int kill; if (!new_fs) |
3e93cd671 Take fs_struct ha... |
134 |
return -ENOMEM; |
498052bba New locking/refco... |
135 136 |
task_lock(current); |
2a4419b5b fs: fs_struct rwl... |
137 |
spin_lock(&fs->lock); |
498052bba New locking/refco... |
138 139 |
kill = !--fs->users; current->fs = new_fs; |
2a4419b5b fs: fs_struct rwl... |
140 |
spin_unlock(&fs->lock); |
498052bba New locking/refco... |
141 142 143 144 |
task_unlock(current); if (kill) free_fs_struct(fs); |
3e93cd671 Take fs_struct ha... |
145 146 147 |
return 0; } EXPORT_SYMBOL_GPL(unshare_fs_struct); |
ce3b0f8d5 New helper - curr... |
148 149 150 151 152 |
int current_umask(void) { return current->fs->umask; } EXPORT_SYMBOL(current_umask); |
3e93cd671 Take fs_struct ha... |
153 154 |
/* to be mentioned only in INIT_TASK */ struct fs_struct init_fs = { |
498052bba New locking/refco... |
155 |
.users = 1, |
2a4419b5b fs: fs_struct rwl... |
156 |
.lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), |
264753719 vfs: Use sequence... |
157 |
.seq = SEQCNT_SPINLOCK_ZERO(init_fs.seq, &init_fs.lock), |
3e93cd671 Take fs_struct ha... |
158 159 |
.umask = 0022, }; |