diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/smack/smack.h | 18 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 241 |
2 files changed, 219 insertions, 40 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 244e035e5a99..69ab9eb7d6d9 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -143,6 +143,24 @@ struct smack_onlycap { | |||
| 143 | struct smack_known *smk_label; | 143 | struct smack_known *smk_label; |
| 144 | }; | 144 | }; |
| 145 | 145 | ||
| 146 | /* Super block security struct flags for mount options */ | ||
| 147 | #define FSDEFAULT_MNT 0x01 | ||
| 148 | #define FSFLOOR_MNT 0x02 | ||
| 149 | #define FSHAT_MNT 0x04 | ||
| 150 | #define FSROOT_MNT 0x08 | ||
| 151 | #define FSTRANS_MNT 0x10 | ||
| 152 | |||
| 153 | #define NUM_SMK_MNT_OPTS 5 | ||
| 154 | |||
| 155 | enum { | ||
| 156 | Opt_error = -1, | ||
| 157 | Opt_fsdefault = 1, | ||
| 158 | Opt_fsfloor = 2, | ||
| 159 | Opt_fshat = 3, | ||
| 160 | Opt_fsroot = 4, | ||
| 161 | Opt_fstransmute = 5, | ||
| 162 | }; | ||
| 163 | |||
| 146 | /* | 164 | /* |
| 147 | * Mount options | 165 | * Mount options |
| 148 | */ | 166 | */ |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a143328f75eb..d962f887d3f4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/msg.h> | 41 | #include <linux/msg.h> |
| 42 | #include <linux/shm.h> | 42 | #include <linux/shm.h> |
| 43 | #include <linux/binfmts.h> | 43 | #include <linux/binfmts.h> |
| 44 | #include <linux/parser.h> | ||
| 44 | #include "smack.h" | 45 | #include "smack.h" |
| 45 | 46 | ||
| 46 | #define TRANS_TRUE "TRUE" | 47 | #define TRANS_TRUE "TRUE" |
| @@ -64,6 +65,15 @@ static char *smk_bu_mess[] = { | |||
| 64 | "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ | 65 | "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 68 | static const match_table_t tokens = { | ||
| 69 | {Opt_fsdefault, SMK_FSDEFAULT "%s"}, | ||
| 70 | {Opt_fsfloor, SMK_FSFLOOR "%s"}, | ||
| 71 | {Opt_fshat, SMK_FSHAT "%s"}, | ||
| 72 | {Opt_fsroot, SMK_FSROOT "%s"}, | ||
| 73 | {Opt_fstransmute, SMK_FSTRANS "%s"}, | ||
| 74 | {Opt_error, NULL}, | ||
| 75 | }; | ||
| 76 | |||
| 67 | static void smk_bu_mode(int mode, char *s) | 77 | static void smk_bu_mode(int mode, char *s) |
| 68 | { | 78 | { |
| 69 | int i = 0; | 79 | int i = 0; |
| @@ -577,76 +587,193 @@ static int smack_sb_copy_data(char *orig, char *smackopts) | |||
| 577 | } | 587 | } |
| 578 | 588 | ||
| 579 | /** | 589 | /** |
| 580 | * smack_sb_kern_mount - Smack specific mount processing | 590 | * smack_parse_opts_str - parse Smack specific mount options |
| 591 | * @options: mount options string | ||
| 592 | * @opts: where to store converted mount opts | ||
| 593 | * | ||
| 594 | * Returns 0 on success or -ENOMEM on error. | ||
| 595 | * | ||
| 596 | * converts Smack specific mount options to generic security option format | ||
| 597 | */ | ||
| 598 | static int smack_parse_opts_str(char *options, | ||
| 599 | struct security_mnt_opts *opts) | ||
| 600 | { | ||
| 601 | char *p; | ||
| 602 | char *fsdefault = NULL, *fsfloor = NULL; | ||
| 603 | char *fshat = NULL, *fsroot = NULL, *fstransmute = NULL; | ||
| 604 | int rc = -ENOMEM, num_mnt_opts = 0; | ||
| 605 | |||
| 606 | opts->num_mnt_opts = 0; | ||
| 607 | |||
| 608 | if (!options) | ||
| 609 | return 0; | ||
| 610 | |||
| 611 | while ((p = strsep(&options, ",")) != NULL) { | ||
| 612 | int token; | ||
| 613 | substring_t args[MAX_OPT_ARGS]; | ||
| 614 | |||
| 615 | if (!*p) | ||
| 616 | continue; | ||
| 617 | |||
| 618 | token = match_token(p, tokens, args); | ||
| 619 | |||
| 620 | switch (token) { | ||
| 621 | case Opt_fsdefault: | ||
| 622 | if (fsdefault) | ||
| 623 | goto out_opt_err; | ||
| 624 | fsdefault = match_strdup(&args[0]); | ||
| 625 | if (!fsdefault) | ||
| 626 | goto out_err; | ||
| 627 | break; | ||
| 628 | case Opt_fsfloor: | ||
| 629 | if (fsfloor) | ||
| 630 | goto out_opt_err; | ||
| 631 | fsfloor = match_strdup(&args[0]); | ||
| 632 | if (!fsfloor) | ||
| 633 | goto out_err; | ||
| 634 | break; | ||
| 635 | case Opt_fshat: | ||
| 636 | if (fshat) | ||
| 637 | goto out_opt_err; | ||
| 638 | fshat = match_strdup(&args[0]); | ||
| 639 | if (!fshat) | ||
| 640 | goto out_err; | ||
| 641 | break; | ||
| 642 | case Opt_fsroot: | ||
| 643 | if (fsroot) | ||
| 644 | goto out_opt_err; | ||
| 645 | fsroot = match_strdup(&args[0]); | ||
| 646 | if (!fsroot) | ||
| 647 | goto out_err; | ||
| 648 | break; | ||
| 649 | case Opt_fstransmute: | ||
| 650 | if (fstransmute) | ||
| 651 | goto out_opt_err; | ||
| 652 | fstransmute = match_strdup(&args[0]); | ||
| 653 | if (!fstransmute) | ||
| 654 | goto out_err; | ||
| 655 | break; | ||
| 656 | default: | ||
| 657 | rc = -EINVAL; | ||
| 658 | pr_warn("Smack: unknown mount option\n"); | ||
| 659 | goto out_err; | ||
| 660 | } | ||
| 661 | } | ||
| 662 | |||
| 663 | opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC); | ||
| 664 | if (!opts->mnt_opts) | ||
| 665 | goto out_err; | ||
| 666 | |||
| 667 | opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), | ||
| 668 | GFP_ATOMIC); | ||
| 669 | if (!opts->mnt_opts_flags) { | ||
| 670 | kfree(opts->mnt_opts); | ||
| 671 | goto out_err; | ||
| 672 | } | ||
| 673 | |||
| 674 | if (fsdefault) { | ||
| 675 | opts->mnt_opts[num_mnt_opts] = fsdefault; | ||
| 676 | opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT; | ||
| 677 | } | ||
| 678 | if (fsfloor) { | ||
| 679 | opts->mnt_opts[num_mnt_opts] = fsfloor; | ||
| 680 | opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT; | ||
| 681 | } | ||
| 682 | if (fshat) { | ||
| 683 | opts->mnt_opts[num_mnt_opts] = fshat; | ||
| 684 | opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT; | ||
| 685 | } | ||
| 686 | if (fsroot) { | ||
| 687 | opts->mnt_opts[num_mnt_opts] = fsroot; | ||
| 688 | opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT; | ||
| 689 | } | ||
| 690 | if (fstransmute) { | ||
| 691 | opts->mnt_opts[num_mnt_opts] = fstransmute; | ||
| 692 | opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT; | ||
| 693 | } | ||
| 694 | |||
| 695 | opts->num_mnt_opts = num_mnt_opts; | ||
| 696 | return 0; | ||
| 697 | |||
| 698 | out_opt_err: | ||
| 699 | rc = -EINVAL; | ||
| 700 | pr_warn("Smack: duplicate mount options\n"); | ||
| 701 | |||
| 702 | out_err: | ||
| 703 | kfree(fsdefault); | ||
| 704 | kfree(fsfloor); | ||
| 705 | kfree(fshat); | ||
| 706 | kfree(fsroot); | ||
| 707 | kfree(fstransmute); | ||
| 708 | return rc; | ||
| 709 | } | ||
| 710 | |||
| 711 | /** | ||
| 712 | * smack_set_mnt_opts - set Smack specific mount options | ||
| 581 | * @sb: the file system superblock | 713 | * @sb: the file system superblock |
| 582 | * @flags: the mount flags | 714 | * @opts: Smack mount options |
| 583 | * @data: the smack mount options | 715 | * @kern_flags: mount option from kernel space or user space |
| 716 | * @set_kern_flags: where to store converted mount opts | ||
| 584 | * | 717 | * |
| 585 | * Returns 0 on success, an error code on failure | 718 | * Returns 0 on success, an error code on failure |
| 719 | * | ||
| 720 | * Allow filesystems with binary mount data to explicitly set Smack mount | ||
| 721 | * labels. | ||
| 586 | */ | 722 | */ |
| 587 | static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | 723 | static int smack_set_mnt_opts(struct super_block *sb, |
| 724 | struct security_mnt_opts *opts, | ||
| 725 | unsigned long kern_flags, | ||
| 726 | unsigned long *set_kern_flags) | ||
| 588 | { | 727 | { |
| 589 | struct dentry *root = sb->s_root; | 728 | struct dentry *root = sb->s_root; |
| 590 | struct inode *inode = d_backing_inode(root); | 729 | struct inode *inode = d_backing_inode(root); |
| 591 | struct superblock_smack *sp = sb->s_security; | 730 | struct superblock_smack *sp = sb->s_security; |
| 592 | struct inode_smack *isp; | 731 | struct inode_smack *isp; |
| 593 | struct smack_known *skp; | 732 | struct smack_known *skp; |
| 594 | char *op; | 733 | int i; |
| 595 | char *commap; | 734 | int num_opts = opts->num_mnt_opts; |
| 596 | int transmute = 0; | 735 | int transmute = 0; |
| 597 | int specified = 0; | ||
| 598 | 736 | ||
| 599 | if (sp->smk_initialized) | 737 | if (sp->smk_initialized) |
| 600 | return 0; | 738 | return 0; |
| 601 | 739 | ||
| 602 | sp->smk_initialized = 1; | 740 | sp->smk_initialized = 1; |
| 603 | 741 | ||
| 604 | for (op = data; op != NULL; op = commap) { | 742 | for (i = 0; i < num_opts; i++) { |
| 605 | commap = strchr(op, ','); | 743 | switch (opts->mnt_opts_flags[i]) { |
| 606 | if (commap != NULL) | 744 | case FSDEFAULT_MNT: |
| 607 | *commap++ = '\0'; | 745 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
| 608 | |||
| 609 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | ||
| 610 | op += strlen(SMK_FSHAT); | ||
| 611 | skp = smk_import_entry(op, 0); | ||
| 612 | if (IS_ERR(skp)) | 746 | if (IS_ERR(skp)) |
| 613 | return PTR_ERR(skp); | 747 | return PTR_ERR(skp); |
| 614 | sp->smk_hat = skp; | 748 | sp->smk_default = skp; |
| 615 | specified = 1; | 749 | break; |
| 616 | 750 | case FSFLOOR_MNT: | |
| 617 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 751 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
| 618 | op += strlen(SMK_FSFLOOR); | ||
| 619 | skp = smk_import_entry(op, 0); | ||
| 620 | if (IS_ERR(skp)) | 752 | if (IS_ERR(skp)) |
| 621 | return PTR_ERR(skp); | 753 | return PTR_ERR(skp); |
| 622 | sp->smk_floor = skp; | 754 | sp->smk_floor = skp; |
| 623 | specified = 1; | 755 | break; |
| 624 | 756 | case FSHAT_MNT: | |
| 625 | } else if (strncmp(op, SMK_FSDEFAULT, | 757 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
| 626 | strlen(SMK_FSDEFAULT)) == 0) { | ||
| 627 | op += strlen(SMK_FSDEFAULT); | ||
| 628 | skp = smk_import_entry(op, 0); | ||
| 629 | if (IS_ERR(skp)) | 758 | if (IS_ERR(skp)) |
| 630 | return PTR_ERR(skp); | 759 | return PTR_ERR(skp); |
| 631 | sp->smk_default = skp; | 760 | sp->smk_hat = skp; |
| 632 | specified = 1; | 761 | break; |
| 633 | 762 | case FSROOT_MNT: | |
| 634 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 763 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
| 635 | op += strlen(SMK_FSROOT); | ||
| 636 | skp = smk_import_entry(op, 0); | ||
| 637 | if (IS_ERR(skp)) | 764 | if (IS_ERR(skp)) |
| 638 | return PTR_ERR(skp); | 765 | return PTR_ERR(skp); |
| 639 | sp->smk_root = skp; | 766 | sp->smk_root = skp; |
| 640 | specified = 1; | 767 | break; |
| 641 | 768 | case FSTRANS_MNT: | |
| 642 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 769 | skp = smk_import_entry(opts->mnt_opts[i], 0); |
| 643 | op += strlen(SMK_FSTRANS); | ||
| 644 | skp = smk_import_entry(op, 0); | ||
| 645 | if (IS_ERR(skp)) | 770 | if (IS_ERR(skp)) |
| 646 | return PTR_ERR(skp); | 771 | return PTR_ERR(skp); |
| 647 | sp->smk_root = skp; | 772 | sp->smk_root = skp; |
| 648 | transmute = 1; | 773 | transmute = 1; |
| 649 | specified = 1; | 774 | break; |
| 775 | default: | ||
| 776 | break; | ||
| 650 | } | 777 | } |
| 651 | } | 778 | } |
| 652 | 779 | ||
| @@ -654,7 +781,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 654 | /* | 781 | /* |
| 655 | * Unprivileged mounts don't get to specify Smack values. | 782 | * Unprivileged mounts don't get to specify Smack values. |
| 656 | */ | 783 | */ |
| 657 | if (specified) | 784 | if (num_opts) |
| 658 | return -EPERM; | 785 | return -EPERM; |
| 659 | /* | 786 | /* |
| 660 | * Unprivileged mounts get root and default from the caller. | 787 | * Unprivileged mounts get root and default from the caller. |
| @@ -663,6 +790,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 663 | sp->smk_root = skp; | 790 | sp->smk_root = skp; |
| 664 | sp->smk_default = skp; | 791 | sp->smk_default = skp; |
| 665 | } | 792 | } |
| 793 | |||
| 666 | /* | 794 | /* |
| 667 | * Initialize the root inode. | 795 | * Initialize the root inode. |
| 668 | */ | 796 | */ |
| @@ -682,6 +810,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 682 | } | 810 | } |
| 683 | 811 | ||
| 684 | /** | 812 | /** |
| 813 | * smack_sb_kern_mount - Smack specific mount processing | ||
| 814 | * @sb: the file system superblock | ||
| 815 | * @flags: the mount flags | ||
| 816 | * @data: the smack mount options | ||
| 817 | * | ||
| 818 | * Returns 0 on success, an error code on failure | ||
| 819 | */ | ||
| 820 | static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | ||
| 821 | { | ||
| 822 | int rc = 0; | ||
| 823 | char *options = data; | ||
| 824 | struct security_mnt_opts opts; | ||
| 825 | |||
| 826 | security_init_mnt_opts(&opts); | ||
| 827 | |||
| 828 | if (!options) | ||
| 829 | goto out; | ||
| 830 | |||
| 831 | rc = smack_parse_opts_str(options, &opts); | ||
| 832 | if (rc) | ||
| 833 | goto out_err; | ||
| 834 | |||
| 835 | out: | ||
| 836 | rc = smack_set_mnt_opts(sb, &opts, 0, NULL); | ||
| 837 | |||
| 838 | out_err: | ||
| 839 | security_free_mnt_opts(&opts); | ||
| 840 | return rc; | ||
| 841 | } | ||
| 842 | |||
| 843 | /** | ||
| 685 | * smack_sb_statfs - Smack check on statfs | 844 | * smack_sb_statfs - Smack check on statfs |
| 686 | * @dentry: identifies the file system in question | 845 | * @dentry: identifies the file system in question |
| 687 | * | 846 | * |
| @@ -4264,6 +4423,8 @@ struct security_hook_list smack_hooks[] = { | |||
| 4264 | LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), | 4423 | LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), |
| 4265 | LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), | 4424 | LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), |
| 4266 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), | 4425 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), |
| 4426 | LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), | ||
| 4427 | LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str), | ||
| 4267 | 4428 | ||
| 4268 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), | 4429 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), |
| 4269 | LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), | 4430 | LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), |
