Root/
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 | void set_fs_root(struct fs_struct *fs, struct path *path) |
14 | { |
15 | struct path old_root; |
16 | |
17 | path_get(path); |
18 | spin_lock(&fs->lock); |
19 | write_seqcount_begin(&fs->seq); |
20 | old_root = fs->root; |
21 | fs->root = *path; |
22 | write_seqcount_end(&fs->seq); |
23 | spin_unlock(&fs->lock); |
24 | if (old_root.dentry) |
25 | path_put(&old_root); |
26 | } |
27 | |
28 | /* |
29 | * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. |
30 | * It can block. |
31 | */ |
32 | void set_fs_pwd(struct fs_struct *fs, struct path *path) |
33 | { |
34 | struct path old_pwd; |
35 | |
36 | path_get(path); |
37 | spin_lock(&fs->lock); |
38 | write_seqcount_begin(&fs->seq); |
39 | old_pwd = fs->pwd; |
40 | fs->pwd = *path; |
41 | write_seqcount_end(&fs->seq); |
42 | spin_unlock(&fs->lock); |
43 | |
44 | if (old_pwd.dentry) |
45 | path_put(&old_pwd); |
46 | } |
47 | |
48 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) |
49 | { |
50 | if (likely(p->dentry != old->dentry || p->mnt != old->mnt)) |
51 | return 0; |
52 | *p = *new; |
53 | return 1; |
54 | } |
55 | |
56 | void chroot_fs_refs(struct path *old_root, struct path *new_root) |
57 | { |
58 | struct task_struct *g, *p; |
59 | struct fs_struct *fs; |
60 | int count = 0; |
61 | |
62 | read_lock(&tasklist_lock); |
63 | do_each_thread(g, p) { |
64 | task_lock(p); |
65 | fs = p->fs; |
66 | 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 | hits += replace_path(&fs->pwd, old_root, new_root); |
72 | write_seqcount_end(&fs->seq); |
73 | while (hits--) { |
74 | count++; |
75 | path_get(new_root); |
76 | } |
77 | spin_unlock(&fs->lock); |
78 | } |
79 | task_unlock(p); |
80 | } while_each_thread(g, p); |
81 | read_unlock(&tasklist_lock); |
82 | while (count--) |
83 | path_put(old_root); |
84 | } |
85 | |
86 | void free_fs_struct(struct fs_struct *fs) |
87 | { |
88 | path_put(&fs->root); |
89 | path_put(&fs->pwd); |
90 | kmem_cache_free(fs_cachep, fs); |
91 | } |
92 | |
93 | void exit_fs(struct task_struct *tsk) |
94 | { |
95 | struct fs_struct *fs = tsk->fs; |
96 | |
97 | if (fs) { |
98 | int kill; |
99 | task_lock(tsk); |
100 | spin_lock(&fs->lock); |
101 | tsk->fs = NULL; |
102 | kill = !--fs->users; |
103 | spin_unlock(&fs->lock); |
104 | task_unlock(tsk); |
105 | if (kill) |
106 | free_fs_struct(fs); |
107 | } |
108 | } |
109 | |
110 | struct fs_struct *copy_fs_struct(struct fs_struct *old) |
111 | { |
112 | struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); |
113 | /* We don't need to lock fs - think why ;-) */ |
114 | if (fs) { |
115 | fs->users = 1; |
116 | fs->in_exec = 0; |
117 | spin_lock_init(&fs->lock); |
118 | seqcount_init(&fs->seq); |
119 | fs->umask = old->umask; |
120 | |
121 | spin_lock(&old->lock); |
122 | fs->root = old->root; |
123 | path_get(&fs->root); |
124 | fs->pwd = old->pwd; |
125 | path_get(&fs->pwd); |
126 | spin_unlock(&old->lock); |
127 | } |
128 | return fs; |
129 | } |
130 | |
131 | int unshare_fs_struct(void) |
132 | { |
133 | struct fs_struct *fs = current->fs; |
134 | struct fs_struct *new_fs = copy_fs_struct(fs); |
135 | int kill; |
136 | |
137 | if (!new_fs) |
138 | return -ENOMEM; |
139 | |
140 | task_lock(current); |
141 | spin_lock(&fs->lock); |
142 | kill = !--fs->users; |
143 | current->fs = new_fs; |
144 | spin_unlock(&fs->lock); |
145 | task_unlock(current); |
146 | |
147 | if (kill) |
148 | free_fs_struct(fs); |
149 | |
150 | return 0; |
151 | } |
152 | EXPORT_SYMBOL_GPL(unshare_fs_struct); |
153 | |
154 | int current_umask(void) |
155 | { |
156 | 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, |
165 | .umask = 0022, |
166 | }; |
167 | |
168 | void daemonize_fs_struct(void) |
169 | { |
170 | struct fs_struct *fs = current->fs; |
171 | |
172 | if (fs) { |
173 | int kill; |
174 | |
175 | task_lock(current); |
176 | |
177 | spin_lock(&init_fs.lock); |
178 | init_fs.users++; |
179 | spin_unlock(&init_fs.lock); |
180 | |
181 | spin_lock(&fs->lock); |
182 | current->fs = &init_fs; |
183 | kill = !--fs->users; |
184 | spin_unlock(&fs->lock); |
185 | |
186 | task_unlock(current); |
187 | if (kill) |
188 | free_fs_struct(fs); |
189 | } |
190 | } |
191 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9