aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorVivek Trivedi <t.vivek@samsung.com>2015-06-22 06:06:06 -0400
committerCasey Schaufler <casey@schaufler-ca.com>2015-07-22 15:31:28 -0400
commit3bf2789cad9e6573dc19a6c3d123c2c049f2d90f (patch)
tree35d1609228bbaee7231478f0ee7538bbb39420e1 /security/smack
parentfe6c59dc17908effd4e2caa666795b9ad984005b (diff)
smack: allow mount opts setting over filesystems with binary mount data
Add support for setting smack mount labels(using smackfsdef, smackfsroot, smackfshat, smackfsfloor, smackfstransmute) for filesystems with binary mount data like NFS. To achieve this, implement sb_parse_opts_str and sb_set_mnt_opts security operations in smack LSM similar to SELinux. Signed-off-by: Vivek Trivedi <t.vivek@samsung.com> Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com> Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-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),