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