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