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