linux-security-module.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: sds@tycho.nsa.gov (Stephen Smalley)
To: linux-security-module@vger.kernel.org
Subject: [RFC][PATCH][v0.2] selinuxns: extend namespace support to security.selinux xattrs
Date: Wed, 22 Nov 2017 12:03:10 -0500	[thread overview]
Message-ID: <1511370190.28491.12.camel@tycho.nsa.gov> (raw)
In-Reply-To: <alpine.LFD.2.20.1711212009330.6297@localhost>

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
> a?
> ? child namespace.
> - Label inheritence & label sharing (both ro/rw).
> 
> 
> ---
> 
> > From 91bcb0b9fe058d9b7b0de1d5a1c22e5e7303989a Mon Sep 17 00:00:00
> > 2001
> 
> From: James Morris <james.l.morris@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@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

      reply	other threads:[~2017-11-22 17:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-21  9:49 [RFC][PATCH][v0.2] selinuxns: extend namespace support to security.selinux xattrs James Morris
2017-11-22 17:03 ` Stephen Smalley [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1511370190.28491.12.camel@tycho.nsa.gov \
    --to=sds@tycho.nsa.gov \
    --cc=linux-security-module@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).