Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752019AbbERFPS (ORCPT ); Mon, 18 May 2015 01:15:18 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:64458 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751495AbbERFPM (ORCPT ); Mon, 18 May 2015 01:15:12 -0400 X-AuditID: cbfee68f-f793b6d000005f66-d5-5559755dff58 Date: Mon, 18 May 2015 05:14:34 +0000 (GMT) From: VIVEK TRIVEDI Subject: [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data To: casey@schaufler-ca.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" Reply-to: t.vivek@samsung.com MIME-version: 1.0 X-MTR: 20150518050545878@t.vivek Msgkey: 20150518050545878@t.vivek X-EPLocale: en_US.utf-8 X-Priority: 3 X-EPWebmail-Msg-Type: personal X-EPWebmail-Reply-Demand: 0 X-EPApproval-Locale: X-EPHeader: ML X-MLAttribute: X-RootMTR: 20150518050545878@t.vivek X-ParentMTR: X-ArchiveUser: X-CPGSPASS: N X-ConfirmMail: N,general Content-type: text/plain; charset=utf-8 MIME-version: 1.0 Message-id: <988247983.320371431926072043.JavaMail.weblogic@ep2mlwas01c> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrIIsWRmVeSWpSXmKPExsWyRsSkVje2NDLUoOu0jcXlXXPYHBg9Pm+S C2CM4rJJSc3JLEst0rdL4Mr4sWkna8GfrIrXm++xNTDOyOhi5OQQElCS2LZpDhuILSFgItF4 4R6ULSZx4d56IJsLqGYpo8SKOUuYYIouTt/PDpGYwyjxbupMVpAEi4CqxJrzrxi7GDk42AS0 JFa90wQxhQXiJC6szAepEBGIkniyfwU7iM0s0MEo8faBI8QNshI/+0+BjecVEJQ4OfMJC8Qq BYlrf6axQcQVJY61r2CGiItL/G14xA5h80rMaH8KVS8nMe3rGqgaaYnzszYwwvyy+PtjqDi/ xLHbO6BeEZCYeuYgVI2qxITff6B+55NYs/AtC0z9rlPLmWF23d8yF6pXQmJryxNWiF8UJaZ0 P2QHeZdZQFNi/S59dK/wCnhI9DashBrTyyFx9H/dBEalWUjKZiGZNAthErKSBYwsqxhFUwuS C4qT0ouM9YoTc4tL89L1kvNzNzECU8Lpf8/6dzDePWB9iFGAg1GJh9fiTUSoEGtiWXFl7iFG U2AUTWSWEk3OByaevJJ4Q2MzIwtTE1NjI3NLMyVx3oVSP4OFBNITS1KzU1MLUovii0pzUosP MTJxcEo1MHZ84214vb78aHSyd9eJ7Sa2zXxbYgK6RfVcun/3xtWu2a8ZsLxu5TqpTa6yOzj+ Nf2+POP5/uUuHeunGuubX06/teDPla/zJihO+mN+JprTY5Xn8n/B9km7ju3ic3nWcXju8YAN bHNzev38rnvbvrW7GWFhdJG/0/lbi8LJ16Ib66Rmd3xe4K7EUpyRaKjFXFScCADEVJEjBAMA AA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrMKsWRmVeSWpSXmKPExsVy+t/tfl2r0shQg91LuSwu75rD5sDo8XmT XABjVJpNRmpiSmqRQmpecn5KZl66rZJ3cLxzvKmZgaGuoaWFuZJCXmJuqq2Si0+ArltmDtBQ JYWyxJxSoFBAYnGxkr6dTVF+aUmqQkZ+cYmtUrShuZGekYGeqZGeoWmslaGBgZEpUE1CWsaP TTtZC/5kVbzefI+tgXFGRhcjJ4eQgJLEtk1z2EBsCQETiYvT97ND2GISF+6tB4pzAdXMYZR4 N3UmK0iCRUBVYs35V4xdjBwcbAJaEqveaYKYwgJxEhdW5oNUiAhESTzZvwJsDLNAB6PE2weO EKtkJX72n2ICsXkFBCVOznzCArFKQeLan2lsEHFFiWPtK5gh4uISfxseQZ3DKzGj/SlUvZzE tK9roGqkJc7P2sAIc/Li74+h4vwSx27vYIKwBSSmnjkIVaMqMeH3H6h3+STWLHzLAlO/69Ry Zphd97fMheqVkNja8oQV4hdFiSndD9lB3mUW0JRYv0sf3Su8Ah4SvQ0rmScwys5CkpqFpHsW QjeykgWMLKsYRVMLkguKk9IrDPWKE3OLS/PS9ZLzczcxghPQs4U7GL+ctz7EKMDBqMTDa/Em IlSINbGsuDL3EKMEB7OSCG/kGaAQb0piZVVqUX58UWlOavEhRlNgjE1klhJNzgcmx7ySeENj E3NTY1MLA0NzczMlcd7/53JDhATSE0tSs1NTC1KLYPqYODilGhg3PUu45bXulvjfky/3HZKQ euZ29jL/Flv2FTbyddlPSr5LHtvz4biJmEr/YQFebZY3Bz/H+0i9OC7Clun1dH5t2mTZ4tem AaKacTzvXsqWc+nVlT5ekbtFsnPbfbcCSW0rg9V7Pun2uc9K56zxOHe3mlHGp5BZ97T96sIz d7X6VBkk8mJDKpRYijMSDbWYi4oTAQxoP/1WAwAA DLP-Filter: Pass X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id t4I5FOD5023105 Content-Length: 9791 Lines: 372 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"); + 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"); + +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), -- 1.7.9.5????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?