Skip to content

Commit 3bf2789

Browse files
Vivek Trivedicschaufler
authored andcommitted
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 <[email protected]> Signed-off-by: Amit Sahrawat <[email protected]> Acked-by: Casey Schaufler <[email protected]>
1 parent fe6c59d commit 3bf2789

File tree

2 files changed

+219
-40
lines changed

2 files changed

+219
-40
lines changed

security/smack/smack.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,24 @@ struct smack_onlycap {
143143
struct smack_known *smk_label;
144144
};
145145

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+
146164
/*
147165
* Mount options
148166
*/

security/smack/smack_lsm.c

Lines changed: 201 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/msg.h>
4242
#include <linux/shm.h>
4343
#include <linux/binfmts.h>
44+
#include <linux/parser.h>
4445
#include "smack.h"
4546

4647
#define TRANS_TRUE "TRUE"
@@ -64,6 +65,15 @@ static char *smk_bu_mess[] = {
6465
"Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
6566
};
6667

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+
6777
static void smk_bu_mode(int mode, char *s)
6878
{
6979
int i = 0;
@@ -577,84 +587,201 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
577587
}
578588

579589
/**
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
581713
* @sb: the file system superblock
582-
* @flags: the mount flags
583-
* @data: the smack mount options
714+
* @opts: Smack mount options
715+
* @kern_flags: mount option from kernel space or user space
716+
* @set_kern_flags: where to store converted mount opts
584717
*
585718
* Returns 0 on success, an error code on failure
719+
*
720+
* Allow filesystems with binary mount data to explicitly set Smack mount
721+
* labels.
586722
*/
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)
588727
{
589728
struct dentry *root = sb->s_root;
590729
struct inode *inode = d_backing_inode(root);
591730
struct superblock_smack *sp = sb->s_security;
592731
struct inode_smack *isp;
593732
struct smack_known *skp;
594-
char *op;
595-
char *commap;
733+
int i;
734+
int num_opts = opts->num_mnt_opts;
596735
int transmute = 0;
597-
int specified = 0;
598736

599737
if (sp->smk_initialized)
600738
return 0;
601739

602740
sp->smk_initialized = 1;
603741

604-
for (op = data; op != NULL; op = commap) {
605-
commap = strchr(op, ',');
606-
if (commap != NULL)
607-
*commap++ = '\0';
608-
609-
if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
610-
op += strlen(SMK_FSHAT);
611-
skp = smk_import_entry(op, 0);
742+
for (i = 0; i < num_opts; i++) {
743+
switch (opts->mnt_opts_flags[i]) {
744+
case FSDEFAULT_MNT:
745+
skp = smk_import_entry(opts->mnt_opts[i], 0);
612746
if (IS_ERR(skp))
613747
return PTR_ERR(skp);
614-
sp->smk_hat = skp;
615-
specified = 1;
616-
617-
} else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
618-
op += strlen(SMK_FSFLOOR);
619-
skp = smk_import_entry(op, 0);
748+
sp->smk_default = skp;
749+
break;
750+
case FSFLOOR_MNT:
751+
skp = smk_import_entry(opts->mnt_opts[i], 0);
620752
if (IS_ERR(skp))
621753
return PTR_ERR(skp);
622754
sp->smk_floor = skp;
623-
specified = 1;
624-
625-
} else if (strncmp(op, SMK_FSDEFAULT,
626-
strlen(SMK_FSDEFAULT)) == 0) {
627-
op += strlen(SMK_FSDEFAULT);
628-
skp = smk_import_entry(op, 0);
755+
break;
756+
case FSHAT_MNT:
757+
skp = smk_import_entry(opts->mnt_opts[i], 0);
629758
if (IS_ERR(skp))
630759
return PTR_ERR(skp);
631-
sp->smk_default = skp;
632-
specified = 1;
633-
634-
} else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
635-
op += strlen(SMK_FSROOT);
636-
skp = smk_import_entry(op, 0);
760+
sp->smk_hat = skp;
761+
break;
762+
case FSROOT_MNT:
763+
skp = smk_import_entry(opts->mnt_opts[i], 0);
637764
if (IS_ERR(skp))
638765
return PTR_ERR(skp);
639766
sp->smk_root = skp;
640-
specified = 1;
641-
642-
} else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
643-
op += strlen(SMK_FSTRANS);
644-
skp = smk_import_entry(op, 0);
767+
break;
768+
case FSTRANS_MNT:
769+
skp = smk_import_entry(opts->mnt_opts[i], 0);
645770
if (IS_ERR(skp))
646771
return PTR_ERR(skp);
647772
sp->smk_root = skp;
648773
transmute = 1;
649-
specified = 1;
774+
break;
775+
default:
776+
break;
650777
}
651778
}
652779

653780
if (!smack_privileged(CAP_MAC_ADMIN)) {
654781
/*
655782
* Unprivileged mounts don't get to specify Smack values.
656783
*/
657-
if (specified)
784+
if (num_opts)
658785
return -EPERM;
659786
/*
660787
* 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)
663790
sp->smk_root = skp;
664791
sp->smk_default = skp;
665792
}
793+
666794
/*
667795
* Initialize the root inode.
668796
*/
@@ -681,6 +809,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
681809
return 0;
682810
}
683811

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+
684843
/**
685844
* smack_sb_statfs - Smack check on statfs
686845
* @dentry: identifies the file system in question
@@ -4264,6 +4423,8 @@ struct security_hook_list smack_hooks[] = {
42644423
LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
42654424
LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
42664425
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),
42674428

42684429
LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
42694430
LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),

0 commit comments

Comments
 (0)