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