0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 #include <linux/module.h>
0011 #include <linux/fs_context.h>
0012 #include <linux/fs_parser.h>
0013 #include <linux/fs.h>
0014 #include <linux/mount.h>
0015 #include <linux/nsproxy.h>
0016 #include <linux/slab.h>
0017 #include <linux/magic.h>
0018 #include <linux/security.h>
0019 #include <linux/mnt_namespace.h>
0020 #include <linux/pid_namespace.h>
0021 #include <linux/user_namespace.h>
0022 #include <net/net_namespace.h>
0023 #include <asm/sections.h>
0024 #include "mount.h"
0025 #include "internal.h"
0026
0027 enum legacy_fs_param {
0028 LEGACY_FS_UNSET_PARAMS,
0029 LEGACY_FS_MONOLITHIC_PARAMS,
0030 LEGACY_FS_INDIVIDUAL_PARAMS,
0031 };
0032
0033 struct legacy_fs_context {
0034 char *legacy_data;
0035 size_t data_size;
0036 enum legacy_fs_param param_type;
0037 };
0038
0039 static int legacy_init_fs_context(struct fs_context *fc);
0040
0041 static const struct constant_table common_set_sb_flag[] = {
0042 { "dirsync", SB_DIRSYNC },
0043 { "lazytime", SB_LAZYTIME },
0044 { "mand", SB_MANDLOCK },
0045 { "ro", SB_RDONLY },
0046 { "sync", SB_SYNCHRONOUS },
0047 { },
0048 };
0049
0050 static const struct constant_table common_clear_sb_flag[] = {
0051 { "async", SB_SYNCHRONOUS },
0052 { "nolazytime", SB_LAZYTIME },
0053 { "nomand", SB_MANDLOCK },
0054 { "rw", SB_RDONLY },
0055 { },
0056 };
0057
0058
0059
0060
0061 static int vfs_parse_sb_flag(struct fs_context *fc, const char *key)
0062 {
0063 unsigned int token;
0064
0065 token = lookup_constant(common_set_sb_flag, key, 0);
0066 if (token) {
0067 fc->sb_flags |= token;
0068 fc->sb_flags_mask |= token;
0069 return 0;
0070 }
0071
0072 token = lookup_constant(common_clear_sb_flag, key, 0);
0073 if (token) {
0074 fc->sb_flags &= ~token;
0075 fc->sb_flags_mask |= token;
0076 return 0;
0077 }
0078
0079 return -ENOPARAM;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 int vfs_parse_fs_param_source(struct fs_context *fc, struct fs_parameter *param)
0095 {
0096 if (strcmp(param->key, "source") != 0)
0097 return -ENOPARAM;
0098
0099 if (param->type != fs_value_is_string)
0100 return invalf(fc, "Non-string source");
0101
0102 if (fc->source)
0103 return invalf(fc, "Multiple sources");
0104
0105 fc->source = param->string;
0106 param->string = NULL;
0107 return 0;
0108 }
0109 EXPORT_SYMBOL(vfs_parse_fs_param_source);
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param)
0128 {
0129 int ret;
0130
0131 if (!param->key)
0132 return invalf(fc, "Unnamed parameter\n");
0133
0134 ret = vfs_parse_sb_flag(fc, param->key);
0135 if (ret != -ENOPARAM)
0136 return ret;
0137
0138 ret = security_fs_context_parse_param(fc, param);
0139 if (ret != -ENOPARAM)
0140
0141
0142
0143 return ret;
0144
0145 if (fc->ops->parse_param) {
0146 ret = fc->ops->parse_param(fc, param);
0147 if (ret != -ENOPARAM)
0148 return ret;
0149 }
0150
0151
0152
0153
0154 ret = vfs_parse_fs_param_source(fc, param);
0155 if (ret != -ENOPARAM)
0156 return ret;
0157
0158 return invalf(fc, "%s: Unknown parameter '%s'",
0159 fc->fs_type->name, param->key);
0160 }
0161 EXPORT_SYMBOL(vfs_parse_fs_param);
0162
0163
0164
0165
0166 int vfs_parse_fs_string(struct fs_context *fc, const char *key,
0167 const char *value, size_t v_size)
0168 {
0169 int ret;
0170
0171 struct fs_parameter param = {
0172 .key = key,
0173 .type = fs_value_is_flag,
0174 .size = v_size,
0175 };
0176
0177 if (value) {
0178 param.string = kmemdup_nul(value, v_size, GFP_KERNEL);
0179 if (!param.string)
0180 return -ENOMEM;
0181 param.type = fs_value_is_string;
0182 }
0183
0184 ret = vfs_parse_fs_param(fc, ¶m);
0185 kfree(param.string);
0186 return ret;
0187 }
0188 EXPORT_SYMBOL(vfs_parse_fs_string);
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 int generic_parse_monolithic(struct fs_context *fc, void *data)
0202 {
0203 char *options = data, *key;
0204 int ret = 0;
0205
0206 if (!options)
0207 return 0;
0208
0209 ret = security_sb_eat_lsm_opts(options, &fc->security);
0210 if (ret)
0211 return ret;
0212
0213 while ((key = strsep(&options, ",")) != NULL) {
0214 if (*key) {
0215 size_t v_len = 0;
0216 char *value = strchr(key, '=');
0217
0218 if (value) {
0219 if (value == key)
0220 continue;
0221 *value++ = 0;
0222 v_len = strlen(value);
0223 }
0224 ret = vfs_parse_fs_string(fc, key, value, v_len);
0225 if (ret < 0)
0226 break;
0227 }
0228 }
0229
0230 return ret;
0231 }
0232 EXPORT_SYMBOL(generic_parse_monolithic);
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
0248 struct dentry *reference,
0249 unsigned int sb_flags,
0250 unsigned int sb_flags_mask,
0251 enum fs_context_purpose purpose)
0252 {
0253 int (*init_fs_context)(struct fs_context *);
0254 struct fs_context *fc;
0255 int ret = -ENOMEM;
0256
0257 fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL_ACCOUNT);
0258 if (!fc)
0259 return ERR_PTR(-ENOMEM);
0260
0261 fc->purpose = purpose;
0262 fc->sb_flags = sb_flags;
0263 fc->sb_flags_mask = sb_flags_mask;
0264 fc->fs_type = get_filesystem(fs_type);
0265 fc->cred = get_current_cred();
0266 fc->net_ns = get_net(current->nsproxy->net_ns);
0267 fc->log.prefix = fs_type->name;
0268
0269 mutex_init(&fc->uapi_mutex);
0270
0271 switch (purpose) {
0272 case FS_CONTEXT_FOR_MOUNT:
0273 fc->user_ns = get_user_ns(fc->cred->user_ns);
0274 break;
0275 case FS_CONTEXT_FOR_SUBMOUNT:
0276 fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
0277 break;
0278 case FS_CONTEXT_FOR_RECONFIGURE:
0279 atomic_inc(&reference->d_sb->s_active);
0280 fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
0281 fc->root = dget(reference);
0282 break;
0283 }
0284
0285
0286 init_fs_context = fc->fs_type->init_fs_context;
0287 if (!init_fs_context)
0288 init_fs_context = legacy_init_fs_context;
0289
0290 ret = init_fs_context(fc);
0291 if (ret < 0)
0292 goto err_fc;
0293 fc->need_free = true;
0294 return fc;
0295
0296 err_fc:
0297 put_fs_context(fc);
0298 return ERR_PTR(ret);
0299 }
0300
0301 struct fs_context *fs_context_for_mount(struct file_system_type *fs_type,
0302 unsigned int sb_flags)
0303 {
0304 return alloc_fs_context(fs_type, NULL, sb_flags, 0,
0305 FS_CONTEXT_FOR_MOUNT);
0306 }
0307 EXPORT_SYMBOL(fs_context_for_mount);
0308
0309 struct fs_context *fs_context_for_reconfigure(struct dentry *dentry,
0310 unsigned int sb_flags,
0311 unsigned int sb_flags_mask)
0312 {
0313 return alloc_fs_context(dentry->d_sb->s_type, dentry, sb_flags,
0314 sb_flags_mask, FS_CONTEXT_FOR_RECONFIGURE);
0315 }
0316 EXPORT_SYMBOL(fs_context_for_reconfigure);
0317
0318 struct fs_context *fs_context_for_submount(struct file_system_type *type,
0319 struct dentry *reference)
0320 {
0321 return alloc_fs_context(type, reference, 0, 0, FS_CONTEXT_FOR_SUBMOUNT);
0322 }
0323 EXPORT_SYMBOL(fs_context_for_submount);
0324
0325 void fc_drop_locked(struct fs_context *fc)
0326 {
0327 struct super_block *sb = fc->root->d_sb;
0328 dput(fc->root);
0329 fc->root = NULL;
0330 deactivate_locked_super(sb);
0331 }
0332
0333 static void legacy_fs_context_free(struct fs_context *fc);
0334
0335
0336
0337
0338
0339 struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc)
0340 {
0341 struct fs_context *fc;
0342 int ret;
0343
0344 if (!src_fc->ops->dup)
0345 return ERR_PTR(-EOPNOTSUPP);
0346
0347 fc = kmemdup(src_fc, sizeof(struct fs_context), GFP_KERNEL);
0348 if (!fc)
0349 return ERR_PTR(-ENOMEM);
0350
0351 mutex_init(&fc->uapi_mutex);
0352
0353 fc->fs_private = NULL;
0354 fc->s_fs_info = NULL;
0355 fc->source = NULL;
0356 fc->security = NULL;
0357 get_filesystem(fc->fs_type);
0358 get_net(fc->net_ns);
0359 get_user_ns(fc->user_ns);
0360 get_cred(fc->cred);
0361 if (fc->log.log)
0362 refcount_inc(&fc->log.log->usage);
0363
0364
0365 ret = fc->ops->dup(fc, src_fc);
0366 if (ret < 0)
0367 goto err_fc;
0368
0369 ret = security_fs_context_dup(fc, src_fc);
0370 if (ret < 0)
0371 goto err_fc;
0372 return fc;
0373
0374 err_fc:
0375 put_fs_context(fc);
0376 return ERR_PTR(ret);
0377 }
0378 EXPORT_SYMBOL(vfs_dup_fs_context);
0379
0380
0381
0382
0383
0384
0385 void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...)
0386 {
0387 va_list va;
0388 struct va_format vaf = {.fmt = fmt, .va = &va};
0389
0390 va_start(va, fmt);
0391 if (!log) {
0392 switch (level) {
0393 case 'w':
0394 printk(KERN_WARNING "%s%s%pV\n", prefix ? prefix : "",
0395 prefix ? ": " : "", &vaf);
0396 break;
0397 case 'e':
0398 printk(KERN_ERR "%s%s%pV\n", prefix ? prefix : "",
0399 prefix ? ": " : "", &vaf);
0400 break;
0401 default:
0402 printk(KERN_NOTICE "%s%s%pV\n", prefix ? prefix : "",
0403 prefix ? ": " : "", &vaf);
0404 break;
0405 }
0406 } else {
0407 unsigned int logsize = ARRAY_SIZE(log->buffer);
0408 u8 index;
0409 char *q = kasprintf(GFP_KERNEL, "%c %s%s%pV\n", level,
0410 prefix ? prefix : "",
0411 prefix ? ": " : "", &vaf);
0412
0413 index = log->head & (logsize - 1);
0414 BUILD_BUG_ON(sizeof(log->head) != sizeof(u8) ||
0415 sizeof(log->tail) != sizeof(u8));
0416 if ((u8)(log->head - log->tail) == logsize) {
0417
0418 if (log->need_free & (1 << index))
0419 kfree(log->buffer[index]);
0420 log->tail++;
0421 }
0422
0423 log->buffer[index] = q ? q : "OOM: Can't store error string";
0424 if (q)
0425 log->need_free |= 1 << index;
0426 else
0427 log->need_free &= ~(1 << index);
0428 log->head++;
0429 }
0430 va_end(va);
0431 }
0432 EXPORT_SYMBOL(logfc);
0433
0434
0435
0436
0437 static void put_fc_log(struct fs_context *fc)
0438 {
0439 struct fc_log *log = fc->log.log;
0440 int i;
0441
0442 if (log) {
0443 if (refcount_dec_and_test(&log->usage)) {
0444 fc->log.log = NULL;
0445 for (i = 0; i <= 7; i++)
0446 if (log->need_free & (1 << i))
0447 kfree(log->buffer[i]);
0448 kfree(log);
0449 }
0450 }
0451 }
0452
0453
0454
0455
0456
0457 void put_fs_context(struct fs_context *fc)
0458 {
0459 struct super_block *sb;
0460
0461 if (fc->root) {
0462 sb = fc->root->d_sb;
0463 dput(fc->root);
0464 fc->root = NULL;
0465 deactivate_super(sb);
0466 }
0467
0468 if (fc->need_free && fc->ops && fc->ops->free)
0469 fc->ops->free(fc);
0470
0471 security_free_mnt_opts(&fc->security);
0472 put_net(fc->net_ns);
0473 put_user_ns(fc->user_ns);
0474 put_cred(fc->cred);
0475 put_fc_log(fc);
0476 put_filesystem(fc->fs_type);
0477 kfree(fc->source);
0478 kfree(fc);
0479 }
0480 EXPORT_SYMBOL(put_fs_context);
0481
0482
0483
0484
0485 static void legacy_fs_context_free(struct fs_context *fc)
0486 {
0487 struct legacy_fs_context *ctx = fc->fs_private;
0488
0489 if (ctx) {
0490 if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS)
0491 kfree(ctx->legacy_data);
0492 kfree(ctx);
0493 }
0494 }
0495
0496
0497
0498
0499 static int legacy_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
0500 {
0501 struct legacy_fs_context *ctx;
0502 struct legacy_fs_context *src_ctx = src_fc->fs_private;
0503
0504 ctx = kmemdup(src_ctx, sizeof(*src_ctx), GFP_KERNEL);
0505 if (!ctx)
0506 return -ENOMEM;
0507
0508 if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS) {
0509 ctx->legacy_data = kmemdup(src_ctx->legacy_data,
0510 src_ctx->data_size, GFP_KERNEL);
0511 if (!ctx->legacy_data) {
0512 kfree(ctx);
0513 return -ENOMEM;
0514 }
0515 }
0516
0517 fc->fs_private = ctx;
0518 return 0;
0519 }
0520
0521
0522
0523
0524
0525 static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param)
0526 {
0527 struct legacy_fs_context *ctx = fc->fs_private;
0528 unsigned int size = ctx->data_size;
0529 size_t len = 0;
0530 int ret;
0531
0532 ret = vfs_parse_fs_param_source(fc, param);
0533 if (ret != -ENOPARAM)
0534 return ret;
0535
0536 if (ctx->param_type == LEGACY_FS_MONOLITHIC_PARAMS)
0537 return invalf(fc, "VFS: Legacy: Can't mix monolithic and individual options");
0538
0539 switch (param->type) {
0540 case fs_value_is_string:
0541 len = 1 + param->size;
0542 fallthrough;
0543 case fs_value_is_flag:
0544 len += strlen(param->key);
0545 break;
0546 default:
0547 return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported",
0548 param->key);
0549 }
0550
0551 if (size + len + 2 > PAGE_SIZE)
0552 return invalf(fc, "VFS: Legacy: Cumulative options too large");
0553 if (strchr(param->key, ',') ||
0554 (param->type == fs_value_is_string &&
0555 memchr(param->string, ',', param->size)))
0556 return invalf(fc, "VFS: Legacy: Option '%s' contained comma",
0557 param->key);
0558 if (!ctx->legacy_data) {
0559 ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
0560 if (!ctx->legacy_data)
0561 return -ENOMEM;
0562 }
0563
0564 ctx->legacy_data[size++] = ',';
0565 len = strlen(param->key);
0566 memcpy(ctx->legacy_data + size, param->key, len);
0567 size += len;
0568 if (param->type == fs_value_is_string) {
0569 ctx->legacy_data[size++] = '=';
0570 memcpy(ctx->legacy_data + size, param->string, param->size);
0571 size += param->size;
0572 }
0573 ctx->legacy_data[size] = '\0';
0574 ctx->data_size = size;
0575 ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS;
0576 return 0;
0577 }
0578
0579
0580
0581
0582 static int legacy_parse_monolithic(struct fs_context *fc, void *data)
0583 {
0584 struct legacy_fs_context *ctx = fc->fs_private;
0585
0586 if (ctx->param_type != LEGACY_FS_UNSET_PARAMS) {
0587 pr_warn("VFS: Can't mix monolithic and individual options\n");
0588 return -EINVAL;
0589 }
0590
0591 ctx->legacy_data = data;
0592 ctx->param_type = LEGACY_FS_MONOLITHIC_PARAMS;
0593 if (!ctx->legacy_data)
0594 return 0;
0595
0596 if (fc->fs_type->fs_flags & FS_BINARY_MOUNTDATA)
0597 return 0;
0598 return security_sb_eat_lsm_opts(ctx->legacy_data, &fc->security);
0599 }
0600
0601
0602
0603
0604 static int legacy_get_tree(struct fs_context *fc)
0605 {
0606 struct legacy_fs_context *ctx = fc->fs_private;
0607 struct super_block *sb;
0608 struct dentry *root;
0609
0610 root = fc->fs_type->mount(fc->fs_type, fc->sb_flags,
0611 fc->source, ctx->legacy_data);
0612 if (IS_ERR(root))
0613 return PTR_ERR(root);
0614
0615 sb = root->d_sb;
0616 BUG_ON(!sb);
0617
0618 fc->root = root;
0619 return 0;
0620 }
0621
0622
0623
0624
0625 static int legacy_reconfigure(struct fs_context *fc)
0626 {
0627 struct legacy_fs_context *ctx = fc->fs_private;
0628 struct super_block *sb = fc->root->d_sb;
0629
0630 if (!sb->s_op->remount_fs)
0631 return 0;
0632
0633 return sb->s_op->remount_fs(sb, &fc->sb_flags,
0634 ctx ? ctx->legacy_data : NULL);
0635 }
0636
0637 const struct fs_context_operations legacy_fs_context_ops = {
0638 .free = legacy_fs_context_free,
0639 .dup = legacy_fs_context_dup,
0640 .parse_param = legacy_parse_param,
0641 .parse_monolithic = legacy_parse_monolithic,
0642 .get_tree = legacy_get_tree,
0643 .reconfigure = legacy_reconfigure,
0644 };
0645
0646
0647
0648
0649
0650 static int legacy_init_fs_context(struct fs_context *fc)
0651 {
0652 fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL_ACCOUNT);
0653 if (!fc->fs_private)
0654 return -ENOMEM;
0655 fc->ops = &legacy_fs_context_ops;
0656 return 0;
0657 }
0658
0659 int parse_monolithic_mount_data(struct fs_context *fc, void *data)
0660 {
0661 int (*monolithic_mount_data)(struct fs_context *, void *);
0662
0663 monolithic_mount_data = fc->ops->parse_monolithic;
0664 if (!monolithic_mount_data)
0665 monolithic_mount_data = generic_parse_monolithic;
0666
0667 return monolithic_mount_data(fc, data);
0668 }
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683 void vfs_clean_context(struct fs_context *fc)
0684 {
0685 if (fc->need_free && fc->ops && fc->ops->free)
0686 fc->ops->free(fc);
0687 fc->need_free = false;
0688 fc->fs_private = NULL;
0689 fc->s_fs_info = NULL;
0690 fc->sb_flags = 0;
0691 security_free_mnt_opts(&fc->security);
0692 kfree(fc->source);
0693 fc->source = NULL;
0694
0695 fc->purpose = FS_CONTEXT_FOR_RECONFIGURE;
0696 fc->phase = FS_CONTEXT_AWAITING_RECONF;
0697 }
0698
0699 int finish_clean_context(struct fs_context *fc)
0700 {
0701 int error;
0702
0703 if (fc->phase != FS_CONTEXT_AWAITING_RECONF)
0704 return 0;
0705
0706 if (fc->fs_type->init_fs_context)
0707 error = fc->fs_type->init_fs_context(fc);
0708 else
0709 error = legacy_init_fs_context(fc);
0710 if (unlikely(error)) {
0711 fc->phase = FS_CONTEXT_FAILED;
0712 return error;
0713 }
0714 fc->need_free = true;
0715 fc->phase = FS_CONTEXT_RECONF_PARAMS;
0716 return 0;
0717 }