~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/fs_struct.c

Version: ~ [ linux-5.10-rc6 ] ~ [ linux-5.9.12 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.81 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.161 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.210 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.247 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.247 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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  */
 14 void 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  */
 33 void 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 
 49 static 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 
 57 void 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 
 87 void 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 
 94 void 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 
111 struct 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 
132 int 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 }
153 EXPORT_SYMBOL_GPL(unshare_fs_struct);
154 
155 int current_umask(void)
156 {
157         return current->fs->umask;
158 }
159 EXPORT_SYMBOL(current_umask);
160 
161 /* to be mentioned only in INIT_TASK */
162 struct 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp