projects/linux·blob master · refs

252 lines · 6.1 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/export.h>
3#include <linux/sched/signal.h>
4#include <linux/sched/task.h>
5#include <linux/fs.h>
6#include <linux/path.h>
7#include <linux/slab.h>
8#include <linux/fs_struct.h>
9#include <linux/init_task.h>
10#include "internal.h"
11#include "mount.h"
12
13/*
14 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
15 * It can block.
16 */
17void set_fs_root(struct fs_struct *fs, const struct path *path)
18{
19 struct path old_root;
20
21 path_get(path);
22 write_seqlock(&fs->seq);
23 old_root = fs->root;
24 fs->root = *path;
25 write_sequnlock(&fs->seq);
26 if (old_root.dentry)
27 path_put(&old_root);
28}
29
30/*
31 * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
32 * It can block.
33 */
34void set_fs_pwd(struct fs_struct *fs, const struct path *path)
35{
36 struct path old_pwd;
37
38 path_get(path);
39 write_seqlock(&fs->seq);
40 old_pwd = fs->pwd;
41 fs->pwd = *path;
42 write_sequnlock(&fs->seq);
43
44 if (old_pwd.dentry)
45 path_put(&old_pwd);
46}
47
48static 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
56void 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 read_lock(&tasklist_lock);
63 for_each_process_thread(g, p) {
64 if (p->flags & (PF_KTHREAD | PF_EXITING | PF_DUMPCORE))
65 continue;
66
67 task_lock(p);
68 fs = p->real_fs;
69 if (fs) {
70 int hits = 0;
71 write_seqlock(&fs->seq);
72 hits += replace_path(&fs->root, old_root, new_root);
73 hits += replace_path(&fs->pwd, old_root, new_root);
74 while (hits--) {
75 count++;
76 path_get(new_root);
77 }
78 write_sequnlock(&fs->seq);
79 }
80 task_unlock(p);
81 }
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->real_fs;
97
98 if (fs) {
99 int kill;
100 task_lock(tsk);
101 read_seqlock_excl(&fs->seq);
102 tsk->real_fs = NULL;
103 tsk->fs = NULL;
104 kill = !--fs->users;
105 read_sequnlock_excl(&fs->seq);
106 task_unlock(tsk);
107 if (kill)
108 free_fs_struct(fs);
109 }
110}
111
112struct fs_struct *copy_fs_struct(struct fs_struct *old)
113{
114 struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
115 /* We don't need to lock fs - think why ;-) */
116 if (fs) {
117 fs->users = 1;
118 fs->in_exec = 0;
119 seqlock_init(&fs->seq);
120 fs->umask = old->umask;
121
122 read_seqlock_excl(&old->seq);
123 fs->root = old->root;
124 path_get(&fs->root);
125 fs->pwd = old->pwd;
126 path_get(&fs->pwd);
127 read_sequnlock_excl(&old->seq);
128 }
129 return fs;
130}
131
132int unshare_fs_struct(void)
133{
134 struct fs_struct *fs = current->real_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 read_seqlock_excl(&fs->seq);
143 VFS_WARN_ON_ONCE(fs != current->fs);
144 kill = !--fs->users;
145 current->fs = new_fs;
146 current->real_fs = new_fs;
147 read_sequnlock_excl(&fs->seq);
148 task_unlock(current);
149
150 if (kill)
151 free_fs_struct(fs);
152
153 return 0;
154}
155EXPORT_SYMBOL_GPL(unshare_fs_struct);
156
157/*
158 * PID 1 may choose to stop sharing fs_struct state with us.
159 * Either via unshare(CLONE_FS) or unshare(CLONE_NEWNS). Of
160 * course, PID 1 could have chosen to create arbitrary process
161 * trees that all share fs_struct state via CLONE_FS. This is a
162 * strong statement: We only care about PID 1 aka the thread-group
163 * leader so subthread's fs_struct state doesn't matter.
164 *
165 * PID 1 unsharing fs_struct state is a bug. PID 1 relies on
166 * various kthreads to be able to perform work based on its
167 * fs_struct state. Breaking that contract sucks for both sides.
168 * So just don't bother with extra work for this. No sane init
169 * system should ever do this.
170 *
171 * On older kernels if PID 1 unshared its filesystem state with us the
172 * kernel simply used the stale fs_struct state implicitly pinning
173 * anything that PID 1 had last used. Even if PID 1 might've moved on to
174 * some completely different fs_struct state and might've even unmounted
175 * the old root.
176 *
177 * This has hilarious consequences: Think continuing to dump coredump
178 * state into an implicitly pinned directory somewhere. Calling random
179 * binaries in the old rootfs via usermodehelpers.
180 *
181 * Be aggressive about this: We simply reject operating on stale
182 * fs_struct state by reverting to nullfs. Every kworker that does
183 * lookups after this point will fail. Every usermodehelper call will
184 * fail. Tough luck but let's be kind and emit a warning to userspace.
185 */
186static inline void validate_fs_switch(struct fs_struct *old_fs)
187{
188 might_sleep();
189
190 if (likely(current->pid != 1))
191 return;
192 /* @old_fs may be dangling but for comparison it's fine */
193 if (old_fs != userspace_init_fs)
194 return;
195 pr_warn("VFS: Pid 1 stopped sharing filesystem state\n");
196 set_fs_root(userspace_init_fs, &init_fs.root);
197 set_fs_pwd(userspace_init_fs, &init_fs.root);
198}
199
200struct fs_struct *switch_fs_struct(struct fs_struct *new_fs)
201{
202 struct fs_struct *fs;
203
204 scoped_guard(task_lock, current) {
205 fs = current->fs;
206 VFS_WARN_ON_ONCE(fs != current->real_fs);
207 read_seqlock_excl(&fs->seq);
208 current->fs = new_fs;
209 current->real_fs = new_fs;
210 if (--fs->users)
211 new_fs = NULL;
212 else
213 new_fs = fs;
214 read_sequnlock_excl(&fs->seq);
215 }
216
217 validate_fs_switch(fs);
218 return new_fs;
219}
220
221/* to be mentioned only in INIT_TASK */
222struct fs_struct init_fs = {
223 .users = 1,
224 .seq = __SEQLOCK_UNLOCKED(init_fs.seq),
225 .umask = 0022,
226};
227
228struct fs_struct *userspace_init_fs __ro_after_init;
229EXPORT_SYMBOL_GPL(userspace_init_fs);
230
231void __init init_userspace_fs(void)
232{
233 struct mount *m;
234 struct path root;
235
236 /* Move PID 1 from nullfs into the initramfs. */
237 m = topmost_overmount(current->nsproxy->mnt_ns->root);
238 root.mnt = &m->mnt;
239 root.dentry = root.mnt->mnt_root;
240
241 VFS_WARN_ON_ONCE(current->pid != 1);
242
243 set_fs_root(current->fs, &root);
244 set_fs_pwd(current->fs, &root);
245
246 /* Hold a reference for the global pointer. */
247 read_seqlock_excl(&current->fs->seq);
248 current->fs->users++;
249 read_sequnlock_excl(&current->fs->seq);
250
251 userspace_init_fs = current->fs;
252}