13e93cd67SAl Viro #include <linux/module.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> 73e93cd67SAl Viro 83e93cd67SAl Viro /* 93e93cd67SAl Viro * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. 103e93cd67SAl Viro * It can block. 113e93cd67SAl Viro */ 123e93cd67SAl Viro void set_fs_root(struct fs_struct *fs, struct path *path) 133e93cd67SAl Viro { 143e93cd67SAl Viro struct path old_root; 153e93cd67SAl Viro 16*2a4419b5SNick Piggin spin_lock(&fs->lock); 173e93cd67SAl Viro old_root = fs->root; 183e93cd67SAl Viro fs->root = *path; 193e93cd67SAl Viro path_get(path); 20*2a4419b5SNick Piggin spin_unlock(&fs->lock); 213e93cd67SAl Viro if (old_root.dentry) 223e93cd67SAl Viro path_put(&old_root); 233e93cd67SAl Viro } 243e93cd67SAl Viro 253e93cd67SAl Viro /* 263e93cd67SAl Viro * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. 273e93cd67SAl Viro * It can block. 283e93cd67SAl Viro */ 293e93cd67SAl Viro void set_fs_pwd(struct fs_struct *fs, struct path *path) 303e93cd67SAl Viro { 313e93cd67SAl Viro struct path old_pwd; 323e93cd67SAl Viro 33*2a4419b5SNick Piggin spin_lock(&fs->lock); 343e93cd67SAl Viro old_pwd = fs->pwd; 353e93cd67SAl Viro fs->pwd = *path; 363e93cd67SAl Viro path_get(path); 37*2a4419b5SNick Piggin spin_unlock(&fs->lock); 383e93cd67SAl Viro 393e93cd67SAl Viro if (old_pwd.dentry) 403e93cd67SAl Viro path_put(&old_pwd); 413e93cd67SAl Viro } 423e93cd67SAl Viro 433e93cd67SAl Viro void chroot_fs_refs(struct path *old_root, struct path *new_root) 443e93cd67SAl Viro { 453e93cd67SAl Viro struct task_struct *g, *p; 463e93cd67SAl Viro struct fs_struct *fs; 473e93cd67SAl Viro int count = 0; 483e93cd67SAl Viro 493e93cd67SAl Viro read_lock(&tasklist_lock); 503e93cd67SAl Viro do_each_thread(g, p) { 513e93cd67SAl Viro task_lock(p); 523e93cd67SAl Viro fs = p->fs; 533e93cd67SAl Viro if (fs) { 54*2a4419b5SNick Piggin spin_lock(&fs->lock); 553e93cd67SAl Viro if (fs->root.dentry == old_root->dentry 563e93cd67SAl Viro && fs->root.mnt == old_root->mnt) { 573e93cd67SAl Viro path_get(new_root); 583e93cd67SAl Viro fs->root = *new_root; 593e93cd67SAl Viro count++; 603e93cd67SAl Viro } 613e93cd67SAl Viro if (fs->pwd.dentry == old_root->dentry 623e93cd67SAl Viro && fs->pwd.mnt == old_root->mnt) { 633e93cd67SAl Viro path_get(new_root); 643e93cd67SAl Viro fs->pwd = *new_root; 653e93cd67SAl Viro count++; 663e93cd67SAl Viro } 67*2a4419b5SNick Piggin spin_unlock(&fs->lock); 683e93cd67SAl Viro } 693e93cd67SAl Viro task_unlock(p); 703e93cd67SAl Viro } while_each_thread(g, p); 713e93cd67SAl Viro read_unlock(&tasklist_lock); 723e93cd67SAl Viro while (count--) 733e93cd67SAl Viro path_put(old_root); 743e93cd67SAl Viro } 753e93cd67SAl Viro 76498052bbSAl Viro void free_fs_struct(struct fs_struct *fs) 773e93cd67SAl Viro { 783e93cd67SAl Viro path_put(&fs->root); 793e93cd67SAl Viro path_put(&fs->pwd); 803e93cd67SAl Viro kmem_cache_free(fs_cachep, fs); 813e93cd67SAl Viro } 823e93cd67SAl Viro 833e93cd67SAl Viro void exit_fs(struct task_struct *tsk) 843e93cd67SAl Viro { 853e93cd67SAl Viro struct fs_struct *fs = tsk->fs; 863e93cd67SAl Viro 873e93cd67SAl Viro if (fs) { 88498052bbSAl Viro int kill; 893e93cd67SAl Viro task_lock(tsk); 90*2a4419b5SNick Piggin spin_lock(&fs->lock); 913e93cd67SAl Viro tsk->fs = NULL; 92498052bbSAl Viro kill = !--fs->users; 93*2a4419b5SNick Piggin spin_unlock(&fs->lock); 943e93cd67SAl Viro task_unlock(tsk); 95498052bbSAl Viro if (kill) 96498052bbSAl Viro free_fs_struct(fs); 973e93cd67SAl Viro } 983e93cd67SAl Viro } 993e93cd67SAl Viro 1003e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old) 1013e93cd67SAl Viro { 1023e93cd67SAl Viro struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); 1033e93cd67SAl Viro /* We don't need to lock fs - think why ;-) */ 1043e93cd67SAl Viro if (fs) { 105498052bbSAl Viro fs->users = 1; 106498052bbSAl Viro fs->in_exec = 0; 107*2a4419b5SNick Piggin spin_lock_init(&fs->lock); 1083e93cd67SAl Viro fs->umask = old->umask; 109f7ad3c6bSMiklos Szeredi get_fs_root_and_pwd(old, &fs->root, &fs->pwd); 1103e93cd67SAl Viro } 1113e93cd67SAl Viro return fs; 1123e93cd67SAl Viro } 1133e93cd67SAl Viro 1143e93cd67SAl Viro int unshare_fs_struct(void) 1153e93cd67SAl Viro { 116498052bbSAl Viro struct fs_struct *fs = current->fs; 117498052bbSAl Viro struct fs_struct *new_fs = copy_fs_struct(fs); 118498052bbSAl Viro int kill; 119498052bbSAl Viro 120498052bbSAl Viro if (!new_fs) 1213e93cd67SAl Viro return -ENOMEM; 122498052bbSAl Viro 123498052bbSAl Viro task_lock(current); 124*2a4419b5SNick Piggin spin_lock(&fs->lock); 125498052bbSAl Viro kill = !--fs->users; 126498052bbSAl Viro current->fs = new_fs; 127*2a4419b5SNick Piggin spin_unlock(&fs->lock); 128498052bbSAl Viro task_unlock(current); 129498052bbSAl Viro 130498052bbSAl Viro if (kill) 131498052bbSAl Viro free_fs_struct(fs); 132498052bbSAl Viro 1333e93cd67SAl Viro return 0; 1343e93cd67SAl Viro } 1353e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct); 1363e93cd67SAl Viro 137ce3b0f8dSAl Viro int current_umask(void) 138ce3b0f8dSAl Viro { 139ce3b0f8dSAl Viro return current->fs->umask; 140ce3b0f8dSAl Viro } 141ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask); 142ce3b0f8dSAl Viro 1433e93cd67SAl Viro /* to be mentioned only in INIT_TASK */ 1443e93cd67SAl Viro struct fs_struct init_fs = { 145498052bbSAl Viro .users = 1, 146*2a4419b5SNick Piggin .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), 1473e93cd67SAl Viro .umask = 0022, 1483e93cd67SAl Viro }; 1493e93cd67SAl Viro 1503e93cd67SAl Viro void daemonize_fs_struct(void) 1513e93cd67SAl Viro { 152498052bbSAl Viro struct fs_struct *fs = current->fs; 1533e93cd67SAl Viro 154498052bbSAl Viro if (fs) { 155498052bbSAl Viro int kill; 156498052bbSAl Viro 157498052bbSAl Viro task_lock(current); 158498052bbSAl Viro 159*2a4419b5SNick Piggin spin_lock(&init_fs.lock); 160498052bbSAl Viro init_fs.users++; 161*2a4419b5SNick Piggin spin_unlock(&init_fs.lock); 162498052bbSAl Viro 163*2a4419b5SNick Piggin spin_lock(&fs->lock); 164498052bbSAl Viro current->fs = &init_fs; 165498052bbSAl Viro kill = !--fs->users; 166*2a4419b5SNick Piggin spin_unlock(&fs->lock); 167498052bbSAl Viro 168498052bbSAl Viro task_unlock(current); 169498052bbSAl Viro if (kill) 170498052bbSAl Viro free_fs_struct(fs); 171498052bbSAl Viro } 1723e93cd67SAl Viro } 173