1630d9c47SPaul Gortmaker #include <linux/export.h> 23e93cd67SAl Viro #include <linux/sched.h> 33e93cd67SAl Viro #include <linux/fs.h> 43e93cd67SAl Viro #include <linux/path.h> 53e93cd67SAl Viro #include <linux/slab.h> 65ad4e53bSAl Viro #include <linux/fs_struct.h> 7f03c6599SAl Viro #include "internal.h" 8f03c6599SAl Viro 93e93cd67SAl Viro /* 103e93cd67SAl Viro * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. 113e93cd67SAl Viro * It can block. 123e93cd67SAl Viro */ 13dcf787f3SAl Viro void set_fs_root(struct fs_struct *fs, const struct path *path) 143e93cd67SAl Viro { 153e93cd67SAl Viro struct path old_root; 163e93cd67SAl Viro 17f7a99c5bSAl Viro path_get(path); 182a4419b5SNick Piggin spin_lock(&fs->lock); 19c28cc364SNick Piggin write_seqcount_begin(&fs->seq); 203e93cd67SAl Viro old_root = fs->root; 213e93cd67SAl Viro fs->root = *path; 22c28cc364SNick Piggin write_seqcount_end(&fs->seq); 232a4419b5SNick Piggin spin_unlock(&fs->lock); 243e93cd67SAl Viro if (old_root.dentry) 25f7a99c5bSAl Viro path_put(&old_root); 263e93cd67SAl Viro } 273e93cd67SAl Viro 283e93cd67SAl Viro /* 293e93cd67SAl Viro * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. 303e93cd67SAl Viro * It can block. 313e93cd67SAl Viro */ 32dcf787f3SAl Viro void set_fs_pwd(struct fs_struct *fs, const struct path *path) 333e93cd67SAl Viro { 343e93cd67SAl Viro struct path old_pwd; 353e93cd67SAl Viro 36f7a99c5bSAl Viro path_get(path); 372a4419b5SNick Piggin spin_lock(&fs->lock); 38c28cc364SNick Piggin write_seqcount_begin(&fs->seq); 393e93cd67SAl Viro old_pwd = fs->pwd; 403e93cd67SAl Viro fs->pwd = *path; 41c28cc364SNick Piggin write_seqcount_end(&fs->seq); 422a4419b5SNick Piggin spin_unlock(&fs->lock); 433e93cd67SAl Viro 443e93cd67SAl Viro if (old_pwd.dentry) 45f7a99c5bSAl Viro path_put(&old_pwd); 463e93cd67SAl Viro } 473e93cd67SAl Viro 4882234e61SAl Viro static inline int replace_path(struct path *p, const struct path *old, const struct path *new) 4982234e61SAl Viro { 5082234e61SAl Viro if (likely(p->dentry != old->dentry || p->mnt != old->mnt)) 5182234e61SAl Viro return 0; 5282234e61SAl Viro *p = *new; 5382234e61SAl Viro return 1; 5482234e61SAl Viro } 5582234e61SAl Viro 56dcf787f3SAl Viro void chroot_fs_refs(const struct path *old_root, const struct path *new_root) 573e93cd67SAl Viro { 583e93cd67SAl Viro struct task_struct *g, *p; 593e93cd67SAl Viro struct fs_struct *fs; 603e93cd67SAl Viro int count = 0; 613e93cd67SAl Viro 623e93cd67SAl Viro read_lock(&tasklist_lock); 633e93cd67SAl Viro do_each_thread(g, p) { 643e93cd67SAl Viro task_lock(p); 653e93cd67SAl Viro fs = p->fs; 663e93cd67SAl Viro if (fs) { 6782234e61SAl Viro int hits = 0; 682a4419b5SNick Piggin spin_lock(&fs->lock); 69c28cc364SNick Piggin write_seqcount_begin(&fs->seq); 7082234e61SAl Viro hits += replace_path(&fs->root, old_root, new_root); 7182234e61SAl Viro hits += replace_path(&fs->pwd, old_root, new_root); 72c28cc364SNick Piggin write_seqcount_end(&fs->seq); 7382234e61SAl Viro while (hits--) { 7482234e61SAl Viro count++; 75f7a99c5bSAl Viro path_get(new_root); 7682234e61SAl Viro } 772a4419b5SNick Piggin spin_unlock(&fs->lock); 783e93cd67SAl Viro } 793e93cd67SAl Viro task_unlock(p); 803e93cd67SAl Viro } while_each_thread(g, p); 813e93cd67SAl Viro read_unlock(&tasklist_lock); 823e93cd67SAl Viro while (count--) 83f7a99c5bSAl Viro path_put(old_root); 843e93cd67SAl Viro } 853e93cd67SAl Viro 86498052bbSAl Viro void free_fs_struct(struct fs_struct *fs) 873e93cd67SAl Viro { 88f7a99c5bSAl Viro path_put(&fs->root); 89f7a99c5bSAl Viro path_put(&fs->pwd); 903e93cd67SAl Viro kmem_cache_free(fs_cachep, fs); 913e93cd67SAl Viro } 923e93cd67SAl Viro 933e93cd67SAl Viro void exit_fs(struct task_struct *tsk) 943e93cd67SAl Viro { 953e93cd67SAl Viro struct fs_struct *fs = tsk->fs; 963e93cd67SAl Viro 973e93cd67SAl Viro if (fs) { 98498052bbSAl Viro int kill; 993e93cd67SAl Viro task_lock(tsk); 1002a4419b5SNick Piggin spin_lock(&fs->lock); 1013e93cd67SAl Viro tsk->fs = NULL; 102498052bbSAl Viro kill = !--fs->users; 1032a4419b5SNick Piggin spin_unlock(&fs->lock); 1043e93cd67SAl Viro task_unlock(tsk); 105498052bbSAl Viro if (kill) 106498052bbSAl Viro free_fs_struct(fs); 1073e93cd67SAl Viro } 1083e93cd67SAl Viro } 1093e93cd67SAl Viro 1103e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old) 1113e93cd67SAl Viro { 1123e93cd67SAl Viro struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); 1133e93cd67SAl Viro /* We don't need to lock fs - think why ;-) */ 1143e93cd67SAl Viro if (fs) { 115498052bbSAl Viro fs->users = 1; 116498052bbSAl Viro fs->in_exec = 0; 1172a4419b5SNick Piggin spin_lock_init(&fs->lock); 118c28cc364SNick Piggin seqcount_init(&fs->seq); 1193e93cd67SAl Viro fs->umask = old->umask; 120b3e19d92SNick Piggin 121b3e19d92SNick Piggin spin_lock(&old->lock); 122b3e19d92SNick Piggin fs->root = old->root; 123f7a99c5bSAl Viro path_get(&fs->root); 124b3e19d92SNick Piggin fs->pwd = old->pwd; 125f7a99c5bSAl Viro path_get(&fs->pwd); 126b3e19d92SNick Piggin spin_unlock(&old->lock); 1273e93cd67SAl Viro } 1283e93cd67SAl Viro return fs; 1293e93cd67SAl Viro } 1303e93cd67SAl Viro 1313e93cd67SAl Viro int unshare_fs_struct(void) 1323e93cd67SAl Viro { 133498052bbSAl Viro struct fs_struct *fs = current->fs; 134498052bbSAl Viro struct fs_struct *new_fs = copy_fs_struct(fs); 135498052bbSAl Viro int kill; 136498052bbSAl Viro 137498052bbSAl Viro if (!new_fs) 1383e93cd67SAl Viro return -ENOMEM; 139498052bbSAl Viro 140498052bbSAl Viro task_lock(current); 1412a4419b5SNick Piggin spin_lock(&fs->lock); 142498052bbSAl Viro kill = !--fs->users; 143498052bbSAl Viro current->fs = new_fs; 1442a4419b5SNick Piggin spin_unlock(&fs->lock); 145498052bbSAl Viro task_unlock(current); 146498052bbSAl Viro 147498052bbSAl Viro if (kill) 148498052bbSAl Viro free_fs_struct(fs); 149498052bbSAl Viro 1503e93cd67SAl Viro return 0; 1513e93cd67SAl Viro } 1523e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct); 1533e93cd67SAl Viro 154ce3b0f8dSAl Viro int current_umask(void) 155ce3b0f8dSAl Viro { 156ce3b0f8dSAl Viro return current->fs->umask; 157ce3b0f8dSAl Viro } 158ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask); 159ce3b0f8dSAl Viro 1603e93cd67SAl Viro /* to be mentioned only in INIT_TASK */ 1613e93cd67SAl Viro struct fs_struct init_fs = { 162498052bbSAl Viro .users = 1, 1632a4419b5SNick Piggin .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), 164*1ca7d67cSJohn Stultz .seq = SEQCNT_ZERO(init_fs.seq), 1653e93cd67SAl Viro .umask = 0022, 1663e93cd67SAl Viro }; 167