e058006
From 1a93a6eac32a2853177f10e274b9b761b42356eb Mon Sep 17 00:00:00 2001
e058006
From: Javier Martinez Canillas <javier@osg.samsung.com>
e058006
Date: Mon, 8 Aug 2016 13:08:25 -0400
e058006
Subject: [PATCH 01/10] security: Use IS_ENABLED() instead of checking for
e058006
 built-in or module
e058006
e058006
The IS_ENABLED() macro checks if a Kconfig symbol has been enabled
e058006
either built-in or as a module, use that macro instead of open coding
e058006
the same.
e058006
e058006
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
e058006
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/lsm_audit.c             |  2 +-
e058006
 security/selinux/hooks.c         | 12 ++++++------
e058006
 security/smack/smack_netfilter.c |  4 ++--
e058006
 3 files changed, 9 insertions(+), 9 deletions(-)
e058006
e058006
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
e058006
index cccbf30..5369036 100644
e058006
--- a/security/lsm_audit.c
e058006
+++ b/security/lsm_audit.c
e058006
@@ -99,7 +99,7 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
e058006
 	}
e058006
 	return ret;
e058006
 }
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 /**
e058006
  * ipv6_skb_to_auditdata : fill auditdata from skb
e058006
  * @skb : the skb
e058006
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
e058006
index 13185a6..880f953 100644
e058006
--- a/security/selinux/hooks.c
e058006
+++ b/security/selinux/hooks.c
e058006
@@ -3984,7 +3984,7 @@ out:
e058006
 	return ret;
e058006
 }
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
e058006
 /* Returns error only if unable to parse addresses */
e058006
 static int selinux_parse_skb_ipv6(struct sk_buff *skb,
e058006
@@ -4075,7 +4075,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
e058006
 				       &ad->u.net->v4info.daddr);
e058006
 		goto okay;
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 	case PF_INET6:
e058006
 		ret = selinux_parse_skb_ipv6(skb, ad, proto);
e058006
 		if (ret)
e058006
@@ -5029,7 +5029,7 @@ static unsigned int selinux_ipv4_forward(void *priv,
e058006
 	return selinux_ip_forward(skb, state->in, PF_INET);
e058006
 }
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 static unsigned int selinux_ipv6_forward(void *priv,
e058006
 					 struct sk_buff *skb,
e058006
 					 const struct nf_hook_state *state)
e058006
@@ -5087,7 +5087,7 @@ static unsigned int selinux_ipv4_output(void *priv,
e058006
 	return selinux_ip_output(skb, PF_INET);
e058006
 }
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 static unsigned int selinux_ipv6_output(void *priv,
e058006
 					struct sk_buff *skb,
e058006
 					const struct nf_hook_state *state)
e058006
@@ -5273,7 +5273,7 @@ static unsigned int selinux_ipv4_postroute(void *priv,
e058006
 	return selinux_ip_postroute(skb, state->out, PF_INET);
e058006
 }
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 static unsigned int selinux_ipv6_postroute(void *priv,
e058006
 					   struct sk_buff *skb,
e058006
 					   const struct nf_hook_state *state)
e058006
@@ -6317,7 +6317,7 @@ static struct nf_hook_ops selinux_nf_ops[] = {
e058006
 		.hooknum =	NF_INET_LOCAL_OUT,
e058006
 		.priority =	NF_IP_PRI_SELINUX_FIRST,
e058006
 	},
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 	{
e058006
 		.hook =		selinux_ipv6_postroute,
e058006
 		.pf =		NFPROTO_IPV6,
e058006
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
e058006
index aa6bf1b..205b785 100644
e058006
--- a/security/smack/smack_netfilter.c
e058006
+++ b/security/smack/smack_netfilter.c
e058006
@@ -20,7 +20,7 @@
e058006
 #include <net/inet_sock.h>
e058006
 #include "smack.h"
e058006
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
e058006
 static unsigned int smack_ipv6_output(void *priv,
e058006
 					struct sk_buff *skb,
e058006
@@ -64,7 +64,7 @@ static struct nf_hook_ops smack_nf_ops[] = {
e058006
 		.hooknum =	NF_INET_LOCAL_OUT,
e058006
 		.priority =	NF_IP_PRI_SELINUX_FIRST,
e058006
 	},
e058006
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
e058006
+#if IS_ENABLED(CONFIG_IPV6)
e058006
 	{
e058006
 		.hook =		smack_ipv6_output,
e058006
 		.pf =		NFPROTO_IPV6,
e058006
-- 
e058006
2.7.4
e058006
e058006
From 8b31f456c72e53ee97474a538bcd91bfb1b93fb7 Mon Sep 17 00:00:00 2001
e058006
From: William Roberts <william.c.roberts@intel.com>
e058006
Date: Mon, 8 Aug 2016 13:08:34 -0400
e058006
Subject: [PATCH 02/10] selinux: print leading 0x on ioctlcmd audits
e058006
e058006
ioctlcmd is currently printing hex numbers, but their is no leading
e058006
0x. Thus things like ioctlcmd=1234 are misleading, as the base is
e058006
not evident.
e058006
e058006
Correct this by adding 0x as a prefix, so ioctlcmd=1234 becomes
e058006
ioctlcmd=0x1234.
e058006
e058006
Signed-off-by: William Roberts <william.c.roberts@intel.com>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/lsm_audit.c | 2 +-
e058006
 1 file changed, 1 insertion(+), 1 deletion(-)
e058006
e058006
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
e058006
index 5369036..9bf8518 100644
e058006
--- a/security/lsm_audit.c
e058006
+++ b/security/lsm_audit.c
e058006
@@ -257,7 +257,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
e058006
 			audit_log_format(ab, " ino=%lu", inode->i_ino);
e058006
 		}
e058006
e058006
-		audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd);
e058006
+		audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
e058006
 		break;
e058006
 	}
