This source file includes following definitions.
- fscontext_read
- fscontext_release
- fscontext_create_fd
- fscontext_alloc_log
- SYSCALL_DEFINE2
- SYSCALL_DEFINE3
- vfs_fsconfig_locked
- SYSCALL_DEFINE5
1
2
3
4
5
6
7
8 #include <linux/fs_context.h>
9 #include <linux/fs_parser.h>
10 #include <linux/slab.h>
11 #include <linux/uaccess.h>
12 #include <linux/syscalls.h>
13 #include <linux/security.h>
14 #include <linux/anon_inodes.h>
15 #include <linux/namei.h>
16 #include <linux/file.h>
17 #include <uapi/linux/mount.h>
18 #include "internal.h"
19 #include "mount.h"
20
21
22
23
24 static ssize_t fscontext_read(struct file *file,
25 char __user *_buf, size_t len, loff_t *pos)
26 {
27 struct fs_context *fc = file->private_data;
28 struct fc_log *log = fc->log;
29 unsigned int logsize = ARRAY_SIZE(log->buffer);
30 ssize_t ret;
31 char *p;
32 bool need_free;
33 int index, n;
34
35 ret = mutex_lock_interruptible(&fc->uapi_mutex);
36 if (ret < 0)
37 return ret;
38
39 if (log->head == log->tail) {
40 mutex_unlock(&fc->uapi_mutex);
41 return -ENODATA;
42 }
43
44 index = log->tail & (logsize - 1);
45 p = log->buffer[index];
46 need_free = log->need_free & (1 << index);
47 log->buffer[index] = NULL;
48 log->need_free &= ~(1 << index);
49 log->tail++;
50 mutex_unlock(&fc->uapi_mutex);
51
52 ret = -EMSGSIZE;
53 n = strlen(p);
54 if (n > len)
55 goto err_free;
56 ret = -EFAULT;
57 if (copy_to_user(_buf, p, n) != 0)
58 goto err_free;
59 ret = n;
60
61 err_free:
62 if (need_free)
63 kfree(p);
64 return ret;
65 }
66
67 static int fscontext_release(struct inode *inode, struct file *file)
68 {
69 struct fs_context *fc = file->private_data;
70
71 if (fc) {
72 file->private_data = NULL;
73 put_fs_context(fc);
74 }
75 return 0;
76 }
77
78 const struct file_operations fscontext_fops = {
79 .read = fscontext_read,
80 .release = fscontext_release,
81 .llseek = no_llseek,
82 };
83
84
85
86
87 static int fscontext_create_fd(struct fs_context *fc, unsigned int o_flags)
88 {
89 int fd;
90
91 fd = anon_inode_getfd("[fscontext]", &fscontext_fops, fc,
92 O_RDWR | o_flags);
93 if (fd < 0)
94 put_fs_context(fc);
95 return fd;
96 }
97
98 static int fscontext_alloc_log(struct fs_context *fc)
99 {
100 fc->log = kzalloc(sizeof(*fc->log), GFP_KERNEL);
101 if (!fc->log)
102 return -ENOMEM;
103 refcount_set(&fc->log->usage, 1);
104 fc->log->owner = fc->fs_type->owner;
105 return 0;
106 }
107
108
109
110
111
112
113
114
115 SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags)
116 {
117 struct file_system_type *fs_type;
118 struct fs_context *fc;
119 const char *fs_name;
120 int ret;
121
122 if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
123 return -EPERM;
124
125 if (flags & ~FSOPEN_CLOEXEC)
126 return -EINVAL;
127
128 fs_name = strndup_user(_fs_name, PAGE_SIZE);
129 if (IS_ERR(fs_name))
130 return PTR_ERR(fs_name);
131
132 fs_type = get_fs_type(fs_name);
133 kfree(fs_name);
134 if (!fs_type)
135 return -ENODEV;
136
137 fc = fs_context_for_mount(fs_type, 0);
138 put_filesystem(fs_type);
139 if (IS_ERR(fc))
140 return PTR_ERR(fc);
141
142 fc->phase = FS_CONTEXT_CREATE_PARAMS;
143
144 ret = fscontext_alloc_log(fc);
145 if (ret < 0)
146 goto err_fc;
147
148 return fscontext_create_fd(fc, flags & FSOPEN_CLOEXEC ? O_CLOEXEC : 0);
149
150 err_fc:
151 put_fs_context(fc);
152 return ret;
153 }
154
155
156
157
158 SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags)
159 {
160 struct fs_context *fc;
161 struct path target;
162 unsigned int lookup_flags;
163 int ret;
164
165 if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
166 return -EPERM;
167
168 if ((flags & ~(FSPICK_CLOEXEC |
169 FSPICK_SYMLINK_NOFOLLOW |
170 FSPICK_NO_AUTOMOUNT |
171 FSPICK_EMPTY_PATH)) != 0)
172 return -EINVAL;
173
174 lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
175 if (flags & FSPICK_SYMLINK_NOFOLLOW)
176 lookup_flags &= ~LOOKUP_FOLLOW;
177 if (flags & FSPICK_NO_AUTOMOUNT)
178 lookup_flags &= ~LOOKUP_AUTOMOUNT;
179 if (flags & FSPICK_EMPTY_PATH)
180 lookup_flags |= LOOKUP_EMPTY;
181 ret = user_path_at(dfd, path, lookup_flags, &target);
182 if (ret < 0)
183 goto err;
184
185 ret = -EINVAL;
186 if (target.mnt->mnt_root != target.dentry)
187 goto err_path;
188
189 fc = fs_context_for_reconfigure(target.dentry, 0, 0);
190 if (IS_ERR(fc)) {
191 ret = PTR_ERR(fc);
192 goto err_path;
193 }
194
195 fc->phase = FS_CONTEXT_RECONF_PARAMS;
196
197 ret = fscontext_alloc_log(fc);
198 if (ret < 0)
199 goto err_fc;
200
201 path_put(&target);
202 return fscontext_create_fd(fc, flags & FSPICK_CLOEXEC ? O_CLOEXEC : 0);
203
204 err_fc:
205 put_fs_context(fc);
206 err_path:
207 path_put(&target);
208 err:
209 return ret;
210 }
211
212
213
214
215
216 static int vfs_fsconfig_locked(struct fs_context *fc, int cmd,
217 struct fs_parameter *param)
218 {
219 struct super_block *sb;
220 int ret;
221
222 ret = finish_clean_context(fc);
223 if (ret)
224 return ret;
225 switch (cmd) {
226 case FSCONFIG_CMD_CREATE:
227 if (fc->phase != FS_CONTEXT_CREATE_PARAMS)
228 return -EBUSY;
229 if (!mount_capable(fc))
230 return -EPERM;
231 fc->phase = FS_CONTEXT_CREATING;
232 ret = vfs_get_tree(fc);
233 if (ret)
234 break;
235 sb = fc->root->d_sb;
236 ret = security_sb_kern_mount(sb);
237 if (unlikely(ret)) {
238 fc_drop_locked(fc);
239 break;
240 }
241 up_write(&sb->s_umount);
242 fc->phase = FS_CONTEXT_AWAITING_MOUNT;
243 return 0;
244 case FSCONFIG_CMD_RECONFIGURE:
245 if (fc->phase != FS_CONTEXT_RECONF_PARAMS)
246 return -EBUSY;
247 fc->phase = FS_CONTEXT_RECONFIGURING;
248 sb = fc->root->d_sb;
249 if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
250 ret = -EPERM;
251 break;
252 }
253 down_write(&sb->s_umount);
254 ret = reconfigure_super(fc);
255 up_write(&sb->s_umount);
256 if (ret)
257 break;
258 vfs_clean_context(fc);
259 return 0;
260 default:
261 if (fc->phase != FS_CONTEXT_CREATE_PARAMS &&
262 fc->phase != FS_CONTEXT_RECONF_PARAMS)
263 return -EBUSY;
264
265 return vfs_parse_fs_param(fc, param);
266 }
267 fc->phase = FS_CONTEXT_FAILED;
268 return ret;
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 SYSCALL_DEFINE5(fsconfig,
315 int, fd,
316 unsigned int, cmd,
317 const char __user *, _key,
318 const void __user *, _value,
319 int, aux)
320 {
321 struct fs_context *fc;
322 struct fd f;
323 int ret;
324
325 struct fs_parameter param = {
326 .type = fs_value_is_undefined,
327 };
328
329 if (fd < 0)
330 return -EINVAL;
331
332 switch (cmd) {
333 case FSCONFIG_SET_FLAG:
334 if (!_key || _value || aux)
335 return -EINVAL;
336 break;
337 case FSCONFIG_SET_STRING:
338 if (!_key || !_value || aux)
339 return -EINVAL;
340 break;
341 case FSCONFIG_SET_BINARY:
342 if (!_key || !_value || aux <= 0 || aux > 1024 * 1024)
343 return -EINVAL;
344 break;
345 case FSCONFIG_SET_PATH:
346 case FSCONFIG_SET_PATH_EMPTY:
347 if (!_key || !_value || (aux != AT_FDCWD && aux < 0))
348 return -EINVAL;
349 break;
350 case FSCONFIG_SET_FD:
351 if (!_key || _value || aux < 0)
352 return -EINVAL;
353 break;
354 case FSCONFIG_CMD_CREATE:
355 case FSCONFIG_CMD_RECONFIGURE:
356 if (_key || _value || aux)
357 return -EINVAL;
358 break;
359 default:
360 return -EOPNOTSUPP;
361 }
362
363 f = fdget(fd);
364 if (!f.file)
365 return -EBADF;
366 ret = -EINVAL;
367 if (f.file->f_op != &fscontext_fops)
368 goto out_f;
369
370 fc = f.file->private_data;
371 if (fc->ops == &legacy_fs_context_ops) {
372 switch (cmd) {
373 case FSCONFIG_SET_BINARY:
374 case FSCONFIG_SET_PATH:
375 case FSCONFIG_SET_PATH_EMPTY:
376 case FSCONFIG_SET_FD:
377 ret = -EOPNOTSUPP;
378 goto out_f;
379 }
380 }
381
382 if (_key) {
383 param.key = strndup_user(_key, 256);
384 if (IS_ERR(param.key)) {
385 ret = PTR_ERR(param.key);
386 goto out_f;
387 }
388 }
389
390 switch (cmd) {
391 case FSCONFIG_SET_FLAG:
392 param.type = fs_value_is_flag;
393 break;
394 case FSCONFIG_SET_STRING:
395 param.type = fs_value_is_string;
396 param.string = strndup_user(_value, 256);
397 if (IS_ERR(param.string)) {
398 ret = PTR_ERR(param.string);
399 goto out_key;
400 }
401 param.size = strlen(param.string);
402 break;
403 case FSCONFIG_SET_BINARY:
404 param.type = fs_value_is_blob;
405 param.size = aux;
406 param.blob = memdup_user_nul(_value, aux);
407 if (IS_ERR(param.blob)) {
408 ret = PTR_ERR(param.blob);
409 goto out_key;
410 }
411 break;
412 case FSCONFIG_SET_PATH:
413 param.type = fs_value_is_filename;
414 param.name = getname_flags(_value, 0, NULL);
415 if (IS_ERR(param.name)) {
416 ret = PTR_ERR(param.name);
417 goto out_key;
418 }
419 param.dirfd = aux;
420 param.size = strlen(param.name->name);
421 break;
422 case FSCONFIG_SET_PATH_EMPTY:
423 param.type = fs_value_is_filename_empty;
424 param.name = getname_flags(_value, LOOKUP_EMPTY, NULL);
425 if (IS_ERR(param.name)) {
426 ret = PTR_ERR(param.name);
427 goto out_key;
428 }
429 param.dirfd = aux;
430 param.size = strlen(param.name->name);
431 break;
432 case FSCONFIG_SET_FD:
433 param.type = fs_value_is_file;
434 ret = -EBADF;
435 param.file = fget(aux);
436 if (!param.file)
437 goto out_key;
438 break;
439 default:
440 break;
441 }
442
443 ret = mutex_lock_interruptible(&fc->uapi_mutex);
444 if (ret == 0) {
445 ret = vfs_fsconfig_locked(fc, cmd, ¶m);
446 mutex_unlock(&fc->uapi_mutex);
447 }
448
449
450
451
452
453 switch (cmd) {
454 case FSCONFIG_SET_STRING:
455 case FSCONFIG_SET_BINARY:
456 kfree(param.string);
457 break;
458 case FSCONFIG_SET_PATH:
459 case FSCONFIG_SET_PATH_EMPTY:
460 if (param.name)
461 putname(param.name);
462 break;
463 case FSCONFIG_SET_FD:
464 if (param.file)
465 fput(param.file);
466 break;
467 default:
468 break;
469 }
470 out_key:
471 kfree(param.key);
472 out_f:
473 fdput(f);
474 return ret;
475 }