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