e058006
 	case LSM_AUDIT_DATA_DENTRY: {
e058006
-- 
e058006
2.7.4
e058006
e058006
From d8ad8b49618410ddeafd78465b63a6cedd6c9484 Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 11:13:56 -0400
e058006
Subject: [PATCH 03/10] security, overlayfs: provide copy up security hook for
e058006
 unioned files
e058006
e058006
Provide a security hook to label new file correctly when a file is copied
e058006
up from lower layer to upper layer of a overlay/union mount.
e058006
e058006
This hook can prepare a new set of creds which are suitable for new file
e058006
creation during copy up. Caller will use new creds to create file and then
e058006
revert back to old creds and release new creds.
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
[PM: whitespace cleanup to appease checkpatch.pl]
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 fs/overlayfs/copy_up.c    | 15 +++++++++++++++
e058006
 include/linux/lsm_hooks.h | 11 +++++++++++
e058006
 include/linux/security.h  |  6 ++++++
e058006
 security/security.c       |  8 ++++++++
e058006
 4 files changed, 40 insertions(+)
e058006
e058006
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
e058006
index 54e5d66..c297b1f 100644
e058006
--- a/fs/overlayfs/copy_up.c
e058006
+++ b/fs/overlayfs/copy_up.c
e058006
@@ -246,6 +246,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
e058006
 	struct dentry *upper = NULL;
e058006
 	umode_t mode = stat->mode;
e058006
 	int err;
e058006
+	const struct cred *old_creds = NULL;
e058006
+	struct cred *new_creds = NULL;
e058006
e058006
 	newdentry = ovl_lookup_temp(workdir, dentry);
e058006
 	err = PTR_ERR(newdentry);
e058006
@@ -258,10 +260,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
e058006
 	if (IS_ERR(upper))
e058006
 		goto out1;
e058006
e058006
+	err = security_inode_copy_up(dentry, &new_creds);
e058006
+	if (err < 0)
e058006
+		goto out2;
e058006
+
e058006
+	if (new_creds)
e058006
+		old_creds = override_creds(new_creds);
e058006
+
e058006
 	/* Can't properly set mode on creation because of the umask */
e058006
 	stat->mode &= S_IFMT;
e058006
 	err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
e058006
 	stat->mode = mode;
e058006
+
e058006
+	if (new_creds) {
e058006
+		revert_creds(old_creds);
e058006
+		put_cred(new_creds);
e058006
+	}
e058006
+
e058006
 	if (err)
e058006
 		goto out2;
e058006
e058006
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
e058006
index 101bf19..cb69fc8 100644
e058006
--- a/include/linux/lsm_hooks.h
e058006
+++ b/include/linux/lsm_hooks.h
e058006
@@ -401,6 +401,15 @@
e058006
  *	@inode contains a pointer to the inode.
e058006
  *	@secid contains a pointer to the location where result will be saved.
e058006
  *	In case of failure, @secid will be set to zero.
e058006
+ * @inode_copy_up:
e058006
+ *	A file is about to be copied up from lower layer to upper layer of
e058006
+ *	overlay filesystem. Security module can prepare a set of new creds
e058006
+ *	and modify as need be and return new creds. Caller will switch to
e058006
+ *	new creds temporarily to create new file and release newly allocated
e058006
+ *	creds.
e058006
+ *	@src indicates the union dentry of file that is being copied up.
e058006
+ *	@new pointer to pointer to return newly allocated creds.
e058006
+ *	Returns 0 on success or a negative error code on error.
e058006
  *
e058006
  * Security hooks for file operations
e058006
  *
e058006
@@ -1425,6 +1434,7 @@ union security_list_options {
e058006
 	int (*inode_listsecurity)(struct inode *inode, char *buffer,
e058006
 					size_t buffer_size);
e058006
 	void (*inode_getsecid)(struct inode *inode, u32 *secid);
e058006
+	int (*inode_copy_up)(struct dentry *src, struct cred **new);
e058006
e058006
 	int (*file_permission)(struct file *file, int mask);
e058006
 	int (*file_alloc_security)(struct file *file);
e058006
@@ -1696,6 +1706,7 @@ struct security_hook_heads {
e058006
 	struct list_head inode_setsecurity;
e058006
 	struct list_head inode_listsecurity;
e058006
 	struct list_head inode_getsecid;
e058006
+	struct list_head inode_copy_up;
e058006
 	struct list_head file_permission;
e058006
 	struct list_head file_alloc_security;
e058006
 	struct list_head file_free_security;
e058006
diff --git a/include/linux/security.h b/include/linux/security.h
e058006
index 7831cd5..c5b0ccd 100644
e058006
--- a/include/linux/security.h
e058006
+++ b/include/linux/security.h
e058006
@@ -282,6 +282,7 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf
e058006
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
e058006
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
e058006
 void security_inode_getsecid(struct inode *inode, u32 *secid);
e058006
+int security_inode_copy_up(struct dentry *src, struct cred **new);
e058006
 int security_file_permission(struct file *file, int mask);
e058006
 int security_file_alloc(struct file *file);
e058006
 void security_file_free(struct file *file);
e058006
@@ -758,6 +759,11 @@ static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
e058006
 	*secid = 0;
e058006
 }
e058006
e058006
+static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
e058006
+{
e058006
+	return 0;
e058006
+}
e058006
+
e058006
 static inline int security_file_permission(struct file *file, int mask)
e058006
 {
e058006
 	return 0;
e058006
diff --git a/security/security.c b/security/security.c
e058006
index 4838e7f..f2a7f27 100644
e058006
--- a/security/security.c
e058006
+++ b/security/security.c
e058006
@@ -748,6 +748,12 @@ void security_inode_getsecid(struct inode *inode, u32 *secid)
e058006
 	call_void_hook(inode_getsecid, inode, secid);
e058006
 }
e058006
e058006
+int security_inode_copy_up(struct dentry *src, struct cred **new)
e058006
+{
e058006
+	return call_int_hook(inode_copy_up, 0, src, new);
e058006
+}
e058006
+EXPORT_SYMBOL(security_inode_copy_up);
e058006
+
e058006
 int security_file_permission(struct file *file, int mask)
e058006
 {
e058006
 	int ret;
e058006
@@ -1684,6 +1690,8 @@ struct security_hook_heads security_hook_heads = {
e058006
 		LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
e058006
 	.inode_getsecid =
e058006
 		LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
e058006
+	.inode_copy_up =
e058006
+		LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
e058006
 	.file_permission =
e058006
 		LIST_HEAD_INIT(security_hook_heads.file_permission),
e058006
 	.file_alloc_security =
e058006
-- 
e058006
2.7.4
e058006
e058006
From 56909eb3f559103196ecbf2c08c923e0804980fb Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:48 -0400
e058006
Subject: [PATCH 04/10] selinux: Implementation for inode_copy_up() hook
e058006
e058006
A file is being copied up for overlay file system. Prepare a new set of
e058006
creds and set create_sid appropriately so that new file is created with
e058006
appropriate label.
e058006
e058006
Overlay inode has right label for both context and non-context mount
e058006
cases. In case of non-context mount, overlay inode will have the label
e058006
of lower file and in case of context mount, overlay inode will have
e058006
the label from context= mount option.
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/selinux/hooks.c | 21 +++++++++++++++++++++
e058006
 1 file changed, 21 insertions(+)
e058006
e058006
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
e058006
index 880f953..40597ed 100644
e058006
--- a/security/selinux/hooks.c
e058006
+++ b/security/selinux/hooks.c
e058006
@@ -3293,6 +3293,26 @@ static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
e058006
 	*secid = isec->sid;
e058006
 }
e058006
e058006
+static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
e058006
+{
e058006
+	u32 sid;
e058006
+	struct task_security_struct *tsec;
e058006
+	struct cred *new_creds = *new;
e058006
+
e058006
+	if (new_creds == NULL) {
e058006
+		new_creds = prepare_creds();
e058006
+		if (!new_creds)
e058006
+			return -ENOMEM;
e058006
+	}
e058006
+
e058006
+	tsec = new_creds->security;
e058006
+	/* Get label from overlay inode and set it in create_sid */
e058006
+	selinux_inode_getsecid(d_inode(src), &sid;;
e058006
+	tsec->create_sid = sid;
e058006
+	*new = new_creds;
e058006
+	return 0;
e058006
+}
e058006
+
e058006
 /* file security operations */
e058006
e058006
 static int selinux_revalidate_file_permission(struct file *file, int mask)
e058006
@@ -6088,6 +6108,7 @@ static struct security_hook_list selinux_hooks[] = {
e058006
 	LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
e058006
 	LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
e058006
 	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
e058006
+	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
e058006
e058006
 	LSM_HOOK_INIT(file_permission, selinux_file_permission),
e058006
 	LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
e058006
-- 
e058006
2.7.4
e058006
e058006
From 121ab822ef21914adac2fa3730efeeb8fd762473 Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:49 -0400
e058006
Subject: [PATCH 05/10] security,overlayfs: Provide security hook for copy up
e058006
 of xattrs for overlay file
e058006
e058006
Provide a security hook which is called when xattrs of a file are being
e058006
copied up. This hook is called once for each xattr and LSM can return
e058006
0 if the security module wants the xattr to be copied up, 1 if the
e058006
security module wants the xattr to be discarded on the copy, -EOPNOTSUPP
e058006
if the security module does not handle/manage the xattr, or a -errno
e058006
upon an error.
e058006
e058006
Signed-off-by: David Howells <dhowells@redhat.com>
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
[PM: whitespace cleanup for checkpatch.pl]
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 fs/overlayfs/copy_up.c    |  7 +++++++
e058006
 include/linux/lsm_hooks.h | 10 ++++++++++
e058006
 include/linux/security.h  |  6 ++++++
e058006
 security/security.c       |  8 ++++++++
e058006
 4 files changed, 31 insertions(+)
e058006
e058006
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
e058006
index c297b1f..cd65f12 100644
e058006
--- a/fs/overlayfs/copy_up.c
e058006
+++ b/fs/overlayfs/copy_up.c
e058006
@@ -103,6 +103,13 @@ retry:
e058006
 			goto retry;
e058006
 		}
e058006
e058006
+		error = security_inode_copy_up_xattr(name);
e058006
+		if (error < 0 && error != -EOPNOTSUPP)
e058006
+			break;
e058006
+		if (error == 1) {
e058006
+			error = 0;
e058006
+			continue; /* Discard */
e058006
+		}
e058006
 		error = vfs_setxattr(new, name, value, size, 0);
e058006
 		if (error)
e058006
 			break;
e058006
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
e058006
index cb69fc8..5797122 100644
e058006
--- a/include/linux/lsm_hooks.h
e058006
+++ b/include/linux/lsm_hooks.h
e058006
@@ -410,6 +410,14 @@
e058006
  *	@src indicates the union dentry of file that is being copied up.
e058006
  *	@new pointer to pointer to return newly allocated creds.
e058006
  *	Returns 0 on success or a negative error code on error.
e058006
+ * @inode_copy_up_xattr:
e058006
+ *	Filter the xattrs being copied up when a unioned file is copied
e058006
+ *	up from a lower layer to the union/overlay layer.
e058006
+ *	@name indicates the name of the xattr.
e058006
+ *	Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if
e058006
+ *	security module does not know about attribute or a negative error code
e058006
+ *	to abort the copy up. Note that the caller is responsible for reading
e058006
+ *	and writing the xattrs as this hook is merely a filter.
e058006
  *
e058006
  * Security hooks for file operations
e058006
  *
e058006
@@ -1435,6 +1443,7 @@ union security_list_options {
e058006
 					size_t buffer_size);
e058006
 	void (*inode_getsecid)(struct inode *inode, u32 *secid);
e058006
 	int (*inode_copy_up)(struct dentry *src, struct cred **new);
e058006
+	int (*inode_copy_up_xattr)(const char *name);
e058006
e058006
 	int (*file_permission)(struct file *file, int mask);
e058006
 	int (*file_alloc_security)(struct file *file);
e058006
@@ -1707,6 +1716,7 @@ struct security_hook_heads {
e058006
 	struct list_head inode_listsecurity;
e058006
 	struct list_head inode_getsecid;
e058006
 	struct list_head inode_copy_up;
e058006
+	struct list_head inode_copy_up_xattr;
e058006
 	struct list_head file_permission;
e058006
 	struct list_head file_alloc_security;
e058006
 	struct list_head file_free_security;
e058006
diff --git a/include/linux/security.h b/include/linux/security.h
e058006
index c5b0ccd..536fafd 100644
e058006
--- a/include/linux/security.h
e058006
+++ b/include/linux/security.h
e058006
@@ -283,6 +283,7 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void
e058006
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
e058006
 void security_inode_getsecid(struct inode *inode, u32 *secid);
e058006
 int security_inode_copy_up(struct dentry *src, struct cred **new);
e058006
+int security_inode_copy_up_xattr(const char *name);
e058006
 int security_file_permission(struct file *file, int mask);
e058006
 int security_file_alloc(struct file *file);
e058006
 void security_file_free(struct file *file);
e058006
@@ -764,6 +765,11 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
e058006
 	return 0;
e058006
 }
e058006
e058006
+static inline int security_inode_copy_up_xattr(const char *name)
e058006
+{
e058006
+	return -EOPNOTSUPP;
e058006
+}
e058006
+
e058006
 static inline int security_file_permission(struct file *file, int mask)
e058006
 {
e058006
 	return 0;
e058006
diff --git a/security/security.c b/security/security.c
e058006
index f2a7f27..a9e2bb9 100644
e058006
--- a/security/security.c
e058006
+++ b/security/security.c
e058006
@@ -754,6 +754,12 @@ int security_inode_copy_up(struct dentry *src, struct cred **new)
e058006
 }
e058006
 EXPORT_SYMBOL(security_inode_copy_up);
e058006
e058006
+int security_inode_copy_up_xattr(const char *name)
e058006
+{
e058006
+	return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name);
e058006
+}
e058006
+EXPORT_SYMBOL(security_inode_copy_up_xattr);
e058006
+
e058006
 int security_file_permission(struct file *file, int mask)
e058006
 {
e058006
 	int ret;
e058006
@@ -1692,6 +1698,8 @@ struct security_hook_heads security_hook_heads = {
e058006
 		LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
e058006
 	.inode_copy_up =
e058006
 		LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
e058006
+	.inode_copy_up_xattr =
e058006
+		LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr),
e058006
 	.file_permission =
e058006
 		LIST_HEAD_INIT(security_hook_heads.file_permission),
e058006
 	.file_alloc_security =
e058006
-- 
e058006
2.7.4
e058006
e058006
From 19472b69d639d58415866bf127d5f9005038c105 Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:50 -0400
e058006
Subject: [PATCH 06/10] selinux: Implementation for inode_copy_up_xattr() hook
e058006
e058006
When a file is copied up in overlay, we have already created file on
e058006
upper/ with right label and there is no need to copy up selinux
e058006
label/xattr from lower file to upper file. In fact in case of context
e058006
mount, we don't want to copy up label as newly created file got its label
e058006
from context= option.
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/selinux/hooks.c | 16 ++++++++++++++++
e058006
 1 file changed, 16 insertions(+)
e058006
e058006
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
e058006
index 40597ed..a2d5108 100644
e058006
--- a/security/selinux/hooks.c
e058006
+++ b/security/selinux/hooks.c
e058006
@@ -3313,6 +3313,21 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
e058006
 	return 0;
e058006
 }
e058006
e058006
+static int selinux_inode_copy_up_xattr(const char *name)
e058006
+{
e058006
+	/* The copy_up hook above sets the initial context on an inode, but we
e058006
+	 * don't then want to overwrite it by blindly copying all the lower
e058006
+	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
e058006
+	 */
e058006
+	if (strcmp(name, XATTR_NAME_SELINUX) == 0)
e058006
+		return 1; /* Discard */
e058006
+	/*
e058006
+	 * Any other attribute apart from SELINUX is not claimed, supported
e058006
+	 * by selinux.
e058006
+	 */
e058006
+	return -EOPNOTSUPP;
e058006
+}
e058006
+
e058006
 /* file security operations */
e058006
e058006
 static int selinux_revalidate_file_permission(struct file *file, int mask)
e058006
@@ -6109,6 +6124,7 @@ static struct security_hook_list selinux_hooks[] = {
e058006
 	LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
e058006
 	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
e058006
 	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
e058006
+	LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
e058006
e058006
 	LSM_HOOK_INIT(file_permission, selinux_file_permission),
e058006
 	LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
e058006
-- 
e058006
2.7.4
e058006
e058006
From c957f6df52c509ccfbb96659fd1a0f7812de333f Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:51 -0400
e058006
Subject: [PATCH 07/10] selinux: Pass security pointer to
e058006
 determine_inode_label()
e058006
e058006
Right now selinux_determine_inode_label() works on security pointer of
e058006
current task. Soon I need this to work on a security pointer retrieved
e058006
from a set of creds. So start passing in a pointer and caller can
e058006
decide where to fetch security pointer from.
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/selinux/hooks.c | 19 ++++++++++---------
e058006
 1 file changed, 10 insertions(+), 9 deletions(-)
e058006
e058006
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
e058006
index a2d5108..f9d398b 100644
e058006
--- a/security/selinux/hooks.c
e058006
+++ b/security/selinux/hooks.c
e058006
@@ -1808,13 +1808,13 @@ out:
e058006
 /*
e058006
  * Determine the label for an inode that might be unioned.
e058006
  */
e058006
-static int selinux_determine_inode_label(struct inode *dir,
e058006
-					 const struct qstr *name,
e058006
-					 u16 tclass,
e058006
-					 u32 *_new_isid)
e058006
+static int
e058006
+selinux_determine_inode_label(const struct task_security_struct *tsec,
e058006
+				 struct inode *dir,
e058006
+				 const struct qstr *name, u16 tclass,
e058006
+				 u32 *_new_isid)
e058006
 {
e058006
 	const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
e058006
-	const struct task_security_struct *tsec = current_security();
e058006
e058006
 	if ((sbsec->flags & SE_SBINITIALIZED) &&
e058006
 	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
e058006
@@ -1857,8 +1857,8 @@ static int may_create(struct inode *dir,
e058006
 	if (rc)
e058006
 		return rc;
e058006
e058006
-	rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
e058006
-					   &newsid);
e058006
+	rc = selinux_determine_inode_label(current_security(), dir,
e058006
+					   &dentry->d_name, tclass, &newsid);
e058006
 	if (rc)
e058006
 		return rc;
e058006
e058006
@@ -2838,7 +2838,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
e058006
 	u32 newsid;
e058006
 	int rc;
e058006
e058006
-	rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
e058006
+	rc = selinux_determine_inode_label(current_security(),
e058006
+					   d_inode(dentry->d_parent), name,
e058006
 					   inode_mode_to_security_class(mode),
e058006
 					   &newsid);
e058006
 	if (rc)
e058006
@@ -2863,7 +2864,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
e058006
 	sid = tsec->sid;
e058006
 	newsid = tsec->create_sid;
e058006
e058006
-	rc = selinux_determine_inode_label(
e058006
+	rc = selinux_determine_inode_label(current_security(),
e058006
 		dir, qstr,
e058006
 		inode_mode_to_security_class(inode->i_mode),
e058006
 		&newsid);
e058006
-- 
e058006
2.7.4
e058006
e058006
From 2602625b7e46576b00db619ac788c508ba3bcb2c Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:52 -0400
e058006
Subject: [PATCH 08/10] security, overlayfs: Provide hook to correctly label
e058006
 newly created files
e058006
e058006
During a new file creation we need to make sure new file is created with the
e058006
right label. New file is created in upper/ so effectively file should get
e058006
label as if task had created file in upper/.
e058006
e058006
We switched to mounter's creds for actual file creation. Also if there is a
e058006
whiteout present, then file will be created in work/ dir first and then
e058006
renamed in upper. In none of the cases file will be labeled as we want it to
e058006
be.
e058006
e058006
This patch introduces a new hook dentry_create_files_as(), which determines
e058006
the label/context dentry will get if it had been created by task in upper
e058006
and modify passed set of creds appropriately. Caller makes use of these new
e058006
creds for file creation.
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
[PM: fix whitespace issues found with checkpatch.pl]
e058006
[PM: changes to use stat->mode in ovl_create_or_link()]
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 fs/overlayfs/dir.c        | 10 ++++++++++
e058006
 include/linux/lsm_hooks.h | 15 +++++++++++++++
e058006
 include/linux/security.h  | 12 ++++++++++++
e058006
 security/security.c       | 11 +++++++++++
e058006
 4 files changed, 48 insertions(+)
e058006
e058006
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
e058006
index 12bcd07..a155e52 100644
e058006
--- a/fs/overlayfs/dir.c
e058006
+++ b/fs/overlayfs/dir.c
e058006
@@ -435,6 +435,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
e058006
 	if (override_cred) {
e058006
 		override_cred->fsuid = inode->i_uid;
e058006
 		override_cred->fsgid = inode->i_gid;
e058006
+		if (!hardlink) {
e058006
+			err = security_dentry_create_files_as(dentry,
e058006
+					stat->mode, &dentry->d_name, old_cred,
e058006
+					override_cred);
e058006
+			if (err) {
e058006
+				put_cred(override_cred);
e058006
+				goto out_revert_creds;
e058006
+			}
e058006
+		}
e058006
 		put_cred(override_creds(override_cred));
e058006
 		put_cred(override_cred);
e058006
e058006
@@ -445,6 +454,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
e058006
 			err = ovl_create_over_whiteout(dentry, inode, stat,
e058006
 							link, hardlink);
e058006
 	}
e058006
+out_revert_creds:
e058006
 	revert_creds(old_cred);
e058006
 	if (!err) {
e058006
 		struct inode *realinode = d_inode(ovl_dentry_upper(dentry));
e058006
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
e058006
index 5797122..f2af2af 100644
e058006
--- a/include/linux/lsm_hooks.h
e058006
+++ b/include/linux/lsm_hooks.h
e058006
@@ -151,6 +151,16 @@
e058006
  *	@name name of the last path component used to create file
e058006
  *	@ctx pointer to place the pointer to the resulting context in.
e058006
  *	@ctxlen point to place the length of the resulting context.
e058006
+ * @dentry_create_files_as:
e058006
+ *	Compute a context for a dentry as the inode is not yet available
e058006
+ *	and set that context in passed in creds so that new files are
e058006
+ *	created using that context. Context is calculated using the
e058006
+ *	passed in creds and not the creds of the caller.
e058006
+ *	@dentry dentry to use in calculating the context.
e058006
+ *	@mode mode used to determine resource type.
e058006
+ *	@name name of the last path component used to create file
e058006
+ *	@old creds which should be used for context calculation
e058006
+ *	@new creds to modify
e058006
  *
e058006
  *
e058006
  * Security hooks for inode operations.
e058006
@@ -1375,6 +1385,10 @@ union security_list_options {
e058006
 	int (*dentry_init_security)(struct dentry *dentry, int mode,
e058006
 					const struct qstr *name, void **ctx,
e058006
 					u32 *ctxlen);
e058006
+	int (*dentry_create_files_as)(struct dentry *dentry, int mode,
e058006
+					struct qstr *name,
e058006
+					const struct cred *old,
e058006
+					struct cred *new);
e058006
e058006
e058006
 #ifdef CONFIG_SECURITY_PATH
e058006
@@ -1675,6 +1689,7 @@ struct security_hook_heads {
e058006
 	struct list_head sb_clone_mnt_opts;
e058006
 	struct list_head sb_parse_opts_str;
e058006
 	struct list_head dentry_init_security;
e058006
+	struct list_head dentry_create_files_as;
e058006
 #ifdef CONFIG_SECURITY_PATH
e058006
 	struct list_head path_unlink;
e058006
 	struct list_head path_mkdir;
e058006
diff --git a/include/linux/security.h b/include/linux/security.h
e058006
index 536fafd..a6c6d5d 100644
e058006
--- a/include/linux/security.h
e058006
+++ b/include/linux/security.h
e058006
@@ -242,6 +242,10 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
e058006
 int security_dentry_init_security(struct dentry *dentry, int mode,
e058006
 					const struct qstr *name, void **ctx,
e058006
 					u32 *ctxlen);
e058006
+int security_dentry_create_files_as(struct dentry *dentry, int mode,
e058006
+					struct qstr *name,
e058006
+					const struct cred *old,
e058006
+					struct cred *new);
e058006
e058006
 int security_inode_alloc(struct inode *inode);
e058006
 void security_inode_free(struct inode *inode);
e058006
@@ -600,6 +604,14 @@ static inline int security_dentry_init_security(struct dentry *dentry,
e058006
 	return -EOPNOTSUPP;
e058006
 }
e058006
e058006
+static inline int security_dentry_create_files_as(struct dentry *dentry,
e058006
+						  int mode, struct qstr *name,
e058006
+						  const struct cred *old,
e058006
+						  struct cred *new)
e058006
+{
e058006
+	return 0;
e058006
+}
e058006
+
e058006
e058006
 static inline int security_inode_init_security(struct inode *inode,
e058006
 						struct inode *dir,
e058006
diff --git a/security/security.c b/security/security.c
e058006
index a9e2bb9..f825304 100644
e058006
--- a/security/security.c
e058006
+++ b/security/security.c
e058006
@@ -364,6 +364,15 @@ int security_dentry_init_security(struct dentry *dentry, int mode,
e058006
 }
e058006
 EXPORT_SYMBOL(security_dentry_init_security);
e058006
e058006
+int security_dentry_create_files_as(struct dentry *dentry, int mode,
e058006
+				    struct qstr *name,
e058006
+				    const struct cred *old, struct cred *new)
e058006
+{
e058006
+	return call_int_hook(dentry_create_files_as, 0, dentry, mode,
e058006
+				name, old, new);
e058006
+}
e058006
+EXPORT_SYMBOL(security_dentry_create_files_as);
e058006
+
e058006
 int security_inode_init_security(struct inode *inode, struct inode *dir,
e058006
 				 const struct qstr *qstr,
e058006
 				 const initxattrs initxattrs, void *fs_data)
e058006
@@ -1635,6 +1644,8 @@ struct security_hook_heads security_hook_heads = {
e058006
 		LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
e058006
 	.dentry_init_security =
e058006
 		LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
e058006
+	.dentry_create_files_as =
e058006
+		LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as),
e058006
 #ifdef CONFIG_SECURITY_PATH
e058006
 	.path_unlink =	LIST_HEAD_INIT(security_hook_heads.path_unlink),
e058006
 	.path_mkdir =	LIST_HEAD_INIT(security_hook_heads.path_mkdir),
e058006
-- 
e058006
2.7.4
e058006
e058006
From a518b0a5b0d7f3397e065acb956bca9635aa892d Mon Sep 17 00:00:00 2001
e058006
From: Vivek Goyal <vgoyal@redhat.com>
e058006
Date: Wed, 13 Jul 2016 10:44:53 -0400
e058006
Subject: [PATCH 09/10] selinux: Implement dentry_create_files_as() hook
e058006
e058006
Calculate what would be the label of newly created file and set that
e058006
secid in the passed creds.
e058006
e058006
Context of the task which is actually creating file is retrieved from
e058006
set of creds passed in. (old->security).
e058006
e058006
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
e058006
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/selinux/hooks.c | 22 ++++++++++++++++++++++
e058006
 1 file changed, 22 insertions(+)
e058006
e058006
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
e058006
index f9d398b..e15e560 100644
e058006
--- a/security/selinux/hooks.c
e058006
+++ b/security/selinux/hooks.c
e058006
@@ -2848,6 +2848,27 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
e058006
 	return security_sid_to_context(newsid, (char **)ctx, ctxlen);
e058006
 }
e058006
e058006
+static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
e058006
+					  struct qstr *name,
e058006
+					  const struct cred *old,
e058006
+					  struct cred *new)
e058006
+{
e058006
+	u32 newsid;
e058006
+	int rc;
e058006
+	struct task_security_struct *tsec;
e058006
+
e058006
+	rc = selinux_determine_inode_label(old->security,
e058006
+					   d_inode(dentry->d_parent), name,
e058006
+					   inode_mode_to_security_class(mode),
e058006
+					   &newsid);
e058006
+	if (rc)
e058006
+		return rc;
e058006
+
e058006
+	tsec = new->security;
e058006
+	tsec->create_sid = newsid;
e058006
+	return 0;
e058006
+}
e058006
+
e058006
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
e058006
 				       const struct qstr *qstr,
e058006
 				       const char **name,
e058006
@@ -6098,6 +6119,7 @@ static struct security_hook_list selinux_hooks[] = {
e058006
 	LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
e058006
e058006
 	LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
e058006
+	LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
e058006
e058006
 	LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
e058006
 	LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
e058006
-- 
e058006
2.7.4
e058006
e058006
From 348a0db9e69e4c214bf5d7677f17cb99cdc47db0 Mon Sep 17 00:00:00 2001
e058006
From: William Roberts <william.c.roberts@intel.com>
e058006
Date: Mon, 15 Aug 2016 12:42:12 -0700
e058006
Subject: [PATCH 10/10] selinux: drop SECURITY_SELINUX_POLICYDB_VERSION_MAX
e058006
e058006
Remove the SECURITY_SELINUX_POLICYDB_VERSION_MAX Kconfig option
e058006
e058006
Per: https://github.com/SELinuxProject/selinux/wiki/Kernel-Todo
e058006
e058006
This was only needed on Fedora 3 and 4 and just causes issues now,
e058006
so drop it.
e058006
e058006
The MAX and MIN should just be whatever the kernel can support.
e058006
e058006
Signed-off-by: William Roberts <william.c.roberts@intel.com>
e058006
Signed-off-by: Paul Moore <paul@paul-moore.com>
e058006
---
e058006
 security/selinux/Kconfig            | 38 -------------------------------------
e058006
 security/selinux/include/security.h |  4 ----
e058006
 2 files changed, 42 deletions(-)
e058006
e058006
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
e058006
index 8691e92..ea7e3ef 100644
e058006
--- a/security/selinux/Kconfig
e058006
+++ b/security/selinux/Kconfig
e058006
@@ -93,41 +93,3 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
e058006
 	  via /selinux/checkreqprot if authorized by policy.
e058006
e058006
 	  If you are unsure how to answer this question, answer 0.
e058006
-
e058006
-config SECURITY_SELINUX_POLICYDB_VERSION_MAX
e058006
-	bool "NSA SELinux maximum supported policy format version"
e058006
-	depends on SECURITY_SELINUX
e058006
-	default n
e058006
-	help
e058006
-	  This option enables the maximum policy format version supported
e058006
-	  by SELinux to be set to a particular value.  This value is reported
e058006
-	  to userspace via /selinux/policyvers and used at policy load time.
e058006
-	  It can be adjusted downward to support legacy userland (init) that
e058006
-	  does not correctly handle kernels that support newer policy versions.
e058006
-
e058006
-	  Examples:
e058006
-	  For the Fedora Core 3 or 4 Linux distributions, enable this option
e058006
-	  and set the value via the next option. For Fedora Core 5 and later,
e058006
-	  do not enable this option.
e058006
-
e058006
-	  If you are unsure how to answer this question, answer N.
e058006
-
e058006
-config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
e058006
-	int "NSA SELinux maximum supported policy format version value"
e058006
-	depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
e058006
-	range 15 23
e058006
-	default 19
e058006
-	help
e058006
-	  This option sets the value for the maximum policy format version
e058006
-	  supported by SELinux.
e058006
-
e058006
-	  Examples:
e058006
-	  For Fedora Core 3, use 18.
e058006
-	  For Fedora Core 4, use 19.
e058006
-
e058006
-	  If you are unsure how to answer this question, look for the
e058006
-	  policy format version supported by your policy toolchain, by
e058006
-	  running 'checkpolicy -V'. Or look at what policy you have
e058006
-	  installed under /etc/selinux/$SELINUXTYPE/policy, where
e058006
-	  SELINUXTYPE is defined in your /etc/selinux/config.
e058006
-
e058006
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
e058006
index 38feb55..308a286 100644
e058006
--- a/security/selinux/include/security.h
e058006
+++ b/security/selinux/include/security.h
e058006
@@ -39,11 +39,7 @@
e058006
e058006
 /* Range of policy versions we understand*/
e058006
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
e058006
-#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
e058006
-#define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
e058006
-#else
e058006
 #define POLICYDB_VERSION_MAX	POLICYDB_VERSION_XPERMS_IOCTL
e058006
-#endif
e058006
e058006
 /* Mask for just the mount related flags */
e058006
 #define SE_MNTMASK	0x0f
e058006
-- 
e058006
2.7.4
e058006