diff options
Diffstat (limited to 'kernel/bpf/inode.c')
-rw-r--r-- | kernel/bpf/inode.c | 92 |
1 files changed, 58 insertions, 34 deletions
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index cc0d0cf114e3..a70f7209cda3 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c | |||
@@ -14,8 +14,9 @@ | |||
14 | #include <linux/mount.h> | 14 | #include <linux/mount.h> |
15 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/fs_context.h> | ||
18 | #include <linux/fs_parser.h> | ||
17 | #include <linux/kdev_t.h> | 19 | #include <linux/kdev_t.h> |
18 | #include <linux/parser.h> | ||
19 | #include <linux/filter.h> | 20 | #include <linux/filter.h> |
20 | #include <linux/bpf.h> | 21 | #include <linux/bpf.h> |
21 | #include <linux/bpf_trace.h> | 22 | #include <linux/bpf_trace.h> |
@@ -583,58 +584,52 @@ static const struct super_operations bpf_super_ops = { | |||
583 | 584 | ||
584 | enum { | 585 | enum { |
585 | OPT_MODE, | 586 | OPT_MODE, |
586 | OPT_ERR, | ||
587 | }; | 587 | }; |
588 | 588 | ||
589 | static const match_table_t bpf_mount_tokens = { | 589 | static const struct fs_parameter_spec bpf_param_specs[] = { |
590 | { OPT_MODE, "mode=%o" }, | 590 | fsparam_u32oct ("mode", OPT_MODE), |
591 | { OPT_ERR, NULL }, | 591 | {} |
592 | }; | ||
593 | |||
594 | static const struct fs_parameter_description bpf_fs_parameters = { | ||
595 | .name = "bpf", | ||
596 | .specs = bpf_param_specs, | ||
592 | }; | 597 | }; |
593 | 598 | ||
594 | struct bpf_mount_opts { | 599 | struct bpf_mount_opts { |
595 | umode_t mode; | 600 | umode_t mode; |
596 | }; | 601 | }; |
597 | 602 | ||
598 | static int bpf_parse_options(char *data, struct bpf_mount_opts *opts) | 603 | static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param) |
599 | { | 604 | { |
600 | substring_t args[MAX_OPT_ARGS]; | 605 | struct bpf_mount_opts *opts = fc->fs_private; |
601 | int option, token; | 606 | struct fs_parse_result result; |
602 | char *ptr; | 607 | int opt; |
603 | 608 | ||
604 | opts->mode = S_IRWXUGO; | 609 | opt = fs_parse(fc, &bpf_fs_parameters, param, &result); |
605 | 610 | if (opt < 0) | |
606 | while ((ptr = strsep(&data, ",")) != NULL) { | ||
607 | if (!*ptr) | ||
608 | continue; | ||
609 | |||
610 | token = match_token(ptr, bpf_mount_tokens, args); | ||
611 | switch (token) { | ||
612 | case OPT_MODE: | ||
613 | if (match_octal(&args[0], &option)) | ||
614 | return -EINVAL; | ||
615 | opts->mode = option & S_IALLUGO; | ||
616 | break; | ||
617 | /* We might like to report bad mount options here, but | 611 | /* We might like to report bad mount options here, but |
618 | * traditionally we've ignored all mount options, so we'd | 612 | * traditionally we've ignored all mount options, so we'd |
619 | * better continue to ignore non-existing options for bpf. | 613 | * better continue to ignore non-existing options for bpf. |
620 | */ | 614 | */ |
621 | } | 615 | return opt == -ENOPARAM ? 0 : opt; |
616 | |||
617 | switch (opt) { | ||
618 | case OPT_MODE: | ||
619 | opts->mode = result.uint_32 & S_IALLUGO; | ||
620 | break; | ||
622 | } | 621 | } |
623 | 622 | ||
624 | return 0; | 623 | return 0; |
625 | } | 624 | } |
626 | 625 | ||
627 | static int bpf_fill_super(struct super_block *sb, void *data, int silent) | 626 | static int bpf_fill_super(struct super_block *sb, struct fs_context *fc) |
628 | { | 627 | { |
629 | static const struct tree_descr bpf_rfiles[] = { { "" } }; | 628 | static const struct tree_descr bpf_rfiles[] = { { "" } }; |
630 | struct bpf_mount_opts opts; | 629 | struct bpf_mount_opts *opts = fc->fs_private; |
631 | struct inode *inode; | 630 | struct inode *inode; |
632 | int ret; | 631 | int ret; |
633 | 632 | ||
634 | ret = bpf_parse_options(data, &opts); | ||
635 | if (ret) | ||
636 | return ret; | ||
637 | |||
638 | ret = simple_fill_super(sb, BPF_FS_MAGIC, bpf_rfiles); | 633 | ret = simple_fill_super(sb, BPF_FS_MAGIC, bpf_rfiles); |
639 | if (ret) | 634 | if (ret) |
640 | return ret; | 635 | return ret; |
@@ -644,21 +639,50 @@ static int bpf_fill_super(struct super_block *sb, void *data, int silent) | |||
644 | inode = sb->s_root->d_inode; | 639 | inode = sb->s_root->d_inode; |
645 | inode->i_op = &bpf_dir_iops; | 640 | inode->i_op = &bpf_dir_iops; |
646 | inode->i_mode &= ~S_IALLUGO; | 641 | inode->i_mode &= ~S_IALLUGO; |
647 | inode->i_mode |= S_ISVTX | opts.mode; | 642 | inode->i_mode |= S_ISVTX | opts->mode; |
648 | 643 | ||
649 | return 0; | 644 | return 0; |
650 | } | 645 | } |
651 | 646 | ||
652 | static struct dentry *bpf_mount(struct file_system_type *type, int flags, | 647 | static int bpf_get_tree(struct fs_context *fc) |
653 | const char *dev_name, void *data) | 648 | { |
649 | return get_tree_nodev(fc, bpf_fill_super); | ||
650 | } | ||
651 | |||
652 | static void bpf_free_fc(struct fs_context *fc) | ||
654 | { | 653 | { |
655 | return mount_nodev(type, flags, data, bpf_fill_super); | 654 | kfree(fc->fs_private); |
655 | } | ||
656 | |||
657 | static const struct fs_context_operations bpf_context_ops = { | ||
658 | .free = bpf_free_fc, | ||
659 | .parse_param = bpf_parse_param, | ||
660 | .get_tree = bpf_get_tree, | ||
661 | }; | ||
662 | |||
663 | /* | ||
664 | * Set up the filesystem mount context. | ||
665 | */ | ||
666 | static int bpf_init_fs_context(struct fs_context *fc) | ||
667 | { | ||
668 | struct bpf_mount_opts *opts; | ||
669 | |||
670 | opts = kzalloc(sizeof(struct bpf_mount_opts), GFP_KERNEL); | ||
671 | if (!opts) | ||
672 | return -ENOMEM; | ||
673 | |||
674 | opts->mode = S_IRWXUGO; | ||
675 | |||
676 | fc->fs_private = opts; | ||
677 | fc->ops = &bpf_context_ops; | ||
678 | return 0; | ||
656 | } | 679 | } |
657 | 680 | ||
658 | static struct file_system_type bpf_fs_type = { | 681 | static struct file_system_type bpf_fs_type = { |
659 | .owner = THIS_MODULE, | 682 | .owner = THIS_MODULE, |
660 | .name = "bpf", | 683 | .name = "bpf", |
661 | .mount = bpf_mount, | 684 | .init_fs_context = bpf_init_fs_context, |
685 | .parameters = &bpf_fs_parameters, | ||
662 | .kill_sb = kill_litter_super, | 686 | .kill_sb = kill_litter_super, |
663 | }; | 687 | }; |
664 | 688 | ||