public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data
@ 2015-05-18  5:14 VIVEK TRIVEDI
  2015-05-18 19:34 ` Casey Schaufler
  2015-05-18 19:48 ` Casey Schaufler
  0 siblings, 2 replies; 3+ messages in thread
From: VIVEK TRIVEDI @ 2015-05-18  5:14 UTC (permalink / raw)
  To: casey, james.l.morris, serge
  Cc: linux-security-module, linux-kernel, a.sahrawat@samsung.com

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 9791 bytes --]

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 <t.vivek@samsung.com>
Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
---
 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 <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/binfmts.h>
+#include <linux/parser.h>
 #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Ç+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data
  2015-05-18  5:14 [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data VIVEK TRIVEDI
@ 2015-05-18 19:34 ` Casey Schaufler
  2015-05-18 19:48 ` Casey Schaufler
  1 sibling, 0 replies; 3+ messages in thread
From: Casey Schaufler @ 2015-05-18 19:34 UTC (permalink / raw)
  To: t.vivek, james.l.morris, serge
  Cc: linux-security-module, linux-kernel, a.sahrawat@samsung.com

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 <t.vivek@samsung.com>
> Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
> ---
>  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 <linux/msg.h>
>  #include <linux/shm.h>
>  #include <linux/binfmts.h>
> +#include <linux/parser.h>
>  #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),


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data
  2015-05-18  5:14 [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data VIVEK TRIVEDI
  2015-05-18 19:34 ` Casey Schaufler
@ 2015-05-18 19:48 ` Casey Schaufler
  1 sibling, 0 replies; 3+ messages in thread
From: Casey Schaufler @ 2015-05-18 19:48 UTC (permalink / raw)
  To: t.vivek, james.l.morris, serge
  Cc: linux-security-module, linux-kernel, a.sahrawat@samsung.com

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 <t.vivek@samsung.com>
> Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>

Please use a plain text format. This patch is unreadable as text.

> ---
>  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 <linux/msg.h>
>  #include <linux/shm.h>
>  #include <linux/binfmts.h>
> +#include <linux/parser.h>
>  #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),


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-18 19:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-18  5:14 [EDT] [PATCH] smack: allow mount opts setting over filesystems with binary mount data VIVEK TRIVEDI
2015-05-18 19:34 ` Casey Schaufler
2015-05-18 19:48 ` Casey Schaufler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox