[RFC][PATCH][v0.2] selinuxns: extend namespace support to security.selinux xattrs

Stephen Smalley sds at tycho.nsa.gov
Wed Nov 22 17:03:10 UTC 2017


On Tue, 2017-11-21 at 20:49 +1100, James Morris wrote:
> This is an updated version of the patch which I first posted here:
> 
> http://kernsec.org/pipermail/linux-security-module-archive/2017-Octob
> er/004053.html
> 
> I've incorporated some of the feedback provided, as follows:
> 
> 1. The init namespace is now an empty string, rather than a hidden
> "init".
> 
> 2. The ".ns." field for namespaced SELinux xattrs has been removed.
> 
> 3. Namespace names are now hierarchical, and always include parent 
>    namespace names preceding the current namespace.
> 
> As before, this works transparently for normal applications.
> 
> Some usage examples with this patch:
> 
> - Create a namespace "VM1":
> 
> # echo VM1 > /sys/fs/selinux/unshare
> # unshare -m -n
> # umount /sys/fs/selinux && mount -t selinuxfs none /sys/fs/selinux
> && load_policy
> # runcon unconfined_u:unconfined_r:unconfined_t:s0:c0.c1023 /bin/bash
> # setenforce 1
> # cat /sys/fs/selinux/unshare
> VM1
> 
> 
> - Note that the current directory appears unlabeled:
> 
> # ls -dZ
> drwxr-xr-x. root root system_u:object_r:unlabeled_t:s0 .
> 
> 
> - If you create a file, it will also thus be unlabeled:
> 
> # touch b
> # ls -Z
> -rw-r--r--. root root unconfined_u:object_r:unlabeled_t:s0 b
> 
> 
> - With the current code, you need to manually label the current
> directory 
> if you want labeling to work correctly:
> 
> # restorecon -v .
> restorecon reset /root/selinux/test context 
>   system_u:object_r:unlabeled_t:s0->system_u:object_r:admin_home_t:s0
> 
> # touch c
> # ls -lZ
> -rw-r--r--. root root unconfined_u:object_r:unlabeled_t:s0 b
> -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 c
> 
> 
> - The on-disk label looks like this:
> 
> # getfattr -d -m . c
> # file: c
> security.selinux.VM1="unconfined_u:object_r:admin_home_t:s0"
> 
> 
> - Now, create a nested namespace, "VM2":
> 
> # echo VM2 > /sys/fs/selinux/unshare
> # unshare -m -n
> #  umount /sys/fs/selinux && mount -t selinuxfs none /sys/fs/selinux
> && load_policy
> # runcon unconfined_u:unconfined_r:unconfined_t:s0:c0.c1023 /bin/bash
> # setenforce 1
> # cat /sys/fs/selinux/unshare 
> VM1.VM2
> 
> - Label .:
> 
> # restorecon -v .
> restorecon reset /root/selinux/test context 
>   system_u:object_r:unlabeled_t:s0->system_u:object_r:admin_home_t:s0
> 
> 
> - Create a new file (note files from parent namespace are unlabled in
> this 
>   one):
> 
> # touch d
> # ls -Z
> -rw-r--r--. root root system_u:object_r:unlabeled_t:s0 b
> -rw-r--r--. root root system_u:object_r:unlabeled_t:s0 c
> -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 d
> 
> 
> - Relabel the file:
> 
> # chcon -t etc_t d
> # ls -Z d
> -rw-r--r--. root root unconfined_u:object_r:etc_t:s0   d
> 
> 
> - View the on-disk label:
> 
> # getfattr -d -m . d
> # file: d
> security.selinux.VM1.VM2="unconfined_u:object_r:etc_t:s0"
> 
> 
> There's a lot more work to do but I figured it would be useful for
> folk to 
> see the hierarchical namespacing changes.  Feedback welcome!

Thanks, this looks good to me wrt the new naming scheme for namespaces
and xattrs.

