1 /* Filesystem access-by-fd. 2 * 3 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12 #include <linux/fs_context.h> 13 #include <linux/fs_parser.h> 14 #include <linux/slab.h> 15 #include <linux/uaccess.h> 16 #include <linux/syscalls.h> 17 #include <linux/security.h> 18 #include <linux/anon_inodes.h> 19 #include <linux/namei.h> 20 #include <linux/file.h> 21 #include <uapi/linux/mount.h> 22 #include "internal.h" 23 #include "mount.h" 24 25 /* 26 * Allow the user to read back any error, warning or informational messages. 27 */ 28 static ssize_t fscontext_read(struct file *file, 29 char __user *_buf, size_t len, loff_t *pos) 30 { 31 struct fs_context *fc = file->private_data; 32 struct fc_log *log = fc->log; 33 unsigned int logsize = ARRAY_SIZE(log->buffer); 34 ssize_t ret; 35 char *p; 36 bool need_free; 37 int index, n; 38 39 ret = mutex_lock_interruptible(&fc->uapi_mutex); 40 if (ret < 0) 41 return ret; 42 43 if (log->head == log->tail) { 44 mutex_unlock(&fc->uapi_mutex); 45 return -ENODATA; 46 } 47 48 index = log->tail & (logsize - 1); 49 p = log->buffer[index]; 50 need_free = log->need_free & (1 << index); 51 log->buffer[index] = NULL; 52 log->need_free &= ~(1 << index); 53 log->tail++; 54 mutex_unlock(&fc->uapi_mutex); 55 56 ret = -EMSGSIZE; 57 n = strlen(p); 58 if (n > len) 59 goto err_free; 60 ret = -EFAULT; 61 if (copy_to_user(_buf, p, n) != 0) 62 goto err_free; 63 ret = n; 64 65 err_free: 66 if (need_free) 67 kfree(p); 68 return ret; 69 } 70 71 static int fscontext_release(struct inode *inode, struct file *file) 72 { 73 struct fs_context *fc = file->private_data; 74 75 if (fc) { 76 file->private_data = NULL; 77 put_fs_context(fc); 78 } 79 return 0; 80 } 81 82 const struct file_operations fscontext_fops = { 83 .read = fscontext_read, 84 .release = fscontext_release, 85 .llseek = no_llseek, 86 }; 87 88 /* 89 * Attach a filesystem context to a file and an fd. 90 */ 91 static int fscontext_create_fd(struct fs_context *fc, unsigned int o_flags) 92 { 93 int fd; 94 95 fd = anon_inode_getfd("[fscontext]", &fscontext_fops, fc, 96 O_RDWR | o_flags); 97 if (fd < 0) 98 put_fs_context(fc); 99 return fd; 100 } 101 102 static int fscontext_alloc_log(struct fs_context *fc) 103 { 104 fc->log = kzalloc(sizeof(*fc->log), GFP_KERNEL); 105 if (!fc->log) 106 return -ENOMEM; 107 refcount_set(&fc->log->usage, 1); 108 fc->log->owner = fc->fs_type->owner; 109 return 0; 110 } 111 112 /* 113 * Open a filesystem by name so that it can be configured for mounting. 114 * 115 * We are allowed to specify a container in which the filesystem will be 116 * opened, thereby indicating which namespaces will be used (notably, which 117 * network namespace will be used for network filesystems). 118 */ 119 SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags) 120 { 121 struct file_system_type *fs_type; 122 struct fs_context *fc; 123 const char *fs_name; 124 int ret; 125 126 if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN)) 127 return -EPERM; 128 129 if (flags & ~FSOPEN_CLOEXEC) 130 return -EINVAL; 131 132 fs_name = strndup_user(_fs_name, PAGE_SIZE); 133 if (IS_ERR(fs_name)) 134 return PTR_ERR(fs_name); 135 136 fs_type = get_fs_type(fs_name); 137 kfree(fs_name); 138 if (!fs_type) 139 return -ENODEV; 140 141 fc = fs_context_for_mount(fs_type, 0); 142 put_filesystem(fs_type); 143 if (IS_ERR(fc)) 144 return PTR_ERR(fc); 145 146 fc->phase = FS_CONTEXT_CREATE_PARAMS; 147 148 ret = fscontext_alloc_log(fc); 149 if (ret < 0) 150 goto err_fc; 151 152 return fscontext_create_fd(fc, flags & FSOPEN_CLOEXEC ? O_CLOEXEC : 0); 153 154 err_fc: 155 put_fs_context(fc); 156 return ret; 157 } 158 159 /* 160 * Pick a superblock into a context for reconfiguration. 161 */ 162 SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags) 163 { 164 struct fs_context *fc; 165 struct path target; 166 unsigned int lookup_flags; 167 int ret; 168 169 if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN)) 170 return -EPERM; 171 172 if ((flags & ~(FSPICK_CLOEXEC | 173 FSPICK_SYMLINK_NOFOLLOW | 174 FSPICK_NO_AUTOMOUNT | 175 FSPICK_EMPTY_PATH)) != 0) 176 return -EINVAL; 177 178 lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT; 179 if (flags & FSPICK_SYMLINK_NOFOLLOW) 180 lookup_flags &= ~LOOKUP_FOLLOW; 181 if (flags & FSPICK_NO_AUTOMOUNT) 182 lookup_flags &= ~LOOKUP_AUTOMOUNT; 183 if (flags & FSPICK_EMPTY_PATH) 184 lookup_flags |= LOOKUP_EMPTY; 185 ret = user_path_at(dfd, path, lookup_flags, &target); 186 if (ret < 0) 187 goto err; 188 189 ret = -EINVAL; 190 if (target.mnt->mnt_root != target.dentry) 191 goto err_path; 192 193 fc = fs_context_for_reconfigure(target.dentry, 0, 0); 194 if (IS_ERR(fc)) { 195 ret = PTR_ERR(fc); 196 goto err_path; 197 } 198 199 fc->phase = FS_CONTEXT_RECONF_PARAMS; 200 201 ret = fscontext_alloc_log(fc); 202 if (ret < 0) 203 goto err_fc; 204 205 path_put(&target); 206 return fscontext_create_fd(fc, flags & FSPICK_CLOEXEC ? O_CLOEXEC : 0); 207 208 err_fc: 209 put_fs_context(fc); 210 err_path: 211 path_put(&target); 212 err: 213 return ret; 214 } 215 216 /* 217 * Check the state and apply the configuration. Note that this function is 218 * allowed to 'steal' the value by setting param->xxx to NULL before returning. 219 */ 220 static int vfs_fsconfig_locked(struct fs_context *fc, int cmd, 221 struct fs_parameter *param) 222 { 223 struct super_block *sb; 224 int ret; 225 226 ret = finish_clean_context(fc); 227 if (ret) 228 return ret; 229 switch (cmd) { 230 case FSCONFIG_CMD_CREATE: 231 if (fc->phase != FS_CONTEXT_CREATE_PARAMS) 232 return -EBUSY; 233 fc->phase = FS_CONTEXT_CREATING; 234 ret = vfs_get_tree(fc); 235 if (ret) 236 break; 237 sb = fc->root->d_sb; 238 ret = security_sb_kern_mount(sb); 239 if (unlikely(ret)) { 240 fc_drop_locked(fc); 241 break; 242 } 243 up_write(&sb->s_umount); 244 fc->phase = FS_CONTEXT_AWAITING_MOUNT; 245 return 0; 246 case FSCONFIG_CMD_RECONFIGURE: 247 if (fc->phase != FS_CONTEXT_RECONF_PARAMS) 248 return -EBUSY; 249 fc->phase = FS_CONTEXT_RECONFIGURING; 250 sb = fc->root->d_sb; 251 if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) { 252 ret = -EPERM; 253 break; 254 } 255 down_write(&sb->s_umount); 256 ret = reconfigure_super(fc); 257 up_write(&sb->s_umount); 258 if (ret) 259 break; 260 vfs_clean_context(fc); 261 return 0; 262 default: 263 if (fc->phase != FS_CONTEXT_CREATE_PARAMS && 264 fc->phase != FS_CONTEXT_RECONF_PARAMS) 265 return -EBUSY; 266 267 return vfs_parse_fs_param(fc, param); 268 } 269 fc->phase = FS_CONTEXT_FAILED; 270 return ret; 271 } 272 273 /** 274 * sys_fsconfig - Set parameters and trigger actions on a context 275 * @fd: The filesystem context to act upon 276 * @cmd: The action to take 277 * @_key: Where appropriate, the parameter key to set 278 * @_value: Where appropriate, the parameter value to set 279 * @aux: Additional information for the value 280 * 281 * This system call is used to set parameters on a context, including 282 * superblock settings, data source and security labelling. 283 * 284 * Actions include triggering the creation of a superblock and the 285 * reconfiguration of the superblock attached to the specified context. 286 * 287 * When setting a parameter, @cmd indicates the type of value being proposed 288 * and @_key indicates the parameter to be altered. 289 * 290 * @_value and @aux are used to specify the value, should a value be required: 291 * 292 * (*) fsconfig_set_flag: No value is specified. The parameter must be boolean 293 * in nature. The key may be prefixed with "no" to invert the 294 * setting. @_value must be NULL and @aux must be 0. 295 * 296 * (*) fsconfig_set_string: A string value is specified. The parameter can be 297 * expecting boolean, integer, string or take a path. A conversion to an 298 * appropriate type will be attempted (which may include looking up as a 299 * path). @_value points to a NUL-terminated string and @aux must be 0. 300 * 301 * (*) fsconfig_set_binary: A binary blob is specified. @_value points to the 302 * blob and @aux indicates its size. The parameter must be expecting a 303 * blob. 304 * 305 * (*) fsconfig_set_path: A non-empty path is specified. The parameter must be 306 * expecting a path object. @_value points to a NUL-terminated string that 307 * is the path and @aux is a file descriptor at which to start a relative 308 * lookup or AT_FDCWD. 309 * 310 * (*) fsconfig_set_path_empty: As fsconfig_set_path, but with AT_EMPTY_PATH 311 * implied. 312 * 313 * (*) fsconfig_set_fd: An open file descriptor is specified. @_value must be 314 * NULL and @aux indicates the file descriptor. 315 */ 316 SYSCALL_DEFINE5(fsconfig, 317 int, fd, 318 unsigned int, cmd, 319 const char __user *, _key, 320 const void __user *, _value, 321 int, aux) 322 { 323 struct fs_context *fc; 324 struct fd f; 325 int ret; 326 327 struct fs_parameter param = { 328 .type = fs_value_is_undefined, 329 }; 330 331 if (fd < 0) 332 return -EINVAL; 333 334 switch (cmd) { 335 case FSCONFIG_SET_FLAG: 336 if (!_key || _value || aux) 337 return -EINVAL; 338 break; 339 case FSCONFIG_SET_STRING: 340 if (!_key || !_value || aux) 341 return -EINVAL; 342 break; 343 case FSCONFIG_SET_BINARY: 344 if (!_key || !_value || aux <= 0 || aux > 1024 * 1024) 345 return -EINVAL; 346 break; 347 case FSCONFIG_SET_PATH: 348 case FSCONFIG_SET_PATH_EMPTY: 349 if (!_key || !_value || (aux != AT_FDCWD && aux < 0)) 350 return -EINVAL; 351 break; 352 case FSCONFIG_SET_FD: 353 if (!_key || _value || aux < 0) 354 return -EINVAL; 355 break; 356 case FSCONFIG_CMD_CREATE: 357 case FSCONFIG_CMD_RECONFIGURE: 358 if (_key || _value || aux) 359 return -EINVAL; 360 break; 361 default: 362 return -EOPNOTSUPP; 363 } 364 365 f = fdget(fd); 366 if (!f.file) 367 return -EBADF; 368 ret = -EINVAL; 369 if (f.file->f_op != &fscontext_fops) 370 goto out_f; 371 372 fc = f.file->private_data; 373 if (fc->ops == &legacy_fs_context_ops) { 374 switch (cmd) { 375 case FSCONFIG_SET_BINARY: 376 case FSCONFIG_SET_PATH: 377 case FSCONFIG_SET_PATH_EMPTY: 378 case FSCONFIG_SET_FD: 379 ret = -EOPNOTSUPP; 380 goto out_f; 381 } 382 } 383 384 if (_key) { 385 param.key = strndup_user(_key, 256); 386 if (IS_ERR(param.key)) { 387 ret = PTR_ERR(param.key); 388 goto out_f; 389 } 390 } 391 392 switch (cmd) { 393 case FSCONFIG_SET_FLAG: 394 param.type = fs_value_is_flag; 395 break; 396 case FSCONFIG_SET_STRING: 397 param.type = fs_value_is_string; 398 param.string = strndup_user(_value, 256); 399 if (IS_ERR(param.string)) { 400 ret = PTR_ERR(param.string); 401 goto out_key; 402 } 403 param.size = strlen(param.string); 404 break; 405 case FSCONFIG_SET_BINARY: 406 param.type = fs_value_is_blob; 407 param.size = aux; 408 param.blob = memdup_user_nul(_value, aux); 409 if (IS_ERR(param.blob)) { 410 ret = PTR_ERR(param.blob); 411 goto out_key; 412 } 413 break; 414 case FSCONFIG_SET_PATH: 415 param.type = fs_value_is_filename; 416 param.name = getname_flags(_value, 0, NULL); 417 if (IS_ERR(param.name)) { 418 ret = PTR_ERR(param.name); 419 goto out_key; 420 } 421 param.dirfd = aux; 422 param.size = strlen(param.name->name); 423 break; 424 case FSCONFIG_SET_PATH_EMPTY: 425 param.type = fs_value_is_filename_empty; 426 param.name = getname_flags(_value, LOOKUP_EMPTY, NULL); 427 if (IS_ERR(param.name)) { 428 ret = PTR_ERR(param.name); 429 goto out_key; 430 } 431 param.dirfd = aux; 432 param.size = strlen(param.name->name); 433 break; 434 case FSCONFIG_SET_FD: 435 param.type = fs_value_is_file; 436 ret = -EBADF; 437 param.file = fget(aux); 438 if (!param.file) 439 goto out_key; 440 break; 441 default: 442 break; 443 } 444 445 ret = mutex_lock_interruptible(&fc->uapi_mutex); 446 if (ret == 0) { 447 ret = vfs_fsconfig_locked(fc, cmd, ¶m); 448 mutex_unlock(&fc->uapi_mutex); 449 } 450 451 /* Clean up the our record of any value that we obtained from 452 * userspace. Note that the value may have been stolen by the LSM or 453 * filesystem, in which case the value pointer will have been cleared. 454 */ 455 switch (cmd) { 456 case FSCONFIG_SET_STRING: 457 case FSCONFIG_SET_BINARY: 458 kfree(param.string); 459 break; 460 case FSCONFIG_SET_PATH: 461 case FSCONFIG_SET_PATH_EMPTY: 462 if (param.name) 463 putname(param.name); 464 break; 465 case FSCONFIG_SET_FD: 466 if (param.file) 467 fput(param.file); 468 break; 469 default: 470 break; 471 } 472 out_key: 473 kfree(param.key); 474 out_f: 475 fdput(f); 476 return ret; 477 } 478