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.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.log = kzalloc(sizeof(*fc->log.log), GFP_KERNEL);
101 if (!fc->log.log)
102 return -ENOMEM;
103 refcount_set(&fc->log.log->usage, 1);
104 fc->log.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 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
314SYSCALL_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 int lookup_flags = 0;
325
326 struct fs_parameter param = {
327 .type = fs_value_is_undefined,
328 };
329
330 if (fd < 0)
331 return -EINVAL;
332
333 switch (cmd) {
334 case FSCONFIG_SET_FLAG:
335 if (!_key || _value || aux)
336 return -EINVAL;
337 break;
338 case FSCONFIG_SET_STRING:
339 if (!_key || !_value || aux)
340 return -EINVAL;
341 break;
342 case FSCONFIG_SET_BINARY:
343 if (!_key || !_value || aux <= 0 || aux > 1024 * 1024)
344 return -EINVAL;
345 break;
346 case FSCONFIG_SET_PATH:
347 case FSCONFIG_SET_PATH_EMPTY:
348 if (!_key || !_value || (aux != AT_FDCWD && aux < 0))
349 return -EINVAL;
350 break;
351 case FSCONFIG_SET_FD:
352 if (!_key || _value || aux < 0)
353 return -EINVAL;
354 break;
355 case FSCONFIG_CMD_CREATE:
356 case FSCONFIG_CMD_RECONFIGURE:
357 if (_key || _value || aux)
358 return -EINVAL;
359 break;
360 default:
361 return -EOPNOTSUPP;
362 }
363
364 f = fdget(fd);
365 if (!f.file)
366 return -EBADF;
367 ret = -EINVAL;
368 if (f.file->f_op != &fscontext_fops)
369 goto out_f;
370
371 fc = f.file->private_data;
372 if (fc->ops == &legacy_fs_context_ops) {
373 switch (cmd) {
374 case FSCONFIG_SET_BINARY:
375 case FSCONFIG_SET_PATH:
376 case FSCONFIG_SET_PATH_EMPTY:
377 case FSCONFIG_SET_FD:
378 ret = -EOPNOTSUPP;
379 goto out_f;
380 }
381 }
382
383 if (_key) {
384 param.key = strndup_user(_key, 256);
385 if (IS_ERR(param.key)) {
386 ret = PTR_ERR(param.key);
387 goto out_f;
388 }
389 }
390
391 switch (cmd) {
392 case FSCONFIG_SET_FLAG:
393 param.type = fs_value_is_flag;
394 break;
395 case FSCONFIG_SET_STRING:
396 param.type = fs_value_is_string;
397 param.string = strndup_user(_value, 256);
398 if (IS_ERR(param.string)) {
399 ret = PTR_ERR(param.string);
400 goto out_key;
401 }
402 param.size = strlen(param.string);
403 break;
404 case FSCONFIG_SET_BINARY:
405 param.type = fs_value_is_blob;
406 param.size = aux;
407 param.blob = memdup_user_nul(_value, aux);
408 if (IS_ERR(param.blob)) {
409 ret = PTR_ERR(param.blob);
410 goto out_key;
411 }
412 break;
413 case FSCONFIG_SET_PATH_EMPTY:
414 lookup_flags = LOOKUP_EMPTY;
415 fallthrough;
416 case FSCONFIG_SET_PATH:
417 param.type = fs_value_is_filename;
418 param.name = getname_flags(_value, lookup_flags, NULL);
419 if (IS_ERR(param.name)) {
420 ret = PTR_ERR(param.name);
421 goto out_key;
422 }
423 param.dirfd = aux;
424 param.size = strlen(param.name->name);
425 break;
426 case FSCONFIG_SET_FD:
427 param.type = fs_value_is_file;
428 ret = -EBADF;
429 param.file = fget(aux);
430 if (!param.file)
431 goto out_key;
432 break;
433 default:
434 break;
435 }
436
437 ret = mutex_lock_interruptible(&fc->uapi_mutex);
438 if (ret == 0) {
439 ret = vfs_fsconfig_locked(fc, cmd, ¶m);
440 mutex_unlock(&fc->uapi_mutex);
441 }
442
443
444
445
446
447 switch (cmd) {
448 case FSCONFIG_SET_STRING:
449 case FSCONFIG_SET_BINARY:
450 kfree(param.string);
451 break;
452 case FSCONFIG_SET_PATH:
453 case FSCONFIG_SET_PATH_EMPTY:
454 if (param.name)
455 putname(param.name);
456 break;
457 case FSCONFIG_SET_FD:
458 if (param.file)
459 fput(param.file);
460 break;
461 default:
462 break;
463 }
464out_key:
465 kfree(param.key);
466out_f:
467 fdput(f);
468 return ret;
469}
470