> 
> Next TODO items:
> 
> - Perform labeling of files in ancestor namespaces upon creation in
>>   child namespace.
> - Label inheritence & label sharing (both ro/rw).
> 
> 
> ---
> 
> > From 91bcb0b9fe058d9b7b0de1d5a1c22e5e7303989a Mon Sep 17 00:00:00
> > 2001
> 
> From: James Morris <james.l.morris at oracle.com>
> Date: Tue, 21 Nov 2017 19:45:22 +1100
> Subject: [PATCH] selinuxns: extend namespace support to
> security.selinux
>  xattrs
> 
> RFC v0.2
> 
> Signed-off-by: James Morris <james.l.morris at oracle.com>
> 
> ---
> 
>  fs/xattr.c                            | 12 +++--
>  include/linux/lsm_hooks.h             |  2 +
>  include/linux/security.h              |  6 +++
>  include/linux/xattr.h                 |  2 +-
>  security/integrity/evm/evm_crypto.c   |  2 +-
>  security/integrity/ima/ima_appraise.c |  2 +-
>  security/security.c                   |  6 +++
>  security/selinux/hooks.c              | 95
> +++++++++++++++++++++++++++++++----
>  security/selinux/include/security.h   |  7 ++-
>  security/selinux/selinuxfs.c          | 63 ++++++++++++++---------
>  security/smack/smack_lsm.c            |  2 +-
>  11 files changed, 159 insertions(+), 40 deletions(-)
> 
> diff --git a/fs/xattr.c b/fs/xattr.c
> index 4424f7f..d8107b7 100644
> --- a/fs/xattr.c
> +++ b/fs/xattr.c
> @@ -157,6 +157,7 @@
>   *
>   *  @dentry - object to perform setxattr on
>   *  @name - xattr name to set
> + *  @nsname - namespaced xattr name, use instead of @name if set
>   *  @value - value to set @name to
>   *  @size - size of @value
>   *  @flags - flags to pass into filesystem operations
> @@ -168,7 +169,7 @@
>   *  permission checks.
>   */
>  int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
> -		const void *value, size_t size, int flags)
> +		const char *nsname, const void *value, size_t size,
> int flags)
>  {
>  	struct inode *inode = dentry->d_inode;
>  	int error = -EAGAIN;
> @@ -178,7 +179,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry,
> const char *name,
>  	if (issec)
>  		inode->i_flags &= ~S_NOSEC;
>  	if (inode->i_opflags & IOP_XATTR) {
> -		error = __vfs_setxattr(dentry, inode, name, value,
> size, flags);
> +		error = __vfs_setxattr(dentry, inode, nsname?:name,
> value,
> +					size, flags);
>  		if (!error) {
>  			fsnotify_xattr(dentry);
>  			security_inode_post_setxattr(dentry, name,
> value,
> @@ -211,6 +213,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry,
> const char *name,
>  {
>  	struct inode *inode = dentry->d_inode;
>  	int error;
> +	char *nsname = NULL;
>  
>  	error = xattr_permission(inode, name, MAY_WRITE);
>  	if (error)
> @@ -221,8 +224,11 @@ int __vfs_setxattr_noperm(struct dentry *dentry,
> const char *name,
>  	if (error)
>  		goto out;
>  
> -	error = __vfs_setxattr_noperm(dentry, name, value, size,
> flags);
> +	error = security_inode_translate_xattr_to_ns(name, &nsname);
> +	if (error)
> +		goto out;
>  
> +	error = __vfs_setxattr_noperm(dentry, name, nsname, value,
> size, flags);
>  out:
>  	inode_unlock(inode);
>  	return error;
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index c925812..e4eb43e 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -1480,6 +1480,7 @@
>  	void (*inode_getsecid)(struct inode *inode, u32 *secid);
>  	int (*inode_copy_up)(struct dentry *src, struct cred **new);
>  	int (*inode_copy_up_xattr)(const char *name);
> +	int (*inode_translate_xattr_to_ns)(const char *name, char
> **tr);
>  
>  	int (*file_permission)(struct file *file, int mask);
>  	int (*file_alloc_security)(struct file *file);
> @@ -1760,6 +1761,7 @@ struct security_hook_heads {
>  	struct list_head inode_getsecid;
>  	struct list_head inode_copy_up;
>  	struct list_head inode_copy_up_xattr;
> +	struct list_head inode_translate_xattr_to_ns;
>  	struct list_head file_permission;
>  	struct list_head file_alloc_security;
>  	struct list_head file_free_security;
> diff --git a/include/linux/security.h b/include/linux/security.h
> index ce62659..64297e1 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -302,6 +302,7 @@ void security_inode_post_setxattr(struct dentry
> *dentry, const char *name,
>  void security_inode_getsecid(struct inode *inode, u32 *secid);
>  int security_inode_copy_up(struct dentry *src, struct cred **new);
>  int security_inode_copy_up_xattr(const char *name);
> +int security_inode_translate_xattr_to_ns(const char *name, char
> **tr);
>  int security_file_permission(struct file *file, int mask);
>  int security_file_alloc(struct file *file);
>  void security_file_free(struct file *file);
> @@ -808,6 +809,11 @@ static inline int
> security_inode_copy_up_xattr(const char *name)
>  	return -EOPNOTSUPP;
>  }
>  
> +static inline int security_inode_translate_xattr_to_ns(const char
> *name, char **tr)
> +{
> +	return 0;
> +}
> +
>  static inline int security_file_permission(struct file *file, int
> mask)
>  {
>  	return 0;
> diff --git a/include/linux/xattr.h b/include/linux/xattr.h
> index e77605a..c25eb8a 100644
> --- a/include/linux/xattr.h
> +++ b/include/linux/xattr.h
> @@ -50,7 +50,7 @@ struct xattr {
>  ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
>  ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
>  int __vfs_setxattr(struct dentry *, struct inode *, const char *,
> const void *, size_t, int);
> -int __vfs_setxattr_noperm(struct dentry *, const char *, const void
> *, size_t, int);
> +int __vfs_setxattr_noperm(struct dentry *, const char *, const char
> *, const void *, size_t, int);
>  int vfs_setxattr(struct dentry *, const char *, const void *,
> size_t, int);
>  int __vfs_removexattr(struct dentry *, const char *);
>  int vfs_removexattr(struct dentry *, const char *);
> diff --git a/security/integrity/evm/evm_crypto.c
> b/security/integrity/evm/evm_crypto.c
> index 1d32cd2..2249186 100644
> --- a/security/integrity/evm/evm_crypto.c
> +++ b/security/integrity/evm/evm_crypto.c
> @@ -260,7 +260,7 @@ int evm_update_evmxattr(struct dentry *dentry,
> const char *xattr_name,
>  	if (rc == 0) {
>  		xattr_data.type = EVM_XATTR_HMAC;
>  		rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
> -					   &xattr_data,
> +					   NULL, &xattr_data,
>  					   sizeof(xattr_data), 0);
>  	} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR))
> {
>  		rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
> diff --git a/security/integrity/ima/ima_appraise.c
> b/security/integrity/ima/ima_appraise.c
> index 809ba70..914cf5f 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -71,7 +71,7 @@ static int ima_fix_xattr(struct dentry *dentry,
>  		iint->ima_hash->xattr.ng.algo = algo;
>  	}
>  	rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
> -				   &iint->ima_hash-
> >xattr.data[offset],
> +				   NULL, &iint->ima_hash-
> >xattr.data[offset],
>  				   (sizeof(iint->ima_hash->xattr) -
> offset) +
>  				   iint->ima_hash->length, 0);
>  	return rc;
> diff --git a/security/security.c b/security/security.c
> index 4bf0f57..7fce259 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -856,6 +856,12 @@ int security_inode_copy_up_xattr(const char
> *name)
>  }
>  EXPORT_SYMBOL(security_inode_copy_up_xattr);
>  
> +int security_inode_translate_xattr_to_ns(const char *name, char
> **tr)
> +{
> +	return call_int_hook(inode_translate_xattr_to_ns, 0, name,
> tr);
> +}
> +EXPORT_SYMBOL(security_inode_translate_xattr_to_ns);
> +
>  int security_file_permission(struct file *file, int mask)
>  {
>  	int ret;
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 3daad14..e439ce2 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -646,6 +646,16 @@ static int selinux_is_sblabel_mnt(struct
> super_block *sb)
>  		  !strcmp(sb->s_type->name, "cgroup2")));
>  }
>  
> +static char *current_xattr_suffix(void)
> +{
> +	return current_selinux_ns->xattr_name +
> XATTR_SECURITY_PREFIX_LEN;
> +}
> +
> +static char *current_xattr_name(void)
> +{
> +	return current_selinux_ns->xattr_name;
> +}
> +
>  static int sb_finish_set_opts(struct super_block *sb)
>  {
>  	struct superblock_security_struct *sbsec =
> superblock_security(sb);
> @@ -654,6 +664,8 @@ static int sb_finish_set_opts(struct super_block
> *sb)
>  	int rc = 0;
>  
>  	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> +		char *name;
> +
>  		/* Make sure that the xattr handler exists and that
> no
>  		   error other than -ENODATA is returned by getxattr
> on
>  		   the root directory.  -ENODATA is ok, as this may
> be
> @@ -666,7 +678,9 @@ static int sb_finish_set_opts(struct super_block
> *sb)
>  			goto out;
>  		}
>  
> -		rc = __vfs_getxattr(root, root_inode,
> XATTR_NAME_SELINUX, NULL, 0);
> +		name = current_xattr_name();
> +
> +		rc = __vfs_getxattr(root, root_inode, name, NULL,
> 0);
>  		if (rc < 0 && rc != -ENODATA) {
>  			if (rc == -EOPNOTSUPP)
>  				printk(KERN_WARNING "SELinux: (dev
> %s, type "
> @@ -1660,6 +1674,7 @@ static int inode_doinit_with_dentry(struct
> inode *inode,
>  	char *context = NULL;
>  	unsigned len = 0;
>  	int rc = 0;
> +	char *name;
>  
>  	if (isec->initialized == LABEL_INITIALIZED)
>  		return 0;
> @@ -1729,12 +1744,14 @@ static int inode_doinit_with_dentry(struct
> inode *inode,
>  			goto out;
>  		}
>  		context[len] = '\0';
> -		rc = __vfs_getxattr(dentry, inode,
> XATTR_NAME_SELINUX, context, len);
> +
> +		name = current_xattr_name();
> +		rc = __vfs_getxattr(dentry, inode, name, context,
> len);
>  		if (rc == -ERANGE) {
>  			kfree(context);
>  
>  			/* Need a larger buffer.  Query for the
> right size. */
> -			rc = __vfs_getxattr(dentry, inode,
> XATTR_NAME_SELINUX, NULL, 0);
> +			rc = __vfs_getxattr(dentry, inode, name,
> NULL, 0);
>  			if (rc < 0) {
>  				dput(dentry);
>  				goto out;
> @@ -1747,7 +1764,7 @@ static int inode_doinit_with_dentry(struct
> inode *inode,
>  				goto out;
>  			}
>  			context[len] = '\0';
> -			rc = __vfs_getxattr(dentry, inode,
> XATTR_NAME_SELINUX, context, len);
> +			rc = __vfs_getxattr(dentry, inode, name,
> context, len);
>  		}
>  		dput(dentry);
>  		if (rc < 0) {
> @@ -3167,7 +3184,7 @@ static int selinux_inode_init_security(struct
> inode *inode, struct inode *dir,
>  		return -EOPNOTSUPP;
>  
>  	if (name)
> -		*name = XATTR_SELINUX_SUFFIX;
> +		*name = current_xattr_suffix();
>  
>  	if (value && len) {
>  		rc =
> security_sid_to_context_force(current_selinux_ns, newsid,
> @@ -3382,6 +3399,10 @@ static bool has_cap_mac_admin(bool audit)
>  	return true;
>  }
>  
> +/* TODO:
> + * - audit
> + * - handle raw namespaced xattrs
> + */
>  static int selinux_inode_setxattr(struct dentry *dentry, const char
> *name,
>  				  const void *value, size_t size,
> int flags)
>  {
> @@ -3392,8 +3413,12 @@ static int selinux_inode_setxattr(struct
> dentry *dentry, const char *name,
>  	u32 newsid, sid = current_sid();
>  	int rc = 0;
>  
> -	if (strcmp(name, XATTR_NAME_SELINUX))
> +	if (strcmp(name, XATTR_NAME_SELINUX)) {
> +		/* No raw namespaced xattrs, yet */
> +		if (!strncmp(name, XATTR_NAME_SELINUX,
> strlen(XATTR_NAME_SELINUX)))
> +			return -EACCES;
>  		return selinux_inode_setotherxattr(dentry, name);
> +	}
>  
>  	sbsec = superblock_security(inode->i_sb);
>  	if (!(sbsec->flags & SBLABEL_MNT))
> @@ -3640,6 +3665,13 @@ static int selinux_inode_copy_up_xattr(const
> char *name)
>  	return -EOPNOTSUPP;
>  }
>  
> +static int selinux_inode_translate_xattr_to_ns(const char *name,
> char **tr)
> +{
> +	if(!strcmp(name, XATTR_NAME_SELINUX))
> +		*tr = current_xattr_name();
> +	return 0;
> +}
> +
>  /* file security operations */
>  
>  static int selinux_revalidate_file_permission(struct file *file, int
> mask)
> @@ -6430,10 +6462,11 @@ static int selinux_inode_notifysecctx(struct
> inode *inode, void *ctx, u32 ctxlen
>  
>  /*
>   *	called with inode->i_mutex locked
> + *	TODO: namespace translation
>   */
>  static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx,
> u32 ctxlen)
>  {
> -	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX,
> ctx, ctxlen, 0);
> +	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX,
> NULL, ctx, ctxlen, 0);
>  }
>  
>  static int selinux_inode_getsecctx(struct inode *inode, void **ctx,
> u32 *ctxlen)
> @@ -6647,6 +6680,7 @@ static void selinux_ib_free_security(void
> *ib_sec)
>  	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
>  	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
>  	LSM_HOOK_INIT(inode_copy_up_xattr,
> selinux_inode_copy_up_xattr),
> +	LSM_HOOK_INIT(inode_translate_xattr_to_ns,
> selinux_inode_translate_xattr_to_ns),
>  
>  	LSM_HOOK_INIT(file_permission, selinux_file_permission),
>  	LSM_HOOK_INIT(file_alloc_security,
> selinux_file_alloc_security),
> @@ -6805,7 +6839,37 @@ static void selinux_ib_free_security(void
> *ib_sec)
>  
>  static void selinux_ns_free(struct work_struct *work);
>  
> -int selinux_ns_create(struct selinux_ns *parent, struct selinux_ns
> **ns)
> +static int selinux_ns_create_name(struct selinux_ns *parent, struct
> selinux_ns *newns, const char *name)
> +{
> +	int rc = 0;
> +
> +	if (parent && parent->parent)
> +		newns->name = kasprintf(GFP_KERNEL, "%s.%s", parent-
> >name, name);
> +	else
> +		newns->name = kstrdup(name, GFP_KERNEL);
> +	
> +	if (!newns->name)
> +		rc = -ENOMEM;
> +
> +	return rc;
> +}
> +
> +static int selinux_ns_create_xattr_name(struct selinux_ns *parent,
> struct selinux_ns *newns)
> +{
> +	int rc = 0;
> +
> +	if (!parent)
> +		newns->xattr_name = kstrdup(XATTR_NAME_SELINUX,
> GFP_KERNEL);
> +	else 
> +		newns->xattr_name = kasprintf(GFP_KERNEL, "%s.%s",
> XATTR_NAME_SELINUX, newns->name);
> +
> +	if (!newns->xattr_name)
> +		rc = -ENOMEM;
> +
> +	return rc;
> +}
> +
> +int selinux_ns_create(struct selinux_ns *parent, struct selinux_ns
> **ns, const char *name)
>  {
>  	struct selinux_ns *newns;
>  	int rc;
> @@ -6825,14 +6889,25 @@ int selinux_ns_create(struct selinux_ns
> *parent, struct selinux_ns **ns)
>  	if (rc)
>  		goto err;
>  
> +	rc = selinux_ns_create_name(parent, newns, name);
> +	if (rc)
> +		goto err_avc;
> +
> +	rc = selinux_ns_create_xattr_name(parent, newns);
> +	if (rc)
> +		goto err_avc;
> +
>  	if (parent)
>  		newns->parent = get_selinux_ns(parent);
>  
>  	*ns = newns;
>  	return 0;
> +err_avc:
> +	selinux_avc_free(newns->avc);
>  err:
>  	selinux_ss_free(newns->ss);
>  	kfree(newns);
> +	kfree(newns->name);
>  	return rc;
>  }
>  
> @@ -6845,6 +6920,8 @@ static void selinux_ns_free(struct work_struct
> *work)
>  		parent = ns->parent;
>  		selinux_ss_free(ns->ss);
>  		selinux_avc_free(ns->avc);
> +		kfree(ns->name);
> +		kfree(ns->xattr_name);
>  		kfree(ns);
>  		ns = parent;
>  	} while (ns && refcount_dec_and_test(&ns->count));
> @@ -6869,7 +6946,7 @@ static __init int selinux_init(void)
>  
>  	printk(KERN_INFO "SELinux:  Initializing.\n");
>  
> -	if (selinux_ns_create(NULL, &init_selinux_ns))
> +	if (selinux_ns_create(NULL, &init_selinux_ns,
> SELINUX_NS_INIT_NAME))
>  		panic("SELinux: Could not create initial
> namespace\n");
>  
>  	set_ns_enforcing(init_selinux_ns, selinux_enforcing_boot);
> diff --git a/security/selinux/include/security.h
> b/security/selinux/include/security.h
> index b80f9bd..300cc8a 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -92,6 +92,9 @@ enum {
>  /* limitation of boundary depth  */
>  #define POLICYDB_BOUNDS_MAXDEPTH	4
>  
> +/* Name of SELinux initial namespace */
> +#define SELINUX_NS_INIT_NAME ""
> +
>  struct selinux_avc;
>  struct selinux_ss;
>  
> @@ -108,9 +111,11 @@ struct selinux_ns {
>  	struct selinux_avc *avc;
>  	struct selinux_ss *ss;
>  	struct selinux_ns *parent;
> +	char *name;
> +	char *xattr_name;
>  };
>  
> -int selinux_ns_create(struct selinux_ns *parent, struct selinux_ns
> **ns);
> +int selinux_ns_create(struct selinux_ns *parent, struct selinux_ns
> **ns, const char *name);
>  void __put_selinux_ns(struct selinux_ns *ns);
>  
>  int selinux_ss_create(struct selinux_ss **ss);
> diff --git a/security/selinux/selinuxfs.c
> b/security/selinux/selinuxfs.c
> index 6c52d24..d190213 100644
> --- a/security/selinux/selinuxfs.c
> +++ b/security/selinux/selinuxfs.c
> @@ -334,9 +334,10 @@ static ssize_t sel_write_unshare(struct file
> *file, const char __user *buf,
>  {
>  	struct selinux_fs_info *fsi = file_inode(file)->i_sb-
> >s_fs_info;
>  	struct selinux_ns *ns = fsi->ns;
> +	struct cred *cred;
> +	struct task_security_struct *tsec;
>  	char *page;
>  	ssize_t length;
> -	bool set;
>  	int rc;
>  
>  	if (ns != current_selinux_ns)
> @@ -359,30 +360,32 @@ static ssize_t sel_write_unshare(struct file
> *file, const char __user *buf,
>  	if (IS_ERR(page))
>  		return PTR_ERR(page);
>  
> -	length = -EINVAL;
> -	if (kstrtobool(page, &set))
> -		goto out;
> +	/* strip any trailing newline */
> +	if (page[strlen(page) - 1] == '\n')
> +		page[strlen(page) - 1] = 0;
>  
> -	if (set) {
> -		struct cred *cred = prepare_creds();
> -		struct task_security_struct *tsec;
> +	/* TODO: check for uniqueness! */
> +	if (!strcmp(SELINUX_NS_INIT_NAME, page)) {
> +		length = -EINVAL;
> +		goto out;
> +	}
>  
> -		if (!cred) {
> -			length = -ENOMEM;
> -			goto out;
> -		}
> -		tsec = cred->security;
> -		if (selinux_ns_create(ns, &tsec->ns)) {
> -			abort_creds(cred);
> -			length = -ENOMEM;
> -			goto out;
> -		}
> -		tsec->osid = tsec->sid = SECINITSID_KERNEL;
> -		tsec->exec_sid = tsec->create_sid = tsec-
> >keycreate_sid =
> -			tsec->sockcreate_sid = SECSID_NULL;
> -		tsec->parent_cred = get_current_cred();
> -		commit_creds(cred);
> +	cred = prepare_creds();
> +	if (!cred) {
> +		length = -ENOMEM;
> +		goto out;
> +	}
> +	tsec = cred->security;
> +	if (selinux_ns_create(ns, &tsec->ns, page)) {
> +		abort_creds(cred);
> +		length = -ENOMEM;
> +		goto out;
>  	}
> +	tsec->osid = tsec->sid = SECINITSID_KERNEL;
> +	tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid =
> +		tsec->sockcreate_sid = SECSID_NULL;
> +	tsec->parent_cred = get_current_cred();
> +	commit_creds(cred);
>  
>  	length = count;
>  out:
> @@ -390,8 +393,22 @@ static ssize_t sel_write_unshare(struct file
> *file, const char __user *buf,
>  	return length;
>  }
>  
> +static ssize_t sel_read_unshare(struct file *file, char __user *buf,
> +				size_t count, loff_t *ppos)
> +{
> +	struct selinux_fs_info *fsi = file_inode(file)->i_sb-
> >s_fs_info;
> +	struct selinux_ns *ns = fsi->ns;
> +	char *name = ns->name;
> +
> +	if (ns != current_selinux_ns)
> +		return -EPERM;
> +
> +	return simple_read_from_buffer(buf, count, ppos, name,
> strlen(name));
> +}
> +
>  static const struct file_operations sel_unshare_ops = {
>  	.write		= sel_write_unshare,
> +	.read		= sel_read_unshare,
>  	.llseek		= generic_file_llseek,
>  };
>  
> @@ -2021,7 +2038,7 @@ static int sel_fill_super(struct super_block
> *sb, void *data, int silent)
>  		[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
>  		[SEL_VALIDATE_TRANS] = {"validatetrans",
> &sel_transition_ops,
>  					S_IWUGO},
> -		[SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0222},
> +		[SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0666},
>  		/* last one */ {""}
>  	};
>  
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 319add3..5ea841f 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4591,7 +4591,7 @@ static int smack_inode_notifysecctx(struct
> inode *inode, void *ctx, u32 ctxlen)
>  
>  static int smack_inode_setsecctx(struct dentry *dentry, void *ctx,
> u32 ctxlen)
>  {
> -	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx,
> ctxlen, 0);
> +	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, NULL,
> ctx, ctxlen, 0);
>  }
>  
>  static int smack_inode_getsecctx(struct inode *inode, void **ctx,
> u32 *ctxlen)
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list