diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-24 15:33:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-24 15:33:34 -0400 |
commit | 0b36c9eed232760fbf51921818f48b3699f1f1ca (patch) | |
tree | 1392ebcd076e87f7c80cd93e29db7acbee542071 /kernel/bpf/inode.c | |
parent | 722e6f500ac72d0d43955710738a24fd957607a4 (diff) | |
parent | 1f52aa08d12f8d359e71b4bfd73ca9d5d668e4da (diff) |
Merge branch 'work.mount3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more mount API conversions from Al Viro:
"Assorted conversions of options parsing to new API.
gfs2 is probably the most serious one here; the rest is trivial stuff.
Other things in what used to be #work.mount are going to wait for the
next cycle (and preferably go via git trees of the filesystems
involved)"
* 'work.mount3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
gfs2: Convert gfs2 to fs_context
vfs: Convert spufs to use the new mount API
vfs: Convert hypfs to use the new mount API
hypfs: Fix error number left in struct pointer member
vfs: Convert functionfs to use the new mount API
vfs: Convert bpf to use the new mount API
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 | ||