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
24static 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
61err_free:
62 if (need_free)
63 kfree(p);
64 return ret;
65}
66
67static 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
78const struct file_operations fscontext_fops = {
79 .read = fscontext_read,
80 .release = fscontext_release,
81 .llseek = no_llseek,
82};
83
84
85
86
87static 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
98static 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
115SYSCALL_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
150err_fc:
151 put_fs_context(fc);
152 return ret;
153}
154
155
156
157
158SYSCALL_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
204err_fc:
205 put_fs_context(fc);
206err_path:
207 path_put(&target);
208err:
209 return ret;
210}
211
212
213
214
215
216static 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 fc->phase = FS_CONTEXT_CREATING;
230 ret = vfs_get_tree(fc);
231 if (ret)
232 break;
233 sb = fc->root->d_sb;
234 ret = security_sb_kern_mount(sb);
235 if (unlikely(ret)) {
236 fc_drop_locked(fc);
237 break;
238 }
239 up_write(&sb->s_umount);
240 fc->phase = FS_CONTEXT_AWAITING_MOUNT;
241 return 0;
242 case FSCONFIG_CMD_RECONFIGURE:
243 if (fc->phase != FS_CONTEXT_RECONF_PARAMS)
244 return -EBUSY;
245 fc->phase = FS_CONTEXT_RECONFIGURING;
246 sb = fc->root->d_sb;
247 if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
248 ret = -EPERM;
249 break;
250 }
251 down_write(&sb->s_umount);
252 ret = reconfigure_super(fc);
253 up_write(&sb->s_umount);
254 if (ret)
255 break;
256 vfs_clean_context(fc);
257 return 0;
258 default:
259 if (fc->phase != FS_CONTEXT_CREATE_PARAMS &&
260 fc->phase != FS_CONTEXT_RECONF_PARAMS)
261 return -EBUSY;
262
263 return vfs_parse_fs_param(fc, param);
264 }
265 fc->phase = FS_CONTEXT_FAILED;
266 return ret;
267}
268
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
312SYSCALL_DEFINE5(fsconfig,
313 int, fd,
314 unsigned int, cmd,
315 const char __user *, _key,
316 const void __user *, _value,
317 int, aux)
318{
319 struct fs_context *fc;
320 struct fd f;
321 int ret;
322
323 struct fs_parameter param = {
324 .type = fs_value_is_undefined,
325 };
326
327 if (fd < 0)
328 return -EINVAL;
329
330 switch (cmd) {
331 case FSCONFIG_SET_FLAG:
332 if (!_key || _value || aux)
333 return -EINVAL;
334 break;
335 case FSCONFIG_SET_STRING:
336 if (!_key || !_value || aux)
337 return -EINVAL;
338 break;
339 case FSCONFIG_SET_BINARY:
340 if (!_key || !_value || aux <= 0 || aux > 1024 * 1024)
341 return -EINVAL;
342 break;
343 case FSCONFIG_SET_PATH:
344 case FSCONFIG_SET_PATH_EMPTY:
345 if (!_key || !_value || (aux != AT_FDCWD && aux < 0))
346 return -EINVAL;
347 break;
348 case FSCONFIG_SET_FD:
349 if (!_key || _value || aux < 0)
350 return -EINVAL;
351 break;
352 case FSCONFIG_CMD_CREATE:
353 case FSCONFIG_CMD_RECONFIGURE:
354 if (_key || _value || aux)
355 return -EINVAL;
356 break;
357 default:
358 return -EOPNOTSUPP;
359 }
360
361 f = fdget(fd);
362 if (!f.file)
363 return -EBADF;
364 ret = -EINVAL;
365 if (f.file->f_op != &fscontext_fops)
366 goto out_f;
367
368 fc = f.file->private_data;
369 if (fc->ops == &legacy_fs_context_ops) {
370 switch (cmd) {
371 case FSCONFIG_SET_BINARY:
372 case FSCONFIG_SET_PATH:
373 case FSCONFIG_SET_PATH_EMPTY:
374 case FSCONFIG_SET_FD:
375 ret = -EOPNOTSUPP;
376 goto out_f;
377 }
378 }
379
380 if (_key) {
381 param.key = strndup_user(_key, 256);
382 if (IS_ERR(param.key)) {
383 ret = PTR_ERR(param.key);
384 goto out_f;
385 }
386 }
387
388 switch (cmd) {
389 case FSCONFIG_SET_FLAG:
390 param.type = fs_value_is_flag;
391 break;
392 case FSCONFIG_SET_STRING:
393 param.type = fs_value_is_string;
394 param.string = strndup_user(_value, 256);
395 if (IS_ERR(param.string)) {
396 ret = PTR_ERR(param.string);
397 goto out_key;
398 }
399 param.size = strlen(param.string);
400 break;
401 case FSCONFIG_SET_BINARY:
402 param.type = fs_value_is_blob;
403 param.size = aux;
404 param.blob = memdup_user_nul(_value, aux);
405 if (IS_ERR(param.blob)) {
406 ret = PTR_ERR(param.blob);
407 goto out_key;
408 }
409 break;
410 case FSCONFIG_SET_PATH:
411 param.type = fs_value_is_filename;
412 param.name = getname_flags(_value, 0, NULL);
413 if (IS_ERR(param.name)) {
414 ret = PTR_ERR(param.name);
415 goto out_key;
416 }
417 param.dirfd = aux;
418 param.size = strlen(param.name->name);
419 break;
420 case FSCONFIG_SET_PATH_EMPTY:
421 param.type = fs_value_is_filename_empty;
422 param.name = getname_flags(_value, LOOKUP_EMPTY, NULL);
423 if (IS_ERR(param.name)) {
424 ret = PTR_ERR(param.name);
425 goto out_key;
426 }
427 param.dirfd = aux;
428 param.size = strlen(param.name->name);
429 break;
430 case FSCONFIG_SET_FD:
431 param.type = fs_value_is_file;
432 ret = -EBADF;
433 param.file = fget(aux);
434 if (!param.file)
435 goto out_key;
436 break;
437 default:
438 break;
439 }
440
441 ret = mutex_lock_interruptible(&fc->uapi_mutex);
442 if (ret == 0) {
443 ret = vfs_fsconfig_locked(fc, cmd, ¶m);
444 mutex_unlock(&fc->uapi_mutex);
445 }
446
447
448
449
450
451 switch (cmd) {
452 case FSCONFIG_SET_STRING:
453 case FSCONFIG_SET_BINARY:
454 kfree(param.string);
455 break;
456 case FSCONFIG_SET_PATH:
457 case FSCONFIG_SET_PATH_EMPTY:
458 if (param.name)
459 putname(param.name);
460 break;
461 case FSCONFIG_SET_FD:
462 if (param.file)
463 fput(param.file);
464 break;
465 default:
466 break;
467 }
468out_key:
469 kfree(param.key);
470out_f:
471 fdput(f);
472 return ret;
473}
474