Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932580AbbERTei (ORCPT ); Mon, 18 May 2015 15:34:38 -0400 Received: from smtp104.biz.mail.bf1.yahoo.com ([98.139.221.63]:46200 "EHLO smtp104.biz.mail.bf1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932068AbbERTef (ORCPT ); Mon, 18 May 2015 15:34:35 -0400 X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: UuKGOAoVM1lYYtPe47_hg_zNM283FnWz07muVd7S8ob0DsM C_iol436PEEc.dqT19WkNTFOqqcWKTAdUIYOXsFv0oIduVhSRU8bXegNNraJ _8hg98XhIjRu5wzzKG_6W.CYby0NuPhGL.28FkN.RAS9tIL36R3edZnNrs.1 IcPExGwuirifiTQOHGyZIMTzsvDTHGQMbtA9DDsflhYntYhESIFqBIi8sisZ EkqXFclt42CkRoZT7YKnZphy_hyiweqG567kUistw_Oo5GpUxyZls_kET.HL 4hss5gsRI6id49mv73j3q0dBBGsc0Le1up.BnPbVIoRc0RKFtz.2qWVFRVE9 c4CH1SfSL6J3cMeMQmqg2K6XTlIscQFt53q7GiJaULFjrdxCeHUhmepTDsDF .vVUGi.r.qEMinmaF6R2Ggzd5qE9d_h3hu6ed4lMuK.GI89nyicsIm1tjhGD BotKTs3oPwFpky2JRIDZEBusNO6G2gjXmzrFIM2HqFYRYx.ADZc_8huu.cZb m2wPDPxmWEhypCqO1KLNCuvCz4I9CXo9ZRciO X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Message-ID: <555A3EC6.6020304@schaufler-ca.com> Date: Mon, 18 May 2015 12:34:30 -0700 From: Casey Schaufler User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: t.vivek@samsung.com, james.l.morris@oracle.com, serge@hallyn.com CC: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, "a.sahrawat@samsung.com" Subject: Re: [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data References: <988247983.320371431926072043.JavaMail.weblogic@ep2mlwas01c> In-Reply-To: <988247983.320371431926072043.JavaMail.weblogic@ep2mlwas01c> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10741 Lines: 384 On 5/17/2015 10:14 PM, VIVEK TRIVEDI wrote: > EP-79F327334E67427298A99177E8F035A1 > > 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 > Signed-off-by: Amit Sahrawat > --- > security/smack/smack.h | 18 ++++ > security/smack/smack_lsm.c | 250 ++++++++++++++++++++++++++++++++++++-------- > 2 files changed, 223 insertions(+), 45 deletions(-) > > diff --git a/security/smack/smack.h b/security/smack/smack.h > index b8c1a86..f5db743 100644 > --- a/security/smack/smack.h > +++ b/security/smack/smack.h > @@ -138,6 +138,24 @@ struct smk_port_label { > struct smack_known *smk_out; /* outgoing label */ > }; > > +/* Super block security struct flags for mount options */ > +#define FSDEFAULT_MNT 0x01 > +#define FSFLOOR_MNT 0x02 > +#define FSHAT_MNT 0x04 > +#define FSROOT_MNT 0x08 > +#define FSTRANS_MNT 0x10 > + > +#define NUM_SMK_MNT_OPTS 5 > + > +enum { > + Opt_error = -1, > + Opt_fsdefault = 1, > + Opt_fsfloor = 2, > + Opt_fshat = 3, > + Opt_fsroot = 4, > + Opt_fstransmute = 5, > +}; > + > /* > * Mount options > */ > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c > index 5eae42c..d88c27e 100644 > --- a/security/smack/smack_lsm.c > +++ b/security/smack/smack_lsm.c > @@ -41,6 +41,7 @@ > #include > #include > #include > +#include > #include "smack.h" > > #define TRANS_TRUE "TRUE" > @@ -64,6 +65,15 @@ static char *smk_bu_mess[] = { > "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ > }; > > +static const match_table_t tokens = { > + {Opt_fsdefault, SMK_FSDEFAULT "%s"}, > + {Opt_fsfloor, SMK_FSFLOOR "%s"}, > + {Opt_fshat, SMK_FSHAT "%s"}, > + {Opt_fsroot, SMK_FSROOT "%s"}, > + {Opt_fstransmute, SMK_FSTRANS "%s"}, > + {Opt_error, NULL}, > +}; > + > static void smk_bu_mode(int mode, char *s) > { > int i = 0; > @@ -573,72 +583,188 @@ static int smack_sb_copy_data(char *orig, char *smackopts) > } > > /** > - * smack_sb_kern_mount - Smack specific mount processing > + * smack_parse_opts_str - parse Smack specific mount options > + * @options: mount options string > + * @opts: where to store converted mount opts > + * > + * Returns 0 on success or -ENOMEM on error. > + * > + * converts Smack specific mount options to generic security option format > + */ > +static int smack_parse_opts_str(char *options, > + struct security_mnt_opts *opts) > +{ > + char *p; > + char *fsdefault = NULL, *fsfloor = NULL; > + char *fshat = NULL, *fsroot = NULL, *fstransmute = NULL; > + int rc = -ENOMEM, num_mnt_opts = 0; > + > + opts->num_mnt_opts = 0; > + > + if (!options) > + return 0; > + > + while ((p = strsep(&options, ",")) != NULL) { > + int token; > + substring_t args[MAX_OPT_ARGS]; > + > + if (!*p) > + continue; > + > + token = match_token(p, tokens, args); > + > + switch (token) { > + case Opt_fsdefault: > + if (fsdefault) > + goto out_opt_err; > + fsdefault = match_strdup(&args[0]); > + if (!fsdefault) > + goto out_err; > + break; > + case Opt_fsfloor: > + if (fsfloor) > + goto out_opt_err; > + fsfloor = match_strdup(&args[0]); > + if (!fsfloor) > + goto out_err; > + break; > + case Opt_fshat: > + if (fshat) > + goto out_opt_err; > + fshat = match_strdup(&args[0]); > + if (!fshat) > + goto out_err; > + break; > + case Opt_fsroot: > + if (fsroot) > + goto out_opt_err; > + fsroot = match_strdup(&args[0]); > + if (!fsroot) > + goto out_err; > + break; > + case Opt_fstransmute: > + if (fstransmute) > + goto out_opt_err; > + fstransmute = match_strdup(&args[0]); > + if (!fstransmute) > + goto out_err; > + break; > + default: > + rc = -EINVAL; > + pr_warn("SMACK: unknown mount option\n"); Please use "Smack: unknown mount option\n". > + goto out_err; > + } > + } > + > + opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC); > + if (!opts->mnt_opts) > + goto out_err; > + > + opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), > + GFP_ATOMIC); > + if (!opts->mnt_opts_flags) { > + kfree(opts->mnt_opts); > + goto out_err; > + } > + > + if (fsdefault) { > + opts->mnt_opts[num_mnt_opts] = fsdefault; > + opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT; > + } > + if (fsfloor) { > + opts->mnt_opts[num_mnt_opts] = fsfloor; > + opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT; > + } > + if (fshat) { > + opts->mnt_opts[num_mnt_opts] = fshat; > + opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT; > + } > + if (fsroot) { > + opts->mnt_opts[num_mnt_opts] = fsroot; > + opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT; > + } > + if (fstransmute) { > + opts->mnt_opts[num_mnt_opts] = fstransmute; > + opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT; > + } > + > + opts->num_mnt_opts = num_mnt_opts; > + return 0; > + > +out_opt_err: > + rc = -EINVAL; > + pr_warn("SMACK: duplicate mount options\n"); Please use "Smack: duplicate mount options\n" > + > +out_err: > + kfree(fsdefault); > + kfree(fsfloor); > + kfree(fshat); > + kfree(fsroot); > + kfree(fstransmute); > + return rc; > +} > + > +/** > + * smack_set_mnt_opts - set Smack specific mount options > * @sb: the file system superblock > - * @flags: the mount flags > - * @data: the smack mount options > + * @opts: Smack mount options > + * @kern_flags: mount option from kernel space or user space > + * @set_kern_flags: where to store converted mount opts > * > - * Returns 0 on success, an error code on failure > + * Returns 0 on success or -EPERM/ENOMEM on error. > + * > + * Allow filesystems with binary mount data to explicitly set Smack mount > + * labels. > */ > -static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) > +static int smack_set_mnt_opts(struct super_block *sb, > + struct security_mnt_opts *opts, > + unsigned long kern_flags, > + unsigned long *set_kern_flags) > { > struct dentry *root = sb->s_root; > struct inode *inode = d_backing_inode(root); > struct superblock_smack *sp = sb->s_security; > struct inode_smack *isp; > struct smack_known *skp; > - char *op; > - char *commap; > + int i, num_opts = opts->num_mnt_opts; > int transmute = 0; > - int specified = 0; > > if (sp->smk_initialized) > return 0; > > sp->smk_initialized = 1; > > - for (op = data; op != NULL; op = commap) { > - commap = strchr(op, ','); > - if (commap != NULL) > - *commap++ = '\0'; > - > - if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { > - op += strlen(SMK_FSHAT); > - skp = smk_import_entry(op, 0); > - if (skp != NULL) { > - sp->smk_hat = skp; > - specified = 1; > - } > - } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { > - op += strlen(SMK_FSFLOOR); > - skp = smk_import_entry(op, 0); > - if (skp != NULL) { > - sp->smk_floor = skp; > - specified = 1; > - } > - } else if (strncmp(op, SMK_FSDEFAULT, > - strlen(SMK_FSDEFAULT)) == 0) { > - op += strlen(SMK_FSDEFAULT); > - skp = smk_import_entry(op, 0); > - if (skp != NULL) { > + for (i = 0; i < num_opts; i++) { > + switch (opts->mnt_opts_flags[i]) { > + case FSDEFAULT_MNT: > + skp = smk_import_entry(opts->mnt_opts[i], 0); > + if (skp != NULL) > sp->smk_default = skp; > - specified = 1; > - } > - } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { > - op += strlen(SMK_FSROOT); > - skp = smk_import_entry(op, 0); > - if (skp != NULL) { > + break; > + case FSFLOOR_MNT: > + skp = smk_import_entry(opts->mnt_opts[i], 0); > + if (skp != NULL) > + sp->smk_floor = skp; > + break; > + case FSHAT_MNT: > + skp = smk_import_entry(opts->mnt_opts[i], 0); > + if (skp != NULL) > + sp->smk_hat = skp; > + break; > + case FSROOT_MNT: > + skp = smk_import_entry(opts->mnt_opts[i], 0); > + if (skp != NULL) > sp->smk_root = skp; > - specified = 1; > - } > - } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { > - op += strlen(SMK_FSTRANS); > - skp = smk_import_entry(op, 0); > + break; > + case FSTRANS_MNT: > + skp = smk_import_entry(opts->mnt_opts[i], 0); > if (skp != NULL) { > sp->smk_root = skp; > transmute = 1; > - specified = 1; > } > + break; > + default: > + break; > } > } > > @@ -646,7 +772,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) > /* > * Unprivileged mounts don't get to specify Smack values. > */ > - if (specified) > + if (num_opts) > return -EPERM; > /* > * Unprivileged mounts get root and default from the caller. > @@ -655,6 +781,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) > sp->smk_root = skp; > sp->smk_default = skp; > } > + > /* > * Initialize the root inode. > */ > @@ -674,6 +801,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) > } > > /** > + * smack_sb_kern_mount - Smack specific mount processing > + * @sb: the file system superblock > + * @flags: the mount flags > + * @data: the smack mount options > + * > + * Returns 0 on success, an error code on failure > + */ > +static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) > +{ > + int rc = 0; > + char *options = data; > + struct security_mnt_opts opts; > + > + security_init_mnt_opts(&opts); > + > + if (!options) > + goto out; > + > + rc = smack_parse_opts_str(options, &opts); > + if (rc) > + goto out_err; > + > +out: > + rc = smack_set_mnt_opts(sb, &opts, 0, NULL); > + > +out_err: > + security_free_mnt_opts(&opts); > + return rc; > +} > + > +/** > * smack_sb_statfs - Smack check on statfs > * @dentry: identifies the file system in question > * > @@ -4246,6 +4404,8 @@ struct security_hook_list smack_hooks[] = { > LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), > LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), > LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), > + LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), > + LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str), > > LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), > LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/