1 /* Provide a way to create a superblock configuration context within the kernel 2 * that allows a superblock to be set up prior to mounting. 3 * 4 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public Licence 9 * as published by the Free Software Foundation; either version 10 * 2 of the Licence, or (at your option) any later version. 11 */ 12 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 #include <linux/fs_context.h> 15 #include <linux/fs_parser.h> 16 #include <linux/fs.h> 17 #include <linux/mount.h> 18 #include <linux/nsproxy.h> 19 #include <linux/slab.h> 20 #include <linux/magic.h> 21 #include <linux/security.h> 22 #include <linux/mnt_namespace.h> 23 #include <linux/pid_namespace.h> 24 #include <linux/user_namespace.h> 25 #include <net/net_namespace.h> 26 #include "mount.h" 27 #include "internal.h" 28 29 enum legacy_fs_param { 30 LEGACY_FS_UNSET_PARAMS, 31 LEGACY_FS_MONOLITHIC_PARAMS, 32 LEGACY_FS_INDIVIDUAL_PARAMS, 33 }; 34 35 struct legacy_fs_context { 36 char *legacy_data; /* Data page for legacy filesystems */ 37 size_t data_size; 38 enum legacy_fs_param param_type; 39 }; 40 41 static int legacy_init_fs_context(struct fs_context *fc); 42 43 static const struct constant_table common_set_sb_flag[] = { 44 { "dirsync", SB_DIRSYNC }, 45 { "lazytime", SB_LAZYTIME }, 46 { "mand", SB_MANDLOCK }, 47 { "posixacl", SB_POSIXACL }, 48 { "ro", SB_RDONLY }, 49 { "sync", SB_SYNCHRONOUS }, 50 }; 51 52 static const struct constant_table common_clear_sb_flag[] = { 53 { "async", SB_SYNCHRONOUS }, 54 { "nolazytime", SB_LAZYTIME }, 55 { "nomand", SB_MANDLOCK }, 56 { "rw", SB_RDONLY }, 57 { "silent", SB_SILENT }, 58 }; 59 60 static const char *const forbidden_sb_flag[] = { 61 "bind", 62 "dev", 63 "exec", 64 "move", 65 "noatime", 66 "nodev", 67 "nodiratime", 68 "noexec", 69 "norelatime", 70 "nostrictatime", 71 "nosuid", 72 "private", 73 "rec", 74 "relatime", 75 "remount", 76 "shared", 77 "slave", 78 "strictatime", 79 "suid", 80 "unbindable", 81 }; 82 83 /* 84 * Check for a common mount option that manipulates s_flags. 85 */ 86 static int vfs_parse_sb_flag(struct fs_context *fc, const char *key) 87 { 88 unsigned int token; 89 unsigned int i; 90 91 for (i = 0; i < ARRAY_SIZE(forbidden_sb_flag); i++) 92 if (strcmp(key, forbidden_sb_flag[i]) == 0) 93 return -EINVAL; 94 95 token = lookup_constant(common_set_sb_flag, key, 0); 96 if (token) { 97 fc->sb_flags |= token; 98 fc->sb_flags_mask |= token; 99 return 0; 100 } 101 102 token = lookup_constant(common_clear_sb_flag, key, 0); 103 if (token) { 104 fc->sb_flags &= ~token; 105 fc->sb_flags_mask |= token; 106 return 0; 107 } 108 109 return -ENOPARAM; 110 } 111 112 /** 113 * vfs_parse_fs_param - Add a single parameter to a superblock config 114 * @fc: The filesystem context to modify 115 * @param: The parameter 116 * 117 * A single mount option in string form is applied to the filesystem context 118 * being set up. Certain standard options (for example "ro") are translated 119 * into flag bits without going to the filesystem. The active security module 120 * is allowed to observe and poach options. Any other options are passed over 121 * to the filesystem to parse. 122 * 123 * This may be called multiple times for a context. 124 * 125 * Returns 0 on success and a negative error code on failure. In the event of 126 * failure, supplementary error information may have been set. 127 */ 128 int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param) 129 { 130 int ret; 131 132 if (!param->key) 133 return invalf(fc, "Unnamed parameter\n"); 134 135 ret = vfs_parse_sb_flag(fc, param->key); 136 if (ret != -ENOPARAM) 137 return ret; 138 139 ret = security_fs_context_parse_param(fc, param); 140 if (ret != -ENOPARAM) 141 /* Param belongs to the LSM or is disallowed by the LSM; so 142 * don't pass to the FS. 143 */ 144 return ret; 145 146 if (fc->ops->parse_param) { 147 ret = fc->ops->parse_param(fc, param); 148 if (ret != -ENOPARAM) 149 return ret; 150 } 151 152 /* If the filesystem doesn't take any arguments, give it the 153 * default handling of source. 154 */ 155 if (strcmp(param->key, "source") == 0) { 156 if (param->type != fs_value_is_string) 157 return invalf(fc, "VFS: Non-string source"); 158 if (fc->source) 159 return invalf(fc, "VFS: Multiple sources"); 160 fc->source = param->string; 161 param->string = NULL; 162 return 0; 163 } 164 165 return invalf(fc, "%s: Unknown parameter '%s'", 166 fc->fs_type->name, param->key); 167 } 168 EXPORT_SYMBOL(vfs_parse_fs_param); 169 170 /** 171 * vfs_parse_fs_string - Convenience function to just parse a string. 172 */ 173 int vfs_parse_fs_string(struct fs_context *fc, const char *key, 174 const char *value, size_t v_size) 175 { 176 int ret; 177 178 struct fs_parameter param = { 179 .key = key, 180 .type = fs_value_is_string, 181 .size = v_size, 182 }; 183 184 if (v_size > 0) { 185 param.string = kmemdup_nul(value, v_size, GFP_KERNEL); 186 if (!param.string) 187 return -ENOMEM; 188 } 189 190 ret = vfs_parse_fs_param(fc, ¶m); 191 kfree(param.string); 192 return ret; 193 } 194 EXPORT_SYMBOL(vfs_parse_fs_string); 195 196 /** 197 * generic_parse_monolithic - Parse key[=val][,key[=val]]* mount data 198 * @ctx: The superblock configuration to fill in. 199 * @data: The data to parse 200 * 201 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be 202 * called from the ->monolithic_mount_data() fs_context operation. 203 * 204 * Returns 0 on success or the error returned by the ->parse_option() fs_context 205 * operation on failure. 206 */ 207 int generic_parse_monolithic(struct fs_context *fc, void *data) 208 { 209 char *options = data, *key; 210 int ret = 0; 211 212 if (!options) 213 return 0; 214 215 ret = security_sb_eat_lsm_opts(options, &fc->security); 216 if (ret) 217 return ret; 218 219 while ((key = strsep(&options, ",")) != NULL) { 220 if (*key) { 221 size_t v_len = 0; 222 char *value = strchr(key, '='); 223 224 if (value) { 225 if (value == key) 226 continue; 227 *value++ = 0; 228 v_len = strlen(value); 229 } 230 ret = vfs_parse_fs_string(fc, key, value, v_len); 231 if (ret < 0) 232 break; 233 } 234 } 235 236 return ret; 237 } 238 EXPORT_SYMBOL(generic_parse_monolithic); 239 240 /** 241 * alloc_fs_context - Create a filesystem context. 242 * @fs_type: The filesystem type. 243 * @reference: The dentry from which this one derives (or NULL) 244 * @sb_flags: Filesystem/superblock flags (SB_*) 245 * @sb_flags_mask: Applicable members of @sb_flags 246 * @purpose: The purpose that this configuration shall be used for. 247 * 248 * Open a filesystem and create a mount context. The mount context is 249 * initialised with the supplied flags and, if a submount/automount from 250 * another superblock (referred to by @reference) is supplied, may have 251 * parameters such as namespaces copied across from that superblock. 252 */ 253 static struct fs_context *alloc_fs_context(struct file_system_type *fs_type, 254 struct dentry *reference, 255 unsigned int sb_flags, 256 unsigned int sb_flags_mask, 257 enum fs_context_purpose purpose) 258 { 259 int (*init_fs_context)(struct fs_context *); 260 struct fs_context *fc; 261 int ret = -ENOMEM; 262 263 fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL); 264 if (!fc) 265 return ERR_PTR(-ENOMEM); 266 267 fc->purpose = purpose; 268 fc->sb_flags = sb_flags; 269 fc->sb_flags_mask = sb_flags_mask; 270 fc->fs_type = get_filesystem(fs_type); 271 fc->cred = get_current_cred(); 272 fc->net_ns = get_net(current->nsproxy->net_ns); 273 274 switch (purpose) { 275 case FS_CONTEXT_FOR_MOUNT: 276 fc->user_ns = get_user_ns(fc->cred->user_ns); 277 break; 278 case FS_CONTEXT_FOR_SUBMOUNT: 279 fc->user_ns = get_user_ns(reference->d_sb->s_user_ns); 280 break; 281 case FS_CONTEXT_FOR_RECONFIGURE: 282 /* We don't pin any namespaces as the superblock's 283 * subscriptions cannot be changed at this point. 284 */ 285 atomic_inc(&reference->d_sb->s_active); 286 fc->root = dget(reference); 287 break; 288 } 289 290 /* TODO: Make all filesystems support this unconditionally */ 291 init_fs_context = fc->fs_type->init_fs_context; 292 if (!init_fs_context) 293 init_fs_context = legacy_init_fs_context; 294 295 ret = init_fs_context(fc); 296 if (ret < 0) 297 goto err_fc; 298 fc->need_free = true; 299 return fc; 300 301 err_fc: 302 put_fs_context(fc); 303 return ERR_PTR(ret); 304 } 305 306 struct fs_context *fs_context_for_mount(struct file_system_type *fs_type, 307 unsigned int sb_flags) 308 { 309 return alloc_fs_context(fs_type, NULL, sb_flags, 0, 310 FS_CONTEXT_FOR_MOUNT); 311 } 312 EXPORT_SYMBOL(fs_context_for_mount); 313 314 struct fs_context *fs_context_for_reconfigure(struct dentry *dentry, 315 unsigned int sb_flags, 316 unsigned int sb_flags_mask) 317 { 318 return alloc_fs_context(dentry->d_sb->s_type, dentry, sb_flags, 319 sb_flags_mask, FS_CONTEXT_FOR_RECONFIGURE); 320 } 321 EXPORT_SYMBOL(fs_context_for_reconfigure); 322 323 struct fs_context *fs_context_for_submount(struct file_system_type *type, 324 struct dentry *reference) 325 { 326 return alloc_fs_context(type, reference, 0, 0, FS_CONTEXT_FOR_SUBMOUNT); 327 } 328 EXPORT_SYMBOL(fs_context_for_submount); 329 330 void fc_drop_locked(struct fs_context *fc) 331 { 332 struct super_block *sb = fc->root->d_sb; 333 dput(fc->root); 334 fc->root = NULL; 335 deactivate_locked_super(sb); 336 } 337 338 static void legacy_fs_context_free(struct fs_context *fc); 339 340 /** 341 * vfs_dup_fc_config: Duplicate a filesystem context. 342 * @src_fc: The context to copy. 343 */ 344 struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc) 345 { 346 struct fs_context *fc; 347 int ret; 348 349 if (!src_fc->ops->dup) 350 return ERR_PTR(-EOPNOTSUPP); 351 352 fc = kmemdup(src_fc, sizeof(struct fs_context), GFP_KERNEL); 353 if (!fc) 354 return ERR_PTR(-ENOMEM); 355 356 fc->fs_private = NULL; 357 fc->s_fs_info = NULL; 358 fc->source = NULL; 359 fc->security = NULL; 360 get_filesystem(fc->fs_type); 361 get_net(fc->net_ns); 362 get_user_ns(fc->user_ns); 363 get_cred(fc->cred); 364 365 /* Can't call put until we've called ->dup */ 366 ret = fc->ops->dup(fc, src_fc); 367 if (ret < 0) 368 goto err_fc; 369 370 ret = security_fs_context_dup(fc, src_fc); 371 if (ret < 0) 372 goto err_fc; 373 return fc; 374 375 err_fc: 376 put_fs_context(fc); 377 return ERR_PTR(ret); 378 } 379 EXPORT_SYMBOL(vfs_dup_fs_context); 380 381 #ifdef CONFIG_PRINTK 382 /** 383 * logfc - Log a message to a filesystem context 384 * @fc: The filesystem context to log to. 385 * @fmt: The format of the buffer. 386 */ 387 void logfc(struct fs_context *fc, const char *fmt, ...) 388 { 389 va_list va; 390 391 va_start(va, fmt); 392 393 switch (fmt[0]) { 394 case 'w': 395 vprintk_emit(0, LOGLEVEL_WARNING, NULL, 0, fmt, va); 396 break; 397 case 'e': 398 vprintk_emit(0, LOGLEVEL_ERR, NULL, 0, fmt, va); 399 break; 400 default: 401 vprintk_emit(0, LOGLEVEL_NOTICE, NULL, 0, fmt, va); 402 break; 403 } 404 405 pr_cont("\n"); 406 va_end(va); 407 } 408 EXPORT_SYMBOL(logfc); 409 #endif 410 411 /** 412 * put_fs_context - Dispose of a superblock configuration context. 413 * @fc: The context to dispose of. 414 */ 415 void put_fs_context(struct fs_context *fc) 416 { 417 struct super_block *sb; 418 419 if (fc->root) { 420 sb = fc->root->d_sb; 421 dput(fc->root); 422 fc->root = NULL; 423 deactivate_super(sb); 424 } 425 426 if (fc->need_free && fc->ops && fc->ops->free) 427 fc->ops->free(fc); 428 429 security_free_mnt_opts(&fc->security); 430 put_net(fc->net_ns); 431 put_user_ns(fc->user_ns); 432 put_cred(fc->cred); 433 kfree(fc->subtype); 434 put_filesystem(fc->fs_type); 435 kfree(fc->source); 436 kfree(fc); 437 } 438 EXPORT_SYMBOL(put_fs_context); 439 440 /* 441 * Free the config for a filesystem that doesn't support fs_context. 442 */ 443 static void legacy_fs_context_free(struct fs_context *fc) 444 { 445 struct legacy_fs_context *ctx = fc->fs_private; 446 447 if (ctx) { 448 if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS) 449 kfree(ctx->legacy_data); 450 kfree(ctx); 451 } 452 } 453 454 /* 455 * Duplicate a legacy config. 456 */ 457 static int legacy_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) 458 { 459 struct legacy_fs_context *ctx; 460 struct legacy_fs_context *src_ctx = src_fc->fs_private; 461 462 ctx = kmemdup(src_ctx, sizeof(*src_ctx), GFP_KERNEL); 463 if (!ctx) 464 return -ENOMEM; 465 466 if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS) { 467 ctx->legacy_data = kmemdup(src_ctx->legacy_data, 468 src_ctx->data_size, GFP_KERNEL); 469 if (!ctx->legacy_data) { 470 kfree(ctx); 471 return -ENOMEM; 472 } 473 } 474 475 fc->fs_private = ctx; 476 return 0; 477 } 478 479 /* 480 * Add a parameter to a legacy config. We build up a comma-separated list of 481 * options. 482 */ 483 static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) 484 { 485 struct legacy_fs_context *ctx = fc->fs_private; 486 unsigned int size = ctx->data_size; 487 size_t len = 0; 488 489 if (strcmp(param->key, "source") == 0) { 490 if (param->type != fs_value_is_string) 491 return invalf(fc, "VFS: Legacy: Non-string source"); 492 if (fc->source) 493 return invalf(fc, "VFS: Legacy: Multiple sources"); 494 fc->source = param->string; 495 param->string = NULL; 496 return 0; 497 } 498 499 if ((fc->fs_type->fs_flags & FS_HAS_SUBTYPE) && 500 strcmp(param->key, "subtype") == 0) { 501 if (param->type != fs_value_is_string) 502 return invalf(fc, "VFS: Legacy: Non-string subtype"); 503 if (fc->subtype) 504 return invalf(fc, "VFS: Legacy: Multiple subtype"); 505 fc->subtype = param->string; 506 param->string = NULL; 507 return 0; 508 } 509 510 if (ctx->param_type == LEGACY_FS_MONOLITHIC_PARAMS) 511 return invalf(fc, "VFS: Legacy: Can't mix monolithic and individual options"); 512 513 switch (param->type) { 514 case fs_value_is_string: 515 len = 1 + param->size; 516 /* Fall through */ 517 case fs_value_is_flag: 518 len += strlen(param->key); 519 break; 520 default: 521 return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported", 522 param->key); 523 } 524 525 if (len > PAGE_SIZE - 2 - size) 526 return invalf(fc, "VFS: Legacy: Cumulative options too large"); 527 if (strchr(param->key, ',') || 528 (param->type == fs_value_is_string && 529 memchr(param->string, ',', param->size))) 530 return invalf(fc, "VFS: Legacy: Option '%s' contained comma", 531 param->key); 532 if (!ctx->legacy_data) { 533 ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL); 534 if (!ctx->legacy_data) 535 return -ENOMEM; 536 } 537 538 ctx->legacy_data[size++] = ','; 539 len = strlen(param->key); 540 memcpy(ctx->legacy_data + size, param->key, len); 541 size += len; 542 if (param->type == fs_value_is_string) { 543 ctx->legacy_data[size++] = '='; 544 memcpy(ctx->legacy_data + size, param->string, param->size); 545 size += param->size; 546 } 547 ctx->legacy_data[size] = '\0'; 548 ctx->data_size = size; 549 ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS; 550 return 0; 551 } 552 553 /* 554 * Add monolithic mount data. 555 */ 556 static int legacy_parse_monolithic(struct fs_context *fc, void *data) 557 { 558 struct legacy_fs_context *ctx = fc->fs_private; 559 560 if (ctx->param_type != LEGACY_FS_UNSET_PARAMS) { 561 pr_warn("VFS: Can't mix monolithic and individual options\n"); 562 return -EINVAL; 563 } 564 565 ctx->legacy_data = data; 566 ctx->param_type = LEGACY_FS_MONOLITHIC_PARAMS; 567 if (!ctx->legacy_data) 568 return 0; 569 570 if (fc->fs_type->fs_flags & FS_BINARY_MOUNTDATA) 571 return 0; 572 return security_sb_eat_lsm_opts(ctx->legacy_data, &fc->security); 573 } 574 575 /* 576 * Get a mountable root with the legacy mount command. 577 */ 578 static int legacy_get_tree(struct fs_context *fc) 579 { 580 struct legacy_fs_context *ctx = fc->fs_private; 581 struct super_block *sb; 582 struct dentry *root; 583 584 root = fc->fs_type->mount(fc->fs_type, fc->sb_flags, 585 fc->source, ctx->legacy_data); 586 if (IS_ERR(root)) 587 return PTR_ERR(root); 588 589 sb = root->d_sb; 590 BUG_ON(!sb); 591 592 fc->root = root; 593 return 0; 594 } 595 596 /* 597 * Handle remount. 598 */ 599 static int legacy_reconfigure(struct fs_context *fc) 600 { 601 struct legacy_fs_context *ctx = fc->fs_private; 602 struct super_block *sb = fc->root->d_sb; 603 604 if (!sb->s_op->remount_fs) 605 return 0; 606 607 return sb->s_op->remount_fs(sb, &fc->sb_flags, 608 ctx ? ctx->legacy_data : NULL); 609 } 610 611 const struct fs_context_operations legacy_fs_context_ops = { 612 .free = legacy_fs_context_free, 613 .dup = legacy_fs_context_dup, 614 .parse_param = legacy_parse_param, 615 .parse_monolithic = legacy_parse_monolithic, 616 .get_tree = legacy_get_tree, 617 .reconfigure = legacy_reconfigure, 618 }; 619 620 /* 621 * Initialise a legacy context for a filesystem that doesn't support 622 * fs_context. 623 */ 624 static int legacy_init_fs_context(struct fs_context *fc) 625 { 626 fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL); 627 if (!fc->fs_private) 628 return -ENOMEM; 629 fc->ops = &legacy_fs_context_ops; 630 return 0; 631 } 632 633 int parse_monolithic_mount_data(struct fs_context *fc, void *data) 634 { 635 int (*monolithic_mount_data)(struct fs_context *, void *); 636 637 monolithic_mount_data = fc->ops->parse_monolithic; 638 if (!monolithic_mount_data) 639 monolithic_mount_data = generic_parse_monolithic; 640 641 return monolithic_mount_data(fc, data); 642 } 643