aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h18
-rw-r--r--security/smack/smack_lsm.c241
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
155enum {
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
68static 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
67static void smk_bu_mode(int mode, char *s) 77static 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 */
598static 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
698out_opt_err:
699 rc = -EINVAL;
700 pr_warn("Smack: duplicate mount options\n");
701
702out_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 */
587static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) 723static 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 */
820static 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
835out:
836 rc = smack_set_mnt_opts(sb, &opts, 0, NULL);
837
838out_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),