summaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-01-05 16:25:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-05 16:25:58 -0500
commit505b050fdf42097883b2d37b8e796e1f11dbef50 (patch)
tree21f5b43505a5771d13533ac675c785a9bf480fdc /security/smack
parent9b286efeb5eb5aaa2712873fc1f928b2f879dbde (diff)
parent718c43038f287e843c2f63d946977de90014cb11 (diff)
Merge branch 'mount.part1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs mount API prep from Al Viro: "Mount API prereqs. Mostly that's LSM mount options cleanups. There are several minor fixes in there, but nothing earth-shattering (leaks on failure exits, mostly)" * 'mount.part1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (27 commits) mount_fs: suppress MAC on MS_SUBMOUNT as well as MS_KERNMOUNT smack: rewrite smack_sb_eat_lsm_opts() smack: get rid of match_token() smack: take the guts of smack_parse_opts_str() into a new helper LSM: new method: ->sb_add_mnt_opt() selinux: rewrite selinux_sb_eat_lsm_opts() selinux: regularize Opt_... names a bit selinux: switch away from match_token() selinux: new helper - selinux_add_opt() LSM: bury struct security_mnt_opts smack: switch to private smack_mnt_opts selinux: switch to private struct selinux_mnt_opts LSM: hide struct security_mnt_opts from any generic code selinux: kill selinux_sb_get_mnt_opts() LSM: turn sb_eat_lsm_opts() into a method nfs_remount(): don't leak, don't ignore LSM options quietly btrfs: sanitize security_mnt_opts use selinux; don't open-code a loop in sb_finish_set_opts() LSM: split ->sb_set_mnt_opts() out of ->sb_kern_mount() new helper: security_sb_eat_lsm_opts() ...
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack_lsm.c359
1 files changed, 137 insertions, 222 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cd720c06b78c..430d4f35e55c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -59,14 +59,31 @@ static LIST_HEAD(smk_ipv6_port_list);
59static struct kmem_cache *smack_inode_cache; 59static struct kmem_cache *smack_inode_cache;
60int smack_enabled; 60int smack_enabled;
61 61
62static const match_table_t smk_mount_tokens = { 62#define A(s) {"smack"#s, sizeof("smack"#s) - 1, Opt_##s}
63 {Opt_fsdefault, SMK_FSDEFAULT "%s"}, 63static struct {
64 {Opt_fsfloor, SMK_FSFLOOR "%s"}, 64 const char *name;
65 {Opt_fshat, SMK_FSHAT "%s"}, 65 int len;
66 {Opt_fsroot, SMK_FSROOT "%s"}, 66 int opt;
67 {Opt_fstransmute, SMK_FSTRANS "%s"}, 67} smk_mount_opts[] = {
68 {Opt_error, NULL}, 68 A(fsdefault), A(fsfloor), A(fshat), A(fsroot), A(fstransmute)
69}; 69};
70#undef A
71
72static int match_opt_prefix(char *s, int l, char **arg)
73{
74 int i;
75
76 for (i = 0; i < ARRAY_SIZE(smk_mount_opts); i++) {
77 size_t len = smk_mount_opts[i].len;
78 if (len > l || memcmp(s, smk_mount_opts[i].name, len))
79 continue;
80 if (len == l || s[len] != '=')
81 continue;
82 *arg = s + len + 1;
83 return smk_mount_opts[i].opt;
84 }
85 return Opt_error;
86}
70 87
71#ifdef CONFIG_SECURITY_SMACK_BRINGUP 88#ifdef CONFIG_SECURITY_SMACK_BRINGUP
72static char *smk_bu_mess[] = { 89static char *smk_bu_mess[] = {
@@ -567,175 +584,110 @@ static void smack_sb_free_security(struct super_block *sb)
567 sb->s_security = NULL; 584 sb->s_security = NULL;
568} 585}
569 586
570/** 587struct smack_mnt_opts {
571 * smack_sb_copy_data - copy mount options data for processing 588 const char *fsdefault, *fsfloor, *fshat, *fsroot, *fstransmute;
572 * @orig: where to start 589};
573 * @smackopts: mount options string
574 *
575 * Returns 0 on success or -ENOMEM on error.
576 *
577 * Copy the Smack specific mount options out of the mount
578 * options list.
579 */
580static int smack_sb_copy_data(char *orig, char *smackopts)
581{
582 char *cp, *commap, *otheropts, *dp;
583
584 otheropts = (char *)get_zeroed_page(GFP_KERNEL);
585 if (otheropts == NULL)
586 return -ENOMEM;
587 590
588 for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) { 591static void smack_free_mnt_opts(void *mnt_opts)
589 if (strstr(cp, SMK_FSDEFAULT) == cp) 592{
590 dp = smackopts; 593 struct smack_mnt_opts *opts = mnt_opts;
591 else if (strstr(cp, SMK_FSFLOOR) == cp) 594 kfree(opts->fsdefault);
592 dp = smackopts; 595 kfree(opts->fsfloor);
593 else if (strstr(cp, SMK_FSHAT) == cp) 596 kfree(opts->fshat);
594 dp = smackopts; 597 kfree(opts->fsroot);
595 else if (strstr(cp, SMK_FSROOT) == cp) 598 kfree(opts->fstransmute);
596 dp = smackopts; 599 kfree(opts);
597 else if (strstr(cp, SMK_FSTRANS) == cp) 600}
598 dp = smackopts;
599 else
600 dp = otheropts;
601 601
602 commap = strchr(cp, ','); 602static int smack_add_opt(int token, const char *s, void **mnt_opts)
603 if (commap != NULL) 603{
604 *commap = '\0'; 604 struct smack_mnt_opts *opts = *mnt_opts;
605 605
606 if (*dp != '\0') 606 if (!opts) {
607 strcat(dp, ","); 607 opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
608 strcat(dp, cp); 608 if (!opts)
609 return -ENOMEM;
610 *mnt_opts = opts;
609 } 611 }
612 if (!s)
613 return -ENOMEM;
610 614
611 strcpy(orig, otheropts); 615 switch (token) {
612 free_page((unsigned long)otheropts); 616 case Opt_fsdefault:
613 617 if (opts->fsdefault)
618 goto out_opt_err;
619 opts->fsdefault = s;
620 break;
621 case Opt_fsfloor:
622 if (opts->fsfloor)
623 goto out_opt_err;
624 opts->fsfloor = s;
625 break;
626 case Opt_fshat:
627 if (opts->fshat)
628 goto out_opt_err;
629 opts->fshat = s;
630 break;
631 case Opt_fsroot:
632 if (opts->fsroot)
633 goto out_opt_err;
634 opts->fsroot = s;
635 break;
636 case Opt_fstransmute:
637 if (opts->fstransmute)
638 goto out_opt_err;
639 opts->fstransmute = s;
640 break;
641 }
614 return 0; 642 return 0;
643
644out_opt_err:
645 pr_warn("Smack: duplicate mount options\n");
646 return -EINVAL;
615} 647}
616 648
617/** 649static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
618 * smack_parse_opts_str - parse Smack specific mount options
619 * @options: mount options string
620 * @opts: where to store converted mount opts
621 *
622 * Returns 0 on success or -ENOMEM on error.
623 *
624 * converts Smack specific mount options to generic security option format
625 */
626static int smack_parse_opts_str(char *options,
627 struct security_mnt_opts *opts)
628{ 650{
629 char *p; 651 char *from = options, *to = options;
630 char *fsdefault = NULL; 652 bool first = true;
631 char *fsfloor = NULL;
632 char *fshat = NULL;
633 char *fsroot = NULL;
634 char *fstransmute = NULL;
635 int rc = -ENOMEM;
636 int num_mnt_opts = 0;
637 int token;
638
639 opts->num_mnt_opts = 0;
640
641 if (!options)
642 return 0;
643
644 while ((p = strsep(&options, ",")) != NULL) {
645 substring_t args[MAX_OPT_ARGS];
646 653
647 if (!*p) 654 while (1) {
648 continue; 655 char *next = strchr(from, ',');
649 656 int token, len, rc;
650 token = match_token(p, smk_mount_tokens, args); 657 char *arg = NULL;
651 658
652 switch (token) { 659 if (next)
653 case Opt_fsdefault: 660 len = next - from;
654 if (fsdefault) 661 else
655 goto out_opt_err; 662 len = strlen(from);
656 fsdefault = match_strdup(&args[0]); 663
657 if (!fsdefault) 664 token = match_opt_prefix(from, len, &arg);
658 goto out_err; 665 if (token != Opt_error) {
659 break; 666 arg = kmemdup_nul(arg, from + len - arg, GFP_KERNEL);
660 case Opt_fsfloor: 667 rc = smack_add_opt(token, arg, mnt_opts);
661 if (fsfloor) 668 if (unlikely(rc)) {
662 goto out_opt_err; 669 kfree(arg);
663 fsfloor = match_strdup(&args[0]); 670 if (*mnt_opts)
664 if (!fsfloor) 671 smack_free_mnt_opts(*mnt_opts);
665 goto out_err; 672 *mnt_opts = NULL;
666 break; 673 return rc;
667 case Opt_fshat: 674 }
668 if (fshat) 675 } else {
669 goto out_opt_err; 676 if (!first) { // copy with preceding comma
670 fshat = match_strdup(&args[0]); 677 from--;
671 if (!fshat) 678 len++;
672 goto out_err; 679 }
673 break; 680 if (to != from)
674 case Opt_fsroot: 681 memmove(to, from, len);
675 if (fsroot) 682 to += len;
676 goto out_opt_err; 683 first = false;
677 fsroot = match_strdup(&args[0]);
678 if (!fsroot)
679 goto out_err;
680 break;
681 case Opt_fstransmute:
682 if (fstransmute)
683 goto out_opt_err;
684 fstransmute = match_strdup(&args[0]);
685 if (!fstransmute)
686 goto out_err;
687 break;
688 default:
689 rc = -EINVAL;
690 pr_warn("Smack: unknown mount option\n");
691 goto out_err;
692 } 684 }
685 if (!from[len])
686 break;
687 from += len + 1;
693 } 688 }
694 689 *to = '\0';
695 opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_KERNEL);
696 if (!opts->mnt_opts)
697 goto out_err;
698
699 opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int),
700 GFP_KERNEL);
701 if (!opts->mnt_opts_flags)
702 goto out_err;
703
704 if (fsdefault) {
705 opts->mnt_opts[num_mnt_opts] = fsdefault;
706 opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT;
707 }
708 if (fsfloor) {
709 opts->mnt_opts[num_mnt_opts] = fsfloor;
710 opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT;
711 }
712 if (fshat) {
713 opts->mnt_opts[num_mnt_opts] = fshat;
714 opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT;
715 }
716 if (fsroot) {
717 opts->mnt_opts[num_mnt_opts] = fsroot;
718 opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT;
719 }
720 if (fstransmute) {
721 opts->mnt_opts[num_mnt_opts] = fstransmute;
722 opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT;
723 }
724
725 opts->num_mnt_opts = num_mnt_opts;
726 return 0; 690 return 0;
727
728out_opt_err:
729 rc = -EINVAL;
730 pr_warn("Smack: duplicate mount options\n");
731
732out_err:
733 kfree(fsdefault);
734 kfree(fsfloor);
735 kfree(fshat);
736 kfree(fsroot);
737 kfree(fstransmute);
738 return rc;
739} 691}
740 692
741/** 693/**
@@ -751,7 +703,7 @@ out_err:
751 * labels. 703 * labels.
752 */ 704 */
753static int smack_set_mnt_opts(struct super_block *sb, 705static int smack_set_mnt_opts(struct super_block *sb,
754 struct security_mnt_opts *opts, 706 void *mnt_opts,
755 unsigned long kern_flags, 707 unsigned long kern_flags,
756 unsigned long *set_kern_flags) 708 unsigned long *set_kern_flags)
757{ 709{
@@ -760,9 +712,8 @@ static int smack_set_mnt_opts(struct super_block *sb,
760 struct superblock_smack *sp = sb->s_security; 712 struct superblock_smack *sp = sb->s_security;
761 struct inode_smack *isp; 713 struct inode_smack *isp;
762 struct smack_known *skp; 714 struct smack_known *skp;
763 int i; 715 struct smack_mnt_opts *opts = mnt_opts;
764 int num_opts = opts->num_mnt_opts; 716 bool transmute = false;
765 int transmute = 0;
766 717
767 if (sp->smk_flags & SMK_SB_INITIALIZED) 718 if (sp->smk_flags & SMK_SB_INITIALIZED)
768 return 0; 719 return 0;
@@ -771,7 +722,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
771 /* 722 /*
772 * Unprivileged mounts don't get to specify Smack values. 723 * Unprivileged mounts don't get to specify Smack values.
773 */ 724 */
774 if (num_opts) 725 if (opts)
775 return -EPERM; 726 return -EPERM;
776 /* 727 /*
777 * Unprivileged mounts get root and default from the caller. 728 * Unprivileged mounts get root and default from the caller.
@@ -787,48 +738,44 @@ static int smack_set_mnt_opts(struct super_block *sb,
787 if (sb->s_user_ns != &init_user_ns && 738 if (sb->s_user_ns != &init_user_ns &&
788 sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC && 739 sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC &&
789 sb->s_magic != RAMFS_MAGIC) { 740 sb->s_magic != RAMFS_MAGIC) {
790 transmute = 1; 741 transmute = true;
791 sp->smk_flags |= SMK_SB_UNTRUSTED; 742 sp->smk_flags |= SMK_SB_UNTRUSTED;
792 } 743 }
793 } 744 }
794 745
795 sp->smk_flags |= SMK_SB_INITIALIZED; 746 sp->smk_flags |= SMK_SB_INITIALIZED;
796 747
797 for (i = 0; i < num_opts; i++) { 748 if (opts) {
798 switch (opts->mnt_opts_flags[i]) { 749 if (opts->fsdefault) {
799 case FSDEFAULT_MNT: 750 skp = smk_import_entry(opts->fsdefault, 0);
800 skp = smk_import_entry(opts->mnt_opts[i], 0);
801 if (IS_ERR(skp)) 751 if (IS_ERR(skp))
802 return PTR_ERR(skp); 752 return PTR_ERR(skp);
803 sp->smk_default = skp; 753 sp->smk_default = skp;
804 break; 754 }
805 case FSFLOOR_MNT: 755 if (opts->fsfloor) {
806 skp = smk_import_entry(opts->mnt_opts[i], 0); 756 skp = smk_import_entry(opts->fsfloor, 0);
807 if (IS_ERR(skp)) 757 if (IS_ERR(skp))
808 return PTR_ERR(skp); 758 return PTR_ERR(skp);
809 sp->smk_floor = skp; 759 sp->smk_floor = skp;
810 break; 760 }
811 case FSHAT_MNT: 761 if (opts->fshat) {
812 skp = smk_import_entry(opts->mnt_opts[i], 0); 762 skp = smk_import_entry(opts->fshat, 0);
813 if (IS_ERR(skp)) 763 if (IS_ERR(skp))
814 return PTR_ERR(skp); 764 return PTR_ERR(skp);
815 sp->smk_hat = skp; 765 sp->smk_hat = skp;
816 break; 766 }
817 case FSROOT_MNT: 767 if (opts->fsroot) {
818 skp = smk_import_entry(opts->mnt_opts[i], 0); 768 skp = smk_import_entry(opts->fsroot, 0);
819 if (IS_ERR(skp)) 769 if (IS_ERR(skp))
820 return PTR_ERR(skp); 770 return PTR_ERR(skp);
821 sp->smk_root = skp; 771 sp->smk_root = skp;
822 break; 772 }
823 case FSTRANS_MNT: 773 if (opts->fstransmute) {
824 skp = smk_import_entry(opts->mnt_opts[i], 0); 774 skp = smk_import_entry(opts->fstransmute, 0);
825 if (IS_ERR(skp)) 775 if (IS_ERR(skp))
826 return PTR_ERR(skp); 776 return PTR_ERR(skp);
827 sp->smk_root = skp; 777 sp->smk_root = skp;
828 transmute = 1; 778 transmute = true;
829 break;
830 default:
831 break;
832 } 779 }
833 } 780 }
834 781
@@ -851,37 +798,6 @@ static int smack_set_mnt_opts(struct super_block *sb,
851} 798}
852 799
853/** 800/**
854 * smack_sb_kern_mount - Smack specific mount processing
855 * @sb: the file system superblock
856 * @flags: the mount flags
857 * @data: the smack mount options
858 *
859 * Returns 0 on success, an error code on failure
860 */
861static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
862{
863 int rc = 0;
864 char *options = data;
865 struct security_mnt_opts opts;
866
867 security_init_mnt_opts(&opts);
868
869 if (!options)
870 goto out;
871
872 rc = smack_parse_opts_str(options, &opts);
873 if (rc)
874 goto out_err;
875
876out:
877 rc = smack_set_mnt_opts(sb, &opts, 0, NULL);
878
879out_err:
880 security_free_mnt_opts(&opts);
881 return rc;
882}
883
884/**
885 * smack_sb_statfs - Smack check on statfs 801 * smack_sb_statfs - Smack check on statfs
886 * @dentry: identifies the file system in question 802 * @dentry: identifies the file system in question
887 * 803 *
@@ -4673,11 +4589,10 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
4673 4589
4674 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), 4590 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
4675 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), 4591 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
4676 LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), 4592 LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts),
4677 LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), 4593 LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts),
4678 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), 4594 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
4679 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), 4595 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts),
4680 LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str),
4681 4596
4682 LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), 4597 LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
4683 4598