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