Blame view
fs/fs_struct.c
3.89 KB
3e93cd671 Take fs_struct ha... |
1 2 3 4 5 |
#include <linux/module.h> #include <linux/sched.h> #include <linux/fs.h> #include <linux/path.h> #include <linux/slab.h> |
5ad4e53bd Get rid of indire... |
6 |
#include <linux/fs_struct.h> |
f03c65993 sanitize vfsmount... |
7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "internal.h" static inline void path_get_longterm(struct path *path) { path_get(path); mnt_make_longterm(path->mnt); } static inline void path_put_longterm(struct path *path) { mnt_make_shortterm(path->mnt); path_put(path); } |
3e93cd671 Take fs_struct ha... |
20 21 22 23 24 25 26 27 |
/* * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. * It can block. */ void set_fs_root(struct fs_struct *fs, struct path *path) { struct path old_root; |
2a4419b5b fs: fs_struct rwl... |
28 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
29 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
30 31 |
old_root = fs->root; fs->root = *path; |
f03c65993 sanitize vfsmount... |
32 |
path_get_longterm(path); |
c28cc3646 fs: fs_struct use... |
33 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
34 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
35 |
if (old_root.dentry) |
f03c65993 sanitize vfsmount... |
36 |
path_put_longterm(&old_root); |
3e93cd671 Take fs_struct ha... |
37 38 39 40 41 42 43 44 45 |
} /* * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. * It can block. */ void set_fs_pwd(struct fs_struct *fs, struct path *path) { struct path old_pwd; |
2a4419b5b fs: fs_struct rwl... |
46 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
47 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
48 49 |
old_pwd = fs->pwd; fs->pwd = *path; |
f03c65993 sanitize vfsmount... |
50 |
path_get_longterm(path); |
c28cc3646 fs: fs_struct use... |
51 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
52 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
53 54 |
if (old_pwd.dentry) |
f03c65993 sanitize vfsmount... |
55 |
path_put_longterm(&old_pwd); |
3e93cd671 Take fs_struct ha... |
56 57 58 59 60 61 62 63 64 65 66 67 68 |
} void chroot_fs_refs(struct path *old_root, struct path *new_root) { 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) { |
2a4419b5b fs: fs_struct rwl... |
69 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
70 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
71 72 |
if (fs->root.dentry == old_root->dentry && fs->root.mnt == old_root->mnt) { |
f03c65993 sanitize vfsmount... |
73 |
path_get_longterm(new_root); |
3e93cd671 Take fs_struct ha... |
74 75 76 77 78 |
fs->root = *new_root; count++; } if (fs->pwd.dentry == old_root->dentry && fs->pwd.mnt == old_root->mnt) { |
f03c65993 sanitize vfsmount... |
79 |
path_get_longterm(new_root); |
3e93cd671 Take fs_struct ha... |
80 81 82 |
fs->pwd = *new_root; count++; } |
c28cc3646 fs: fs_struct use... |
83 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
84 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
85 86 87 88 89 |
} task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); while (count--) |
f03c65993 sanitize vfsmount... |
90 |
path_put_longterm(old_root); |
3e93cd671 Take fs_struct ha... |
91 |
} |
498052bba New locking/refco... |
92 |
void free_fs_struct(struct fs_struct *fs) |
3e93cd671 Take fs_struct ha... |
93 |
{ |
f03c65993 sanitize vfsmount... |
94 95 |
path_put_longterm(&fs->root); path_put_longterm(&fs->pwd); |
498052bba New locking/refco... |
96 |
kmem_cache_free(fs_cachep, fs); |
3e93cd671 Take fs_struct ha... |
97 98 99 100 |
} void exit_fs(struct task_struct *tsk) { |
498052bba New locking/refco... |
101 |
struct fs_struct *fs = tsk->fs; |
3e93cd671 Take fs_struct ha... |
102 103 |
if (fs) { |
498052bba New locking/refco... |
104 |
int kill; |
3e93cd671 Take fs_struct ha... |
105 |
task_lock(tsk); |
2a4419b5b fs: fs_struct rwl... |
106 |
spin_lock(&fs->lock); |
c28cc3646 fs: fs_struct use... |
107 |
write_seqcount_begin(&fs->seq); |
3e93cd671 Take fs_struct ha... |
108 |
tsk->fs = NULL; |
498052bba New locking/refco... |
109 |
kill = !--fs->users; |
c28cc3646 fs: fs_struct use... |
110 |
write_seqcount_end(&fs->seq); |
2a4419b5b fs: fs_struct rwl... |
111 |
spin_unlock(&fs->lock); |
3e93cd671 Take fs_struct ha... |
112 |
task_unlock(tsk); |
498052bba New locking/refco... |
113 114 |
if (kill) free_fs_struct(fs); |
3e93cd671 Take fs_struct ha... |
115 116 117 118 119 120 121 122 |
} } 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... |
123 124 |
fs->users = 1; fs->in_exec = 0; |
2a4419b5b fs: fs_struct rwl... |
125 |
spin_lock_init(&fs->lock); |
c28cc3646 fs: fs_struct use... |
126 |
seqcount_init(&fs->seq); |
3e93cd671 Take fs_struct ha... |
127 |
fs->umask = old->umask; |
b3e19d924 fs: scale mntget/... |
128 129 130 |
spin_lock(&old->lock); fs->root = old->root; |
f03c65993 sanitize vfsmount... |
131 |
path_get_longterm(&fs->root); |
b3e19d924 fs: scale mntget/... |
132 |
fs->pwd = old->pwd; |
f03c65993 sanitize vfsmount... |
133 |
path_get_longterm(&fs->pwd); |
b3e19d924 fs: scale mntget/... |
134 |
spin_unlock(&old->lock); |
3e93cd671 Take fs_struct ha... |
135 136 137 138 139 140 |
} return fs; } int unshare_fs_struct(void) { |
498052bba New locking/refco... |
141 142 143 144 145 |
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... |
146 |
return -ENOMEM; |
498052bba New locking/refco... |
147 148 |
task_lock(current); |
2a4419b5b fs: fs_struct rwl... |
149 |
spin_lock(&fs->lock); |
498052bba New locking/refco... |
150 151 |
kill = !--fs->users; current->fs = new_fs; |
2a4419b5b fs: fs_struct rwl... |
152 |
spin_unlock(&fs->lock); |
498052bba New locking/refco... |
153 154 155 156 |
task_unlock(current); if (kill) free_fs_struct(fs); |
3e93cd671 Take fs_struct ha... |
157 158 159 |
return 0; } EXPORT_SYMBOL_GPL(unshare_fs_struct); |
ce3b0f8d5 New helper - curr... |
160 161 162 163 164 |
int current_umask(void) { return current->fs->umask; } EXPORT_SYMBOL(current_umask); |
3e93cd671 Take fs_struct ha... |
165 166 |
/* to be mentioned only in INIT_TASK */ struct fs_struct init_fs = { |
498052bba New locking/refco... |
167 |
.users = 1, |
2a4419b5b fs: fs_struct rwl... |
168 |
.lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), |
c28cc3646 fs: fs_struct use... |
169 |
.seq = SEQCNT_ZERO, |
3e93cd671 Take fs_struct ha... |
170 171 172 173 174 |
.umask = 0022, }; void daemonize_fs_struct(void) { |
498052bba New locking/refco... |
175 176 177 178 179 180 |
struct fs_struct *fs = current->fs; if (fs) { int kill; task_lock(current); |
3e93cd671 Take fs_struct ha... |
181 |
|
2a4419b5b fs: fs_struct rwl... |
182 |
spin_lock(&init_fs.lock); |
498052bba New locking/refco... |
183 |
init_fs.users++; |
2a4419b5b fs: fs_struct rwl... |
184 |
spin_unlock(&init_fs.lock); |
498052bba New locking/refco... |
185 |
|
2a4419b5b fs: fs_struct rwl... |
186 |
spin_lock(&fs->lock); |
498052bba New locking/refco... |
187 188 |
current->fs = &init_fs; kill = !--fs->users; |
2a4419b5b fs: fs_struct rwl... |
189 |
spin_unlock(&fs->lock); |
498052bba New locking/refco... |
190 191 192 193 194 |
task_unlock(current); if (kill) free_fs_struct(fs); } |
3e93cd671 Take fs_struct ha... |
195 |
} |