selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/97] LSM: Complete module stacking
@ 2019-02-28 22:43 Casey Schaufler
  2019-02-28 22:43 ` [PATCH 71/97] LSM: Add secmark refcounting to call_one list Casey Schaufler
                   ` (26 more replies)
  0 siblings, 27 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

This is a preliminary version of the complete stacking
implementation. The patches need to be cleaned up, and
several are not strictly necessary. There is likely to
be work required in the audit sub-system. It does address
all the shared data, including CIPSO headers. It should
handle CALIPSO once Smack supports it. I will be revising
the set after 5.1.

Complete the transition from module based blob management
to infrastructure based blob management. This includes
the socket, superblock and key blobs.

Change the LSM infrastructure from exposing secids to
exposing an opaque "lsm_export" structure that can contain
information for multiple active security modules. Update
all of the security modules to use information from the
lsm_export structure. Update the LSM interfaces that expose
secids for more than one module to use the export structure.
Update all the users of these interfaces.

Change the LSM infrastructure from using a string/size pair
for security "contexts" to a "lsm_context" structure that
can represent information for multiple modules. This contains
information that allows the "context" to be properly freed
regardless of where it is allocated and where it is used.

Add an interface to identify which security module data
should be presented with SO_PEERSEC. /proc/.../attr/display
will set and report the name of the LSM for which the
security_secid_to_secctx() will use to translate to text.
If it is not explicitly set, the first security module that
supplies secid (now lsm_export) interfaces will be used.
To ensure consistency, a set of module hooks dealing with
the secid/context processing is maintained with each process
that explicitly sets it.

Before sending a network packet verify that all interested
security modules agree on the labeling. Fail if the labeling
cannot be reconciled. This requires a new Netlabel interface
to compare proposed labels, and a change to the return values
from the existing netlabel attribute setting functions.

git://github.com/cschaufler/lsm-stacking.git#5.0-rc3-plus-a

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 fs/kernfs/dir.c                                    |   6 +-
 fs/kernfs/inode.c                                  |  31 +-
 fs/kernfs/kernfs-internal.h                        |   4 +-
 fs/nfs/inode.c                                     |  13 +-
 fs/nfs/internal.h                                  |   8 +-
 fs/nfs/nfs4proc.c                                  |  17 +-
 fs/nfs/nfs4xdr.c                                   |  16 +-
 fs/nfsd/nfs4proc.c                                 |   8 +-
 fs/nfsd/nfs4xdr.c                                  |  14 +-
 fs/nfsd/vfs.c                                      |   7 +-
 fs/proc/base.c                                     |   1 +
 include/linux/cred.h                               |   3 +-
 include/linux/lsm_hooks.h                          | 122 ++--
 include/linux/nfs4.h                               |   8 +-
 include/linux/security.h                           | 165 +++--
 include/net/netlabel.h                             |  18 +-
 include/net/route.h                                |  55 +-
 include/net/scm.h                                  |  14 +-
 include/net/sock.h                                 |  14 +-
 include/uapi/linux/netfilter/xt_CONNMARK.h         |  45 +-
 include/uapi/linux/netfilter/xt_DSCP.h             |  27 +-
 include/uapi/linux/netfilter/xt_MARK.h             |  17 +-
 include/uapi/linux/netfilter/xt_RATEEST.h          |  38 +-
 include/uapi/linux/netfilter/xt_TCPMSS.h           |  13 +-
 include/uapi/linux/netfilter_ipv4/ipt_ECN.h        |  40 +-
 include/uapi/linux/netfilter_ipv4/ipt_TTL.h        |  14 +-
 include/uapi/linux/netfilter_ipv6/ip6t_HL.h        |  14 +-
 kernel/audit.c                                     |  60 +-
 kernel/audit.h                                     |   9 +-
 kernel/auditfilter.c                               |   6 +-
 kernel/auditsc.c                                   |  61 +-
 kernel/cred.c                                      |  15 +-
 net/ipv4/cipso_ipv4.c                              |  13 +-
 net/ipv4/ip_sockglue.c                             |  14 +-
 net/ipv4/route.c                                   |  61 ++
 net/netfilter/nf_conntrack_netlink.c               |  27 +-
 net/netfilter/nf_conntrack_standalone.c            |  16 +-
 net/netfilter/nfnetlink_queue.c                    |  35 +-
 net/netfilter/nft_meta.c                           |   8 +-
 net/netfilter/xt_DSCP.c                            | 149 ++---
 net/netfilter/xt_HL.c                              | 164 ++---
 net/netfilter/xt_RATEEST.c                         | 278 +++------
 net/netfilter/xt_SECMARK.c                         |   9 +-
 net/netfilter/xt_TCPMSS.c                          | 378 +++---------
 net/netlabel/netlabel_kapi.c                       | 125 +++-
 net/netlabel/netlabel_unlabeled.c                  |  99 ++-
 net/netlabel/netlabel_unlabeled.h                  |   2 +-
 net/netlabel/netlabel_user.c                       |  13 +-
 net/netlabel/netlabel_user.h                       |   2 +-
 net/socket.c                                       |  17 +
 net/unix/af_unix.c                                 |  11 +-
 security/apparmor/audit.c                          |   4 +-
 security/apparmor/include/audit.h                  |   2 +-
 security/apparmor/include/net.h                    |   6 +-
 security/apparmor/include/secid.h                  |   9 +-
 security/apparmor/lsm.c                            |  64 +-
 security/apparmor/secid.c                          |  42 +-
 security/integrity/ima/ima.h                       |  14 +-
 security/integrity/ima/ima_api.c                   |   9 +-
 security/integrity/ima/ima_appraise.c              |   6 +-
 security/integrity/ima/ima_main.c                  |  34 +-
 security/integrity/ima/ima_policy.c                |  19 +-
 security/security.c                                | 682 ++++++++++++++++++---
 security/selinux/hooks.c                           | 308 +++++-----
 security/selinux/include/audit.h                   |   6 +-
 security/selinux/include/netlabel.h                |   7 +
 security/selinux/include/objsec.h                  |  43 +-
 security/selinux/netlabel.c                        |  69 ++-
 security/selinux/ss/services.c                     |  19 +-
 security/smack/smack.h                             |  34 +
 security/smack/smack_access.c                      |  14 +-
 security/smack/smack_lsm.c                         | 389 ++++++------
 security/smack/smack_netfilter.c                   |  48 +-
 security/smack/smackfs.c                           |  23 +-
 .../Z6.0+pooncelock+poonceLock+pombonce.litmus     |  12 +-
 75 files changed, 2369 insertions(+), 1798 deletions(-)

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

* [PATCH 71/97] LSM: Add secmark refcounting to call_one list
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 72/97] LSM: Add secmark refcounting to call_one list - part 2 Casey Schaufler
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add secmark_refcount_dec and secmark_refcount_inc to the
LSM hooks for which only the designated module is called.
This is in support of consistant secmark behavior.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hooks.h |  2 ++
 security/security.c       | 42 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index e76e5cd05180..4020e13f0669 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2029,6 +2029,8 @@ struct lsm_one_hooks {
 	union security_list_options secctx_to_secid;
 	union security_list_options socket_getpeersec_stream;
 	union security_list_options secmark_relabel_packet;
+	union security_list_options secmark_refcount_inc;
+	union security_list_options secmark_refcount_dec;
 };
 
 /*
diff --git a/security/security.c b/security/security.c
index 024601db215e..af3f6a89ee88 100644
--- a/security/security.c
+++ b/security/security.c
@@ -472,6 +472,12 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
 		else if (hooks[i].head ==
 				&security_hook_heads.secmark_relabel_packet)
 			lsm_base_one.secmark_relabel_packet = hooks[i].hook;
+		else if (hooks[i].head ==
+				&security_hook_heads.secmark_refcount_inc)
+			lsm_base_one.secmark_refcount_inc = hooks[i].hook;
+		else if (hooks[i].head ==
+				&security_hook_heads.secmark_refcount_dec)
+			lsm_base_one.secmark_refcount_dec = hooks[i].hook;
 		else
 			continue;
 		if (lsm_base_one.lsm == NULL)
@@ -752,6 +758,14 @@ int lsm_superblock_alloc(struct super_block *sb)
 	RC;							\
 })
 
+#define call_one_void_hook(FUNC, ...) ({			\
+	struct lsm_one_hooks *LOH = current_cred()->security;	\
+	if (LOH->FUNC.FUNC)					\
+		LOH->FUNC.FUNC(__VA_ARGS__);			\
+	else if (LOH->lsm == NULL && lsm_base_one.FUNC.FUNC)	\
+		lsm_base_one.FUNC.FUNC(__VA_ARGS__);		\
+})
+
 #define call_one_int_hook(FUNC, IRC, ...) ({			\
 	int RC = IRC;						\
 	struct lsm_one_hooks *LOH = current_cred()->security;	\
@@ -2022,6 +2036,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 		union security_list_options secctx_to_secid;
 		union security_list_options socket_getpeersec_stream;
 		union security_list_options secmark_relabel_packet;
+		union security_list_options secmark_refcount_inc;
+		union security_list_options secmark_refcount_dec;
 
 		if (size == 0 || size >= 100)
 			return -EINVAL;
@@ -2068,6 +2084,28 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 				break;
 			}
 		}
+		secmark_refcount_inc.secmark_refcount_inc = NULL;
+		hlist_for_each_entry(hp,
+				&security_hook_heads.secmark_refcount_inc,
+				     list) {
+			if (size >= strlen(hp->lsm) &&
+			    !strncmp(value, hp->lsm, size)) {
+				secmark_refcount_inc = hp->hook;
+				found = true;
+				break;
+			}
+		}
+		secmark_refcount_dec.secmark_refcount_dec = NULL;
+		hlist_for_each_entry(hp,
+				&security_hook_heads.secmark_refcount_dec,
+				     list) {
+			if (size >= strlen(hp->lsm) &&
+			    !strncmp(value, hp->lsm, size)) {
+				secmark_refcount_dec = hp->hook;
+				found = true;
+				break;
+			}
+		}
 		if (!found)
 			return -EINVAL;
 
@@ -2339,13 +2377,13 @@ EXPORT_SYMBOL(security_secmark_relabel_packet);
 
 void security_secmark_refcount_inc(void)
 {
-	call_void_hook(secmark_refcount_inc);
+	call_one_void_hook(secmark_refcount_inc);
 }
 EXPORT_SYMBOL(security_secmark_refcount_inc);
 
 void security_secmark_refcount_dec(void)
 {
-	call_void_hook(secmark_refcount_dec);
+	call_one_void_hook(secmark_refcount_dec);
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);
 
-- 
2.17.0


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

* [PATCH 72/97] LSM: Add secmark refcounting to call_one list - part 2
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
  2019-02-28 22:43 ` [PATCH 71/97] LSM: Add secmark refcounting to call_one list Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 73/97] LSM: refactor security_setprocattr Casey Schaufler
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add secmark_refcount_dec and secmark_refcount_inc to the
LSM hooks for which only the designated module is called.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/security/security.c b/security/security.c
index af3f6a89ee88..fc446af4c3bf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2125,6 +2125,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 		loh->secctx_to_secid = secctx_to_secid;
 		loh->socket_getpeersec_stream = socket_getpeersec_stream;
 		loh->secmark_relabel_packet = secmark_relabel_packet;
+		loh->secmark_refcount_inc = secmark_refcount_inc;
+		loh->secmark_refcount_dec = secmark_refcount_dec;
 
 		return size;
 	}
-- 
2.17.0


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

* [PATCH 73/97] LSM: refactor security_setprocattr
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
  2019-02-28 22:43 ` [PATCH 71/97] LSM: Add secmark refcounting to call_one list Casey Schaufler
  2019-02-28 22:43 ` [PATCH 72/97] LSM: Add secmark refcounting to call_one list - part 2 Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 74/97] Smack: Detect if secmarks can be safely used Casey Schaufler
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Break the common code for setting the lsm_one hooks into
helper function.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c | 120 ++++++++++++++++----------------------------
 1 file changed, 43 insertions(+), 77 deletions(-)

diff --git a/security/security.c b/security/security.c
index fc446af4c3bf..66bc1a580d48 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2016,12 +2016,31 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
 	return -EINVAL;
 }
 
+/*
+ * The use of the secid_to_secctx memeber of the union is
+ * arbitrary. Any member would work.
+ */
+static bool lsm_add_one(union security_list_options *hook,
+			struct hlist_head *head, char *lsm, size_t size,
+			bool was)
+{
+	struct security_hook_list *hp;
+
+	hlist_for_each_entry(hp, head, list) {
+		if (size >= strlen(hp->lsm) && !strncmp(lsm, hp->lsm, size)) {
+			hook->secid_to_secctx = hp->hook.secid_to_secctx;
+			return true;
+		}
+	}
+	hook->secid_to_secctx = NULL;
+	return was;
+}
+
 int security_setprocattr(const char *lsm, const char *name, void *value,
 			 size_t size)
 {
 	struct security_hook_list *hp;
 	struct lsm_one_hooks *loh = current_cred()->security;
-	bool found = false;
 	char *s;
 
 	/*
@@ -2032,80 +2051,31 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 		*s = '\0';
 
 	if (!strcmp(name, "display")) {
-		union security_list_options secid_to_secctx;
-		union security_list_options secctx_to_secid;
-		union security_list_options socket_getpeersec_stream;
-		union security_list_options secmark_relabel_packet;
-		union security_list_options secmark_refcount_inc;
-		union security_list_options secmark_refcount_dec;
+		struct lsm_one_hooks o;
+		bool found = false;
 
 		if (size == 0 || size >= 100)
 			return -EINVAL;
 
-		secid_to_secctx.secid_to_secctx = NULL;
-		hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				secid_to_secctx = hp->hook;
-				found = true;
-				break;
-			}
-		}
-		secctx_to_secid.secctx_to_secid = NULL;
-		hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				secctx_to_secid = hp->hook;
-				found = true;
-				break;
-			}
-		}
-		socket_getpeersec_stream.socket_getpeersec_stream = NULL;
-		hlist_for_each_entry(hp,
-				&security_hook_heads.socket_getpeersec_stream,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				socket_getpeersec_stream = hp->hook;
-				found = true;
-				break;
-			}
-		}
-		secmark_relabel_packet.secmark_relabel_packet = NULL;
-		hlist_for_each_entry(hp,
-				&security_hook_heads.secmark_relabel_packet,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				secmark_relabel_packet = hp->hook;
-				found = true;
-				break;
-			}
-		}
-		secmark_refcount_inc.secmark_refcount_inc = NULL;
-		hlist_for_each_entry(hp,
-				&security_hook_heads.secmark_refcount_inc,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				secmark_refcount_inc = hp->hook;
-				found = true;
-				break;
-			}
-		}
-		secmark_refcount_dec.secmark_refcount_dec = NULL;
-		hlist_for_each_entry(hp,
-				&security_hook_heads.secmark_refcount_dec,
-				     list) {
-			if (size >= strlen(hp->lsm) &&
-			    !strncmp(value, hp->lsm, size)) {
-				secmark_refcount_dec = hp->hook;
-				found = true;
-				break;
-			}
-		}
+		found = lsm_add_one(&o.secid_to_secctx,
+				    &security_hook_heads.secid_to_secctx,
+				    value, size, found);
+		found = lsm_add_one(&o.secctx_to_secid,
+				    &security_hook_heads.secctx_to_secid,
+				    value, size, found);
+		found = lsm_add_one(&o.socket_getpeersec_stream,
+				 &security_hook_heads.socket_getpeersec_stream,
+				    value, size, found);
+		found = lsm_add_one(&o.secmark_relabel_packet,
+				    &security_hook_heads.secmark_relabel_packet,
+				    value, size, found);
+		found = lsm_add_one(&o.secmark_refcount_inc,
+				    &security_hook_heads.secmark_refcount_inc,
+				    value, size, found);
+		found = lsm_add_one(&o.secmark_refcount_dec,
+				    &security_hook_heads.secmark_refcount_dec,
+				    value, size, found);
+
 		if (!found)
 			return -EINVAL;
 
@@ -2120,13 +2090,9 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 
 		if (loh->lsm)
 			kfree(loh->lsm);
+
+		*loh = o;
 		loh->lsm = s;
-		loh->secid_to_secctx = secid_to_secctx;
-		loh->secctx_to_secid = secctx_to_secid;
-		loh->socket_getpeersec_stream = socket_getpeersec_stream;
-		loh->secmark_relabel_packet = secmark_relabel_packet;
-		loh->secmark_refcount_inc = secmark_refcount_inc;
-		loh->secmark_refcount_dec = secmark_refcount_dec;
 
 		return size;
 	}
-- 
2.17.0


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

* [PATCH 74/97] Smack: Detect if secmarks can be safely used
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (2 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 73/97] LSM: refactor security_setprocattr Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 75/97] LSM: Support multiple LSMs using inode_init_security Casey Schaufler
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Utilize the security_secmark_refcount_in() hooks to determine
if Smack can safely assume that IP secmarks are not being used
by another LSM. Only use secmarks if they can be determined to
belong to Smack.

[cschaufler@localhost lsm-stacking]$ head -30 ../from-lap-190128/0073*
From 796ddbf9da8e0e8180805591badf182d2578ed5a Mon Sep 17 00:00:00 2001
From: Casey Schaufler <casey@schaufler-ca.com>
Date: Thu, 3 Jan 2019 15:56:59 -0800
Subject: [PATCH 73/79] Smack: Detect if secmarks can be safely used

Utilize the security_secmark_refcount_in() hooks to determine
if Smack can safely assume that IP secmarks are not being used
by another LSM. Only use secmarks if they can be determined to
belong to Smack.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack.h           | 15 +++++++++++++++
 security/smack/smack_lsm.c       | 16 +++++-----------
 security/smack/smack_netfilter.c | 25 +++++++++++++++++++++++--
 3 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/security/smack/smack.h b/security/smack/smack.h
index f623d059421d..147afb9233b4 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -553,4 +553,19 @@ static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
 }
 #endif
 
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+extern bool smack_use_secmark;
+void smack_secmark_refcount_inc(void);
+
+static inline bool smk_use_secmark(void)
+{
+	return smack_use_secmark;
+}
+#else
+static inline bool smk_use_secmark(void)
+{
+	return false;
+}
+#endif
+
 #endif  /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7b8ad16c09e0..c45e2dc3f959 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3742,7 +3742,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
  */
 static struct smack_known *smack_from_skb(struct sk_buff *skb)
 {
-	if (skb == NULL || skb->secmark == 0)
+	if (skb == NULL || skb->secmark == 0 || !smk_use_secmark())
 		return NULL;
 
 	return smack_from_secid(skb->secmark);
@@ -3776,7 +3776,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
 	switch (family) {
 	case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
 		/*
 		 * If there is a secmark use it rather than the CIPSO label.
 		 * If there is no secmark fall back to CIPSO.
@@ -3785,7 +3784,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 		skp = smack_from_skb(skb);
 		if (skp)
 			goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
 		/*
 		 * Translate what netlabel gave us.
 		 */
@@ -3799,9 +3797,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
 		netlbl_secattr_destroy(&secattr);
 
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
 access_check:
-#endif
+
 #ifdef CONFIG_AUDIT
 		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
 		ad.a.u.net->family = family;
@@ -3928,13 +3925,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
 		s = ssp->smk_out->smk_secid;
 		break;
 	case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
 		skp = smack_from_skb(skb);
 		if (skp) {
 			s = skp->smk_secid;
 			break;
 		}
-#endif
 		/*
 		 * Translate what netlabel gave us.
 		 */
@@ -4024,7 +4019,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 	}
 #endif /* CONFIG_IPV6 */
 
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
 	/*
 	 * If there is a secmark use it rather than the CIPSO label.
 	 * If there is no secmark fall back to CIPSO.
@@ -4033,7 +4027,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 	skp = smack_from_skb(skb);
 	if (skp)
 		goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
 
 	netlbl_secattr_init(&secattr);
 	rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -4043,9 +4036,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 		skp = &smack_known_huh;
 	netlbl_secattr_destroy(&secattr);
 
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
 access_check:
-#endif
 
 #ifdef CONFIG_AUDIT
 	smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
@@ -4620,6 +4611,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
 #ifdef SMACK_IPV6_PORT_LABELING
 	LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+#endif
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+	LSM_HOOK_INIT(secmark_refcount_inc, smack_secmark_refcount_inc),
 #endif
 	LSM_HOOK_INIT(sock_graft, smack_sock_graft),
 	LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 701a1cc1bdcc..ea45b173f8ca 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -21,6 +21,15 @@
 #include <net/net_namespace.h>
 #include "smack.h"
 
+bool smack_use_secmark;
+static bool smack_checked_secmark;
+
+void smack_secmark_refcount_inc(void)
+{
+        smack_use_secmark = true;
+	pr_info("Smack: Using network secmarks.\n");
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 
 static unsigned int smack_ipv6_output(void *priv,
@@ -31,7 +40,13 @@ static unsigned int smack_ipv6_output(void *priv,
 	struct socket_smack *ssp;
 	struct smack_known *skp;
 
-	if (sk && smack_sock(sk)) {
+	if (!smack_checked_secmark) {
+		security_secmark_refcount_inc();
+		security_secmark_refcount_dec();
+		smack_checked_secmark = true;
+	}
+
+	if (smack_use_secmark && sk && smack_sock(sk)) {
 		ssp = smack_sock(sk);
 		skp = ssp->smk_out;
 		skb->secmark = skp->smk_secid;
@@ -49,7 +64,13 @@ static unsigned int smack_ipv4_output(void *priv,
 	struct socket_smack *ssp;
 	struct smack_known *skp;
 
-	if (sk && smack_sock(sk)) {
+	if (!smack_checked_secmark) {
+		security_secmark_refcount_inc();
+		security_secmark_refcount_dec();
+		smack_checked_secmark = true;
+	}
+
+	if (smack_use_secmark && sk && smack_sock(sk)) {
 		ssp = smack_sock(sk);
 		skp = ssp->smk_out;
 		skb->secmark = skp->smk_secid;
-- 
2.17.0


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

* [PATCH 75/97] LSM: Support multiple LSMs using inode_init_security
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (3 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 74/97] Smack: Detect if secmarks can be safely used Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 76/97] LSM: Use full security context in security_inode_setsecctx Casey Schaufler
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Refactor security_inode_init_security() so that it can
do the integrity processing for more than one LSM.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c | 48 +++++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 19 deletions(-)

diff --git a/security/security.c b/security/security.c
index 66bc1a580d48..16ff98c86414 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1066,9 +1066,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 				 const struct qstr *qstr,
 				 const initxattrs initxattrs, void *fs_data)
 {
-	struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
-	struct xattr *lsm_xattr, *evm_xattr, *xattr;
-	int ret;
+	struct security_hook_list *p;
+	struct xattr *repo;
+	int rc;
+	int i;
 
 	if (unlikely(IS_PRIVATE(inode)))
 		return 0;
@@ -1076,24 +1077,33 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 	if (!initxattrs)
 		return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
 				     dir, qstr, NULL, NULL, NULL);
-	memset(new_xattrs, 0, sizeof(new_xattrs));
-	lsm_xattr = new_xattrs;
-	ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
-						&lsm_xattr->name,
-						&lsm_xattr->value,
-						&lsm_xattr->value_len);
-	if (ret)
-		goto out;
 
-	evm_xattr = lsm_xattr + 1;
-	ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
-	if (ret)
-		goto out;
-	ret = initxattrs(inode, new_xattrs, fs_data);
+	repo = kzalloc((LSM_COUNT * 2) * sizeof(*repo), GFP_NOFS);
+	if (repo == NULL)
+		return -ENOMEM;
+
+	i = 0;
+	rc = -EOPNOTSUPP;
+	hlist_for_each_entry(p, &security_hook_heads.inode_init_security,
+			     list) {
+		rc = p->hook.inode_init_security(inode, dir, qstr,
+						 &repo[i].name, &repo[i].value,
+						 &repo[i].value_len);
+		if (rc)
+			goto out;
+
+		rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
+		if (rc)
+			goto out;
+
+		i += 2;
+	}
+	rc = initxattrs(inode, repo, fs_data);
 out:
-	for (xattr = new_xattrs; xattr->value != NULL; xattr++)
-		kfree(xattr->value);
-	return (ret == -EOPNOTSUPP) ? 0 : ret;
+	for (i-- ; i >= 0; i--)
+		kfree(repo[i].value);
+	kfree(repo);
+	return (rc == -EOPNOTSUPP) ? 0 : rc;
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
-- 
2.17.0


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

* [PATCH 76/97] LSM: Use full security context in security_inode_setsecctx
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (4 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 75/97] LSM: Support multiple LSMs using inode_init_security Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 77/97] LSM: Correct handling of ENOSYS in inode_setxattr Casey Schaufler
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

The security hooks security_inode_setsecctx and security_inode_getsecctx
need to maintain the context strings for any and all LSMs that
provide contexts. This information is internal to the kernel
and volitile. If only one LSM uses this information the raw form is
used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 108 insertions(+), 2 deletions(-)

diff --git a/security/security.c b/security/security.c
index 16ff98c86414..bb0eea873a7e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -438,6 +438,9 @@ static int lsm_append(char *new, char **result)
 /* Base list of once-only hooks */
 struct lsm_one_hooks lsm_base_one;
 
+/* Count of inode_[gs]etsecctx hooks */
+static int lsm_inode_secctx_count;
+
 /**
  * security_add_hooks - Add a modules hooks to the hook lists.
  * @hooks: the hooks to add
@@ -455,6 +458,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
 		hooks[i].lsm = lsm;
 		hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
 
+		/*
+		 * Keep count of the internal security context using hooks.
+		 * Assume that there is a 1:1 mapping from inode_getsecctx
+		 * to inode_setsecctx in the security modules.
+		 */
+		if (hooks[i].head == &security_hook_heads.inode_getsecctx) {
+			lsm_inode_secctx_count++;
+			continue;
+		}
 		/*
 		 * Check for the special hooks that are restricted to
 		 * a single module to create the base set. Use the hooks
@@ -2162,15 +2174,109 @@ int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
 }
 EXPORT_SYMBOL(security_inode_notifysecctx);
 
+/*
+ * The inode_[gs]etsecctx functions need to proved a context
+ * for multiple security modules. If there is more than one
+ * LSM supplying hooks the format will be
+ *	lsm1='value',lsm2='value'[,lsmN='value']...
+ */
+static void lsm_release_secctx(struct lsm_context *cp)
+{
+	kfree(cp->context);
+}
+
 int security_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp)
 {
-	return call_int_hook(inode_setsecctx, 0, dentry, cp);
+	struct security_hook_list *hp;
+	struct lsm_context lc;
+	char *full;
+	char *ctx;
+	char *quote;
+	int rc = 0;
+
+	if (lsm_inode_secctx_count <= 1)
+		return call_int_hook(inode_setsecctx, 0, dentry, cp);
+
+	full = kstrndup(cp->context, cp->len, GFP_KERNEL);
+	if (full == NULL)
+		return -ENOMEM;
+
+	ctx = full;
+	hlist_for_each_entry(hp, &security_hook_heads.inode_setsecctx, list) {
+		if (strncmp(ctx, hp->lsm, strlen(hp->lsm))) {
+			WARN_ONCE(1, "security_inode_setsecctx form1 error\n");
+			rc = -EINVAL;
+			break;
+		}
+		ctx += strlen(hp->lsm);
+		if (ctx[0] != '=' || ctx[1] != '\'') {
+			WARN_ONCE(1, "security_inode_setsecctx form2 error\n");
+			rc = -EINVAL;
+			break;
+		}
+		ctx += 2;
+		quote = strnchr(ctx, cp->len, '\'');
+		if (quote == NULL) {
+			WARN_ONCE(1, "security_inode_setsecctx form3 error\n");
+			rc = -EINVAL;
+			break;
+		}
+		quote[0] = '\0';
+		if (quote[1] != ',' && quote[1] != '\0') {
+			WARN_ONCE(1, "security_inode_setsecctx form4 error\n");
+			rc = -EINVAL;
+			break;
+		}
+		lc.context = ctx;
+		lc.len = strlen(ctx);
+
+		ctx = quote + 2;
+
+		rc = hp->hook.inode_setsecctx(dentry, &lc);
+		if (rc)
+			break;
+	}
+
+	kfree(full);
+	return rc;
 }
 EXPORT_SYMBOL(security_inode_setsecctx);
 
 int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
 {
-	return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+	struct security_hook_list *hp;
+	struct lsm_context lc;
+	char *final = NULL;
+	char *tp;
+	int rc;
+
+	if (lsm_inode_secctx_count <= 1)
+		return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+
+	hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) {
+		rc = hp->hook.inode_getsecctx(inode, &lc);
+		if (rc) {
+			kfree(final);
+			return rc;
+		}
+		if (final) {
+			tp = kasprintf(GFP_KERNEL, "%s,%s='%s'", final,
+				       hp->lsm, lc.context);
+			kfree(final);
+		} else
+			tp = kasprintf(GFP_KERNEL, "%s='%s'", hp->lsm,
+				       lc.context);
+		security_release_secctx(&lc);
+		if (tp == NULL) {
+			kfree(final);
+			return -ENOMEM;
+		}
+		final = tp;
+	}
+	cp->context = final;
+	cp->len = strlen(final);
+	cp->release = lsm_release_secctx;
+	return 0;
 }
 EXPORT_SYMBOL(security_inode_getsecctx);
 
-- 
2.17.0


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

* [PATCH 77/97] LSM: Correct handling of ENOSYS in inode_setxattr
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (5 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 76/97] LSM: Use full security context in security_inode_setsecctx Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 78/97] LSM: Infrastructure security blobs for mount options Casey Schaufler
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

The usual "bail on fail" behavior of LSM hooks doesn't
work for security_inode_setxattr(). Modules are allowed
to return -ENOSYS if the attribute specifed isn't one
they manage. Fix the code to accomodate this unusal case.
This requires changes to the hooks in SELinux and Smack.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c        | 28 ++++++++++++++--------------
 security/selinux/hooks.c   |  7 ++-----
 security/smack/smack_lsm.c | 10 +++++-----
 3 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/security/security.c b/security/security.c
index bb0eea873a7e..105b5ee22bcf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1343,24 +1343,24 @@ int security_inode_getattr(const struct path *path)
 int security_inode_setxattr(struct dentry *dentry, const char *name,
 			    const void *value, size_t size, int flags)
 {
-	int ret;
+	struct security_hook_list *hp;
+	int rc = -ENOSYS;
 
 	if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
 		return 0;
-	/*
-	 * SELinux and Smack integrate the cap call,
-	 * so assume that all LSMs supplying this call do so.
-	 */
-	ret = call_int_hook(inode_setxattr, 1, dentry, name, value, size,
-				flags);
 
-	if (ret == 1)
-		ret = cap_inode_setxattr(dentry, name, value, size, flags);
-	if (ret)
-		return ret;
-	ret = ima_inode_setxattr(dentry, name, value, size);
-	if (ret)
-		return ret;
+	hlist_for_each_entry(hp, &security_hook_heads.inode_setxattr, list) {
+		rc = hp->hook.inode_setxattr(dentry, name, value, size, flags);
+		if (rc != -ENOSYS)
+			break;
+	}
+	if (rc == -ENOSYS)
+		rc = cap_inode_setxattr(dentry, name, value, size, flags);
+	if (rc)
+		return rc;
+	rc = ima_inode_setxattr(dentry, name, value, size);
+	if (rc)
+		return rc;
 	return evm_inode_setxattr(dentry, name, value, size);
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f58c96e2b6c1..501aed18f100 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2998,13 +2998,10 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 	int rc = 0;
 
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
-		rc = cap_inode_setxattr(dentry, name, value, size, flags);
-		if (rc)
-			return rc;
-
 		/* Not an attribute we recognize, so just check the
 		   ordinary setattr permission. */
-		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
+		rc = dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
+		return rc ? rc : -ENOSYS;
 	}
 
 	sbsec = selinux_superblock(inode->i_sb);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c45e2dc3f959..c84c71a31b80 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1194,7 +1194,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 		    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
 			rc = -EINVAL;
 	} else
-		rc = cap_inode_setxattr(dentry, name, value, size, flags);
+		rc = -ENOSYS;
 
 	if (check_priv && !smack_privileged(CAP_MAC_ADMIN))
 		rc = -EPERM;
@@ -1208,11 +1208,11 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 			rc = -EINVAL;
 	}
 
-	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
-	smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
 	if (rc == 0) {
-		rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+		smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
+		smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+		rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)),
+				MAY_WRITE, &ad);
 		rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
 	}
 
-- 
2.17.0


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

* [PATCH 78/97] LSM: Infrastructure security blobs for mount options
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (6 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 77/97] LSM: Correct handling of ENOSYS in inode_setxattr Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 79/97] LSM: Fix for security_init_inode_security Casey Schaufler
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Manage LSM data for mount options in the infrastructure
rather than in the individual modules.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hooks.h  |  5 +++++
 security/security.c        | 18 ++++++++++++++++++
 security/selinux/hooks.c   | 31 ++++++++++++++++++-------------
 security/smack/smack_lsm.c | 19 +++++++++++++------
 4 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 4020e13f0669..58e5465fdd79 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2046,6 +2046,7 @@ struct lsm_blob_sizes {
 	int	lbs_key;
 	int	lbs_msg_msg;
 	int	lbs_task;
+	int	lbs_mnt_opts;
 };
 
 /*
@@ -2119,4 +2120,8 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
 
 extern int lsm_inode_alloc(struct inode *inode);
 
+#ifdef CONFIG_SECURITY
+void *lsm_mnt_opts_alloc(void);
+#endif
+
 #endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/security.c b/security/security.c
index 105b5ee22bcf..780c914df9fb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -194,6 +194,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
 #ifdef CONFIG_KEYS
 	lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
 #endif
+	lsm_set_blob_size(&needed->lbs_mnt_opts, &blob_sizes.lbs_mnt_opts);
 	lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
 	lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
 	lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
@@ -328,6 +329,7 @@ static void __init ordered_lsm_init(void)
 #ifdef CONFIG_KEYS
 	init_debug("key blob size        = %d\n", blob_sizes.lbs_key);
 #endif /* CONFIG_KEYS */
+	init_debug("mnt_opts blob size   = %d\n", blob_sizes.lbs_mnt_opts);
 	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
 	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
 	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
@@ -738,6 +740,21 @@ int lsm_superblock_alloc(struct super_block *sb)
 	return 0;
 }
 
+/**
+ * lsm_mnt_opts_alloc - allocate a composite mnt_opts blob
+ *
+ * Allocate the mount options blob
+ *
+ * Returns the blob, or NULL if memory can't be allocated.
+ */
+void *lsm_mnt_opts_alloc(void)
+{
+	if (blob_sizes.lbs_mnt_opts == 0)
+		return NULL;
+
+	return kzalloc(blob_sizes.lbs_mnt_opts, GFP_KERNEL);
+}
+
 /*
  * Hook list operation macros.
  *
@@ -941,6 +958,7 @@ void security_free_mnt_opts(void **mnt_opts)
 	if (!*mnt_opts)
 		return;
 	call_void_hook(sb_free_mnt_opts, *mnt_opts);
+	kfree(*mnt_opts);
 	*mnt_opts = NULL;
 }
 EXPORT_SYMBOL(security_free_mnt_opts);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 501aed18f100..e149be6226d6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -381,14 +381,20 @@ struct selinux_mnt_opts {
 	const char *fscontext, *context, *rootcontext, *defcontext;
 };
 
+static void *selinux_mnt_opts(void *mnt_opts)
+{
+	if (mnt_opts)
+		return mnt_opts + selinux_blob_sizes.lbs_mnt_opts;
+	return NULL;
+}
+
 static void selinux_free_mnt_opts(void *mnt_opts)
 {
-	struct selinux_mnt_opts *opts = mnt_opts;
+	struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
 	kfree(opts->fscontext);
 	kfree(opts->context);
 	kfree(opts->rootcontext);
 	kfree(opts->defcontext);
-	kfree(opts);
 }
 
 static inline int inode_doinit(struct inode *inode)
@@ -614,7 +620,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	const struct cred *cred = current_cred();
 	struct superblock_security_struct *sbsec = selinux_superblock(sb);
 	struct dentry *root = sbsec->sb->s_root;
-	struct selinux_mnt_opts *opts = mnt_opts;
+	struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
 	struct inode_security_struct *root_isec;
 	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
 	u32 defcontext_sid = 0;
@@ -629,7 +635,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 			   server is ready to handle calls. */
 			goto out;
 		}
-		rc = -EINVAL;
+		/* Don't set any SELinux options. Allow any other LSM
+		   that's on the stack to do so. */
 		pr_warn("SELinux: Unable to set superblock options "
 			"before the security server is initialized\n");
 		goto out;
@@ -953,16 +960,17 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 
 static int selinux_add_opt(int token, const char *s, void **mnt_opts)
 {
-	struct selinux_mnt_opts *opts = *mnt_opts;
+	struct selinux_mnt_opts *opts = selinux_mnt_opts(*mnt_opts);
 
 	if (token == Opt_seclabel)	/* eaten and completely ignored */
 		return 0;
 
 	if (!opts) {
-		opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
+		opts = lsm_mnt_opts_alloc();
 		if (!opts)
 			return -ENOMEM;
 		*mnt_opts = opts;
+		opts = selinux_mnt_opts(opts);
 	}
 	if (!s)
 		return -ENOMEM;
@@ -1015,10 +1023,8 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
 	rc = selinux_add_opt(token, val, mnt_opts);
 	if (unlikely(rc)) {
 		kfree(val);
-		if (*mnt_opts) {
+		if (*mnt_opts)
 			selinux_free_mnt_opts(*mnt_opts);
-			*mnt_opts = NULL;
-		}
 	}
 	return rc;
 }
@@ -2583,10 +2589,8 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
 			rc = selinux_add_opt(token, arg, mnt_opts);
 			if (unlikely(rc)) {
 				kfree(arg);
-				if (*mnt_opts) {
+				if (*mnt_opts)
 					selinux_free_mnt_opts(*mnt_opts);
-					*mnt_opts = NULL;
-				}
 				return rc;
 			}
 		} else {
@@ -2609,7 +2613,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
 
 static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
 {
-	struct selinux_mnt_opts *opts = mnt_opts;
+	struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
 	struct superblock_security_struct *sbsec = selinux_superblock(sb);
 	u32 sid;
 	int rc;
@@ -6532,6 +6536,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
 #ifdef CONFIG_KEYS
 	.lbs_key = sizeof(struct key_security_struct),
 #endif /* CONFIG_KEYS */
+	.lbs_mnt_opts = sizeof(struct selinux_mnt_opts),
 	.lbs_msg_msg = sizeof(struct msg_security_struct),
 	.lbs_sock = sizeof(struct sk_security_struct),
 	.lbs_superblock = sizeof(struct superblock_security_struct),
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c84c71a31b80..f1e0f1378666 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -573,26 +573,33 @@ struct smack_mnt_opts {
 	const char *fsdefault, *fsfloor, *fshat, *fsroot, *fstransmute;
 };
 
+static void *smack_mnt_opts(void *opts)
+{
+	if (opts)
+		return opts + smack_blob_sizes.lbs_mnt_opts;
+	return NULL;
+}
+
 static void smack_free_mnt_opts(void *mnt_opts)
 {
-	struct smack_mnt_opts *opts = mnt_opts;
+	struct smack_mnt_opts *opts = smack_mnt_opts(mnt_opts);
 	kfree(opts->fsdefault);
 	kfree(opts->fsfloor);
 	kfree(opts->fshat);
 	kfree(opts->fsroot);
 	kfree(opts->fstransmute);
-	kfree(opts);
 }
 
 static int smack_add_opt(int token, const char *s, void **mnt_opts)
 {
-	struct smack_mnt_opts *opts = *mnt_opts;
+	struct smack_mnt_opts *opts = smack_mnt_opts(*mnt_opts);
 
 	if (!opts) {
-		opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
+		opts = lsm_mnt_opts_alloc();
 		if (!opts)
 			return -ENOMEM;
 		*mnt_opts = opts;
+		opts = smack_mnt_opts(opts);
 	}
 	if (!s)
 		return -ENOMEM;
@@ -654,7 +661,6 @@ static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
 				kfree(arg);
 				if (*mnt_opts)
 					smack_free_mnt_opts(*mnt_opts);
-				*mnt_opts = NULL;
 				return rc;
 			}
 		} else {
@@ -697,7 +703,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
 	struct superblock_smack *sp = smack_superblock(sb);
 	struct inode_smack *isp;
 	struct smack_known *skp;
-	struct smack_mnt_opts *opts = mnt_opts;
+	struct smack_mnt_opts *opts = smack_mnt_opts(mnt_opts);
 	bool transmute = false;
 
 	if (sp->smk_flags & SMK_SB_INITIALIZED)
@@ -4501,6 +4507,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
 #ifdef CONFIG_KEYS
 	.lbs_key = sizeof(struct smack_known *),
 #endif /* CONFIG_KEYS */
+	.lbs_mnt_opts = sizeof(struct smack_mnt_opts),
 	.lbs_msg_msg = sizeof(struct smack_known *),
 	.lbs_sock = sizeof(struct socket_smack),
 	.lbs_superblock = sizeof(struct superblock_smack),
-- 
2.17.0


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

* [PATCH 79/97] LSM: Fix for security_init_inode_security
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (7 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 78/97] LSM: Infrastructure security blobs for mount options Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 80/97] Smack: Advertise the secid to netlabel Casey Schaufler
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

The code assumes you can call evm_init_inode_security more
than once for an inode, but that won't work because security.evm
is a single value attribute. This does not make EVM work properly,
but does allow the security modules to initialize their attribures.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/security/security.c b/security/security.c
index 780c914df9fb..c4265ceb6dd0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1104,11 +1104,24 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 	if (unlikely(IS_PRIVATE(inode)))
 		return 0;
 
-	if (!initxattrs)
-		return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
-				     dir, qstr, NULL, NULL, NULL);
+	if (!initxattrs) {
+		rc = -EOPNOTSUPP;
+		hlist_for_each_entry(p,
+				     &security_hook_heads.inode_init_security,
+				     list) {
+			rc = p->hook.inode_init_security(inode, dir, qstr,
+							 NULL, NULL, NULL);
+			if (rc == -EOPNOTSUPP) {
+				rc = 0;
+				continue;
+			}
+			if (rc)
+				break;
+		}
+		return rc;
+	}
 
-	repo = kzalloc((LSM_COUNT * 2) * sizeof(*repo), GFP_NOFS);
+	repo = kzalloc((LSM_COUNT + 1) * sizeof(*repo), GFP_NOFS);
 	if (repo == NULL)
 		return -ENOMEM;
 
@@ -1119,18 +1132,20 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 		rc = p->hook.inode_init_security(inode, dir, qstr,
 						 &repo[i].name, &repo[i].value,
 						 &repo[i].value_len);
+		if (rc == -EOPNOTSUPP)
+			continue;
 		if (rc)
 			goto out;
 
-		rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
-		if (rc)
-			goto out;
-
-		i += 2;
+		i++;
 	}
+	rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
+	if (rc)
+		goto out;
+
 	rc = initxattrs(inode, repo, fs_data);
 out:
-	for (i-- ; i >= 0; i--)
+	for (i++ ; i >= 0; i--)
 		kfree(repo[i].value);
 	kfree(repo);
 	return (rc == -EOPNOTSUPP) ? 0 : rc;
-- 
2.17.0


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

* [PATCH 80/97] Smack: Advertise the secid to netlabel
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (8 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 79/97] LSM: Fix for security_init_inode_security Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 81/97] LSM: Change error detection for UDP peer security Casey Schaufler
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add the secid to the attributes shared with netlabel.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_access.c | 8 ++++++--
 security/smack/smackfs.c      | 8 ++++++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index fe2ce3a65822..0764bb85daee 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -549,8 +549,12 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	skp->smk_known = smack;
 	skp->smk_secid = smack_next_secid++;
 	skp->smk_netlabel.domain = skp->smk_known;
-	skp->smk_netlabel.flags =
-		NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+	lsm_export_init(&skp->smk_netlabel.attr.le);
+	skp->smk_netlabel.attr.le.flags = LSM_EXPORT_SMACK;
+	skp->smk_netlabel.attr.le.smack = skp->smk_secid;
+	skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+				  NETLBL_SECATTR_MLS_LVL |
+				  NETLBL_SECATTR_SECID;
 	/*
 	 * If direct labeling works use it.
 	 * Otherwise use mapped labeling.
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 28c567465f6c..abaa5325c32f 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -2953,8 +2953,12 @@ static struct vfsmount *smackfs_mount;
 static int __init smk_preset_netlabel(struct smack_known *skp)
 {
 	skp->smk_netlabel.domain = skp->smk_known;
-	skp->smk_netlabel.flags =
-		NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+	lsm_export_init(&skp->smk_netlabel.attr.le);
+	skp->smk_netlabel.attr.le.flags = LSM_EXPORT_SMACK;
+	skp->smk_netlabel.attr.le.smack = skp->smk_secid;
+	skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+				  NETLBL_SECATTR_MLS_LVL |
+				  NETLBL_SECATTR_SECID;
 	return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
 				&skp->smk_netlabel, strlen(skp->smk_known));
 }
-- 
2.17.0


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

* [PATCH 81/97] LSM: Change error detection for UDP peer security
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (9 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 80/97] Smack: Advertise the secid to netlabel Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 82/97] Smack: Fix setting of the CIPSO MLS_CAT flags Casey Schaufler
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

security_socket_getpeercred_dgram() supplies secids for use
by security_secid_to_secctx(). Sometimes a secid will be invalid.
Move the check for an invalid secid from the LSM specific
socket_getpeercred_dgram hooks into the secid_to_secctx hooks.
This allows for the case where one LSM (Smack) will provide a
secid and another (SELinux) to have an error for the same call.
Regardless of which LSM the caller wants to see the peer security
attributes for the correct result will be provided.

As there is no longer any reason for security_secid_to_secctx()
to return a value make all the secid_to_secctx functions void
instead of int. Add checking for a invalid secid to the Smack
and SELinux secid_to_secctx hooks.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hooks.h  |  3 +--
 include/linux/security.h   | 11 +++++------
 net/ipv4/ip_sockglue.c     |  4 +---
 security/security.c        |  7 +++----
 security/selinux/hooks.c   | 13 +++++++------
 security/smack/smack_lsm.c | 17 ++++++++---------
 6 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 58e5465fdd79..fec7f86897ea 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -867,7 +867,6 @@
  *	@sock is the socket
  *	@skb is the skbuff for the packet being queried
  *	@l is a pointer to a buffer in which to copy the security data
- *	Return 0 on success, error on failure.
  * @sk_alloc_security:
  *	Allocate and attach a security structure to the sk->sk_security field,
  *	which is used to copy security attributes between local stream sockets.
@@ -1681,7 +1680,7 @@ union security_list_options {
 	int (*socket_getpeersec_stream)(struct socket *sock,
 					char __user *optval,
 					int __user *optlen, unsigned len);
-	int (*socket_getpeersec_dgram)(struct socket *sock,
+	void (*socket_getpeersec_dgram)(struct socket *sock,
 					struct sk_buff *skb,
 					struct lsm_export *l);
 	int (*sk_alloc_security)(struct sock *sk, int family, gfp_t priority);
diff --git a/include/linux/security.h b/include/linux/security.h
index cb392c6b620f..7edceb91d77f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1274,8 +1274,8 @@ int security_socket_shutdown(struct socket *sock, int how);
 int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
 int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
 				      int __user *optlen, unsigned len);
-int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
-				     struct lsm_export *l);
+void security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
+				      struct lsm_export *l);
 int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
 void security_sk_free(struct sock *sk);
 void security_sk_clone(const struct sock *sk, struct sock *newsk);
@@ -1413,11 +1413,10 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __
 	return -ENOPROTOOPT;
 }
 
-static inline int security_socket_getpeersec_dgram(struct socket *sock,
-						   struct sk_buff *skb,
-						   struct lsm_export *l)
+static inline void security_socket_getpeersec_dgram(struct socket *sock,
+						    struct sk_buff *skb,
+						    struct lsm_export *l)
 {
-	return -ENOPROTOOPT;
 }
 
 static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 56035b53952d..ae69718d87ae 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -134,9 +134,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 	struct lsm_context lc;
 	int err;
 
-	err = security_socket_getpeersec_dgram(NULL, skb, &le);
-	if (err)
-		return;
+	security_socket_getpeersec_dgram(NULL, skb, &le);
 
 	err = security_secid_to_secctx(&le, &lc);
 	if (err)
diff --git a/security/security.c b/security/security.c
index c4265ceb6dd0..ab1050a2dce3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2414,12 +2414,11 @@ int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
 				optval, optlen, len);
 }
 
-int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
-				     struct lsm_export *l)
+void security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
+				      struct lsm_export *l)
 {
 	lsm_export_init(l);
-	return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, skb,
-			     l);
+	call_void_hook(socket_getpeersec_dgram, sock, skb, l);
 }
 EXPORT_SYMBOL(security_socket_getpeersec_dgram);
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e149be6226d6..22a190f291c0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4835,9 +4835,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock,
 	return err;
 }
 
-static int selinux_socket_getpeersec_dgram(struct socket *sock,
-					   struct sk_buff *skb,
-					   struct lsm_export *l)
+static void selinux_socket_getpeersec_dgram(struct socket *sock,
+					    struct sk_buff *skb,
+					    struct lsm_export *l)
 {
 	u32 peer_secid = SECSID_NULL;
 	u16 family;
@@ -4860,9 +4860,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock,
 
 out:
 	selinux_export_secid(l, peer_secid);
-	if (peer_secid == SECSID_NULL)
-		return -EINVAL;
-	return 0;
+	return;
 }
 
 static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -6206,6 +6204,9 @@ static int selinux_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
 	u32 secid;
 
 	selinux_import_secid(l, &secid);
+	if (secid == SECSID_NULL)
+		return -EINVAL;
+
 	cp->release = selinux_release_secctx;
 	if (l->flags & LSM_EXPORT_LENGTH)
 		return security_sid_to_context(&selinux_state, secid,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f1e0f1378666..a4c8f93534ec 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3902,9 +3902,9 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
  *
  * Sets the netlabel socket state on sk from parent
  */
-static int smack_socket_getpeersec_dgram(struct socket *sock,
-					 struct sk_buff *skb,
-					 struct lsm_export *l)
+static void smack_socket_getpeersec_dgram(struct socket *sock,
+					  struct sk_buff *skb,
+					  struct lsm_export *l)
 
 {
 	struct netlbl_lsm_secattr secattr;
@@ -3912,7 +3912,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
 	struct smack_known *skp;
 	int family = PF_UNSPEC;
 	u32 s = 0;	/* 0 is the invalid secid */
-	int rc;
 
 	if (skb != NULL) {
 		if (skb->protocol == htons(ETH_P_IP))
@@ -3942,8 +3941,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
 		if (sock != NULL && sock->sk != NULL)
 			ssp = smack_sock(sock->sk);
 		netlbl_secattr_init(&secattr);
-		rc = netlbl_skbuff_getattr(skb, family, &secattr);
-		if (rc == 0) {
+		if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) {
 			skp = smack_from_secattr(&secattr, ssp);
 			s = skp->smk_secid;
 		}
@@ -3958,9 +3956,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
 		break;
 	}
 	smack_export_secid(l, s);
-	if (s == 0)
-		return -EINVAL;
-	return 0;
+	return;
 }
 
 /**
@@ -4373,6 +4369,9 @@ static int smack_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
 	u32 secid;
 
 	smack_import_secid(l, &secid);
+	if (secid == 0)
+		return -EINVAL;
+
 	skp = smack_from_secid(secid);
 
 	cp->context = (l->flags & LSM_EXPORT_LENGTH) ? NULL : skp->smk_known;
-- 
2.17.0


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

* [PATCH 82/97] Smack: Fix setting of the CIPSO MLS_CAT flags
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (10 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 81/97] LSM: Change error detection for UDP peer security Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 83/97] Smack: Set netlabel flags properly on new label import Casey Schaufler
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Don't tell CIPSO that a netlabel created by Smack has
categories set whenit doesn't.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_access.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 0764bb85daee..5fe5c6799b27 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -494,8 +494,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
 	int cat;
 	int rc;
 	int byte;
+	bool has = false;
 
-	sap->flags |= NETLBL_SECATTR_MLS_CAT;
 	sap->attr.mls.lvl = level;
 	sap->attr.mls.cat = NULL;
 
@@ -503,6 +503,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
 		for (m = 0x80; m != 0; m >>= 1, cat++) {
 			if ((m & *cp) == 0)
 				continue;
+			has = true;
 			rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
 						  cat, GFP_KERNEL);
 			if (rc < 0) {
@@ -511,6 +512,9 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
 			}
 		}
 
+	if (has)
+		sap->flags |= NETLBL_SECATTR_MLS_CAT;
+
 	return 0;
 }
 
-- 
2.17.0


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

* [PATCH 83/97] Smack: Set netlabel flags properly on new label import
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (11 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 82/97] Smack: Fix setting of the CIPSO MLS_CAT flags Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 84/97] Netlabel: Add a secattr comparison API function Casey Schaufler
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Ensure that all netlabel flags are correctly set on the
netlabel attribute of a newly imported Smack label.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smackfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index abaa5325c32f..0abfa4315fb1 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -931,6 +931,9 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
 		smack_catset_bit(cat, mapcatset);
 	}
 
+	skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+				  NETLBL_SECATTR_MLS_LVL |
+				  NETLBL_SECATTR_SECID;
 	rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
 	if (rc >= 0) {
 		netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat);
-- 
2.17.0


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

* [PATCH 84/97] Netlabel: Add a secattr comparison API function
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (12 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 83/97] Smack: Set netlabel flags properly on new label import Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 85/97] Smack: Let netlabel do the work on the ambient domain Casey Schaufler
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add a new API function netlbl_secattr_equal() that
determines if two secattr structures would result in the
same on-wire representation.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/net/netlabel.h       |  8 ++++++
 net/netlabel/netlabel_kapi.c | 50 ++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 546c75f27d05..00000d53cdcd 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -472,6 +472,8 @@ int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
 			  u32 offset,
 			  unsigned long bitmap,
 			  gfp_t flags);
+bool netlbl_secattr_equal(const struct netlbl_lsm_secattr *secattr_a,
+			  const struct netlbl_lsm_secattr *secattr_b);
 
 /* Bitmap functions
  */
@@ -623,6 +625,12 @@ static inline int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
 {
 	return 0;
 }
+static inline bool netlbl_secattr_equal(
+				const struct netlbl_lsm_secattr *secattr_a,
+				const struct netlbl_lsm_secattr *secattr_b)
+{
+	return true;
+}
 static inline int netlbl_enabled(void)
 {
 	return 0;
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 01b8006c7c55..db6bb1c037f9 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1460,6 +1460,56 @@ int netlbl_cache_add(const struct sk_buff *skb, u16 family,
 	return -ENOMSG;
 }
 
+/**
+ * netlbl_secattr_equal - Compare two lsm secattrs
+ * @secattr_a: one security attribute
+ * @secattr_b: the other security attribute
+ *
+ * Description:
+ * Compare two lsm security attribute structures.
+ * Don't compare secid fields, as those are distinct.
+ * Returns true if they are the same, false otherwise.
+ *
+ */
+bool netlbl_secattr_equal(const struct netlbl_lsm_secattr *secattr_a,
+			  const struct netlbl_lsm_secattr *secattr_b)
+{
+	struct netlbl_lsm_catmap *iter_a;
+	struct netlbl_lsm_catmap *iter_b;
+
+	if (secattr_a == secattr_b)
+		return true;
+	if (!secattr_a || !secattr_b)
+		return false;
+
+	if ((secattr_a->flags & NETLBL_SECATTR_MLS_LVL) !=
+	    (secattr_b->flags & NETLBL_SECATTR_MLS_LVL))
+		return false;
+
+	if ((secattr_a->flags & NETLBL_SECATTR_MLS_LVL) &&
+	    secattr_a->attr.mls.lvl != secattr_b->attr.mls.lvl)
+		return false;
+
+	if ((secattr_a->flags & NETLBL_SECATTR_MLS_CAT) !=
+	    (secattr_b->flags & NETLBL_SECATTR_MLS_CAT))
+		return false;
+
+	iter_a = secattr_a->attr.mls.cat;
+	iter_b = secattr_b->attr.mls.cat;
+
+	while (iter_a && iter_b) {
+		if (iter_a->startbit != iter_b->startbit)
+			return false;
+		if (memcmp(iter_a->bitmap, iter_b->bitmap,
+			   sizeof(iter_a->bitmap)))
+			return false;
+		iter_a = iter_a->next;
+		iter_b = iter_b->next;
+	}
+
+	return !iter_a && !iter_b;
+}
+
 /*
  * Protocol Engine Functions
  */
-- 
2.17.0


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

* [PATCH 85/97] Smack: Let netlabel do the work on the ambient domain
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (13 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 84/97] Netlabel: Add a secattr comparison API function Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 86/97] Smack: Don't set the socket label on each send Casey Schaufler
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Don't delete the netlabel data from sockets on the
ambient domain as netlabel will do it correctly without
any help.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_lsm.c | 31 ++++++++-----------------------
 1 file changed, 8 insertions(+), 23 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a4c8f93534ec..d2a73d8a6976 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2316,37 +2316,27 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
 /**
  * smack_netlabel - Set the secattr on a socket
  * @sk: the socket
- * @labeled: socket label scheme
  *
  * Convert the outbound smack value (smk_out) to a
  * secattr and attach it to the socket.
  *
  * Returns 0 on success or an error code
  */
-static int smack_netlabel(struct sock *sk, int labeled)
+static int smack_netlabel(struct sock *sk)
 {
 	struct smack_known *skp;
 	struct socket_smack *ssp = smack_sock(sk);
 	int rc = 0;
 
 	/*
-	 * Usually the netlabel code will handle changing the
+	 * The netlabel code will handle changing the
 	 * packet labeling based on the label.
-	 * The case of a single label host is different, because
-	 * a single label host should never get a labeled packet
-	 * even though the label is usually associated with a packet
-	 * label.
 	 */
 	local_bh_disable();
 	bh_lock_sock_nested(sk);
 
-	if (ssp->smk_out == smack_net_ambient ||
-	    labeled == SMACK_UNLABELED_SOCKET)
-		netlbl_sock_delattr(sk);
-	else {
-		skp = ssp->smk_out;
-		rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
-	}
+	skp = ssp->smk_out;
+	rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
 
 	bh_unlock_sock(sk);
 	local_bh_enable();
@@ -2368,8 +2358,7 @@ static int smack_netlabel(struct sock *sk, int labeled)
 static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
 {
 	struct smack_known *skp;
-	int rc;
-	int sk_lbl;
+	int rc = 0;
 	struct smack_known *hkp;
 	struct socket_smack *ssp = smack_sock(sk);
 	struct smk_audit_info ad;
@@ -2385,19 +2374,15 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
 		ad.a.u.net->dport = sap->sin_port;
 		ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
 #endif
-		sk_lbl = SMACK_UNLABELED_SOCKET;
 		skp = ssp->smk_out;
 		rc = smk_access(skp, hkp, MAY_WRITE, &ad);
 		rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
-	} else {
-		sk_lbl = SMACK_CIPSO_SOCKET;
-		rc = 0;
 	}
 	rcu_read_unlock();
 	if (rc != 0)
 		return rc;
 
-	return smack_netlabel(sk, sk_lbl);
+	return smack_netlabel(sk);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -2635,7 +2620,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
 	else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
 		ssp->smk_out = skp;
 		if (sock->sk->sk_family == PF_INET) {
-			rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
+			rc = smack_netlabel(sock->sk);
 			if (rc != 0)
 				printk(KERN_WARNING
 					"Smack: \"%s\" netlbl error %d.\n",
@@ -2686,7 +2671,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
 	/*
 	 * Set the outbound netlbl.
 	 */
-	return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
+	return smack_netlabel(sock->sk);
 }
 
 /**
-- 
2.17.0


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

* [PATCH 86/97] Smack: Don't set the socket label on each send
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (14 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 85/97] Smack: Let netlabel do the work on the ambient domain Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 87/97] Smack: Let netlabel do the work on connections Casey Schaufler
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

The socket does not need to be relabeled on each send.
Remove the code that does that.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_lsm.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d2a73d8a6976..d9055a0df75c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2379,10 +2379,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
 		rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
 	}
 	rcu_read_unlock();
-	if (rc != 0)
-		return rc;
-
-	return smack_netlabel(sk);
+	return rc;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-- 
2.17.0


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

* [PATCH 87/97] Smack: Let netlabel do the work on connections
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (15 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 86/97] Smack: Don't set the socket label on each send Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 88/97] Netlabel: Return the labeling type on socket Casey Schaufler
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Rather than removing the netlabel socket attribute
on connections set the ambient domain. This is more
in line with the way netlabel "should" be used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_lsm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d9055a0df75c..f965c9e6287e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4057,7 +4057,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 	if (hskp == NULL)
 		rc = netlbl_req_setattr(req, &skp->smk_netlabel);
 	else
-		netlbl_req_delattr(req);
+		rc = netlbl_req_setattr(req, &smack_net_ambient->smk_netlabel);
 
 	return rc;
 }
-- 
2.17.0


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

* [PATCH 88/97] Netlabel: Return the labeling type on socket
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (16 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 87/97] Smack: Let netlabel do the work on connections Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 89/97] " Casey Schaufler
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Change netlbl_sock_setattr() to return the labeling
type of the domain. This allows the labeling types to
be compared when two LSMs want to determine how a socket
should be used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 net/netlabel/netlabel_kapi.c | 25 ++++++++++++-------------
 security/selinux/netlabel.c  | 11 ++++-------
 security/smack/smack_lsm.c   |  2 ++
 3 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index db6bb1c037f9..61766da2cfac 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -973,15 +973,14 @@ int netlbl_enabled(void)
  * Attach the correct label to the given socket using the security attributes
  * specified in @secattr.  This function requires exclusive access to @sk,
  * which means it either needs to be in the process of being created or locked.
- * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
- * network address selectors (can't blindly label the socket), and negative
- * values on all other failures.
+ * Returns the labeling type of the domain, or negative values on failures.
  *
  */
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr)
 {
+	int rc;
 	int ret_val;
 	struct netlbl_dom_map *dom_entry;
 
@@ -993,17 +992,17 @@ int netlbl_sock_setattr(struct sock *sk,
 	}
 	switch (family) {
 	case AF_INET:
+		ret_val = dom_entry->def.type;
 		switch (dom_entry->def.type) {
 		case NETLBL_NLTYPE_ADDRSELECT:
-			ret_val = -EDESTADDRREQ;
 			break;
 		case NETLBL_NLTYPE_CIPSOV4:
-			ret_val = cipso_v4_sock_setattr(sk,
-							dom_entry->def.cipso,
-							secattr);
+			rc = cipso_v4_sock_setattr(sk, dom_entry->def.cipso,
+						   secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
@@ -1011,17 +1010,17 @@ int netlbl_sock_setattr(struct sock *sk,
 		break;
 #if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6:
+		ret_val = dom_entry->def.type;
 		switch (dom_entry->def.type) {
 		case NETLBL_NLTYPE_ADDRSELECT:
-			ret_val = -EDESTADDRREQ;
 			break;
 		case NETLBL_NLTYPE_CALIPSO:
-			ret_val = calipso_sock_setattr(sk,
-						       dom_entry->def.calipso,
-						       secattr);
+			rc = calipso_sock_setattr(sk, dom_entry->def.calipso,
+						  secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 4bbd50237a8a..85156a0cdfc3 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -418,15 +418,12 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
 	if (secattr == NULL)
 		return -ENOMEM;
 	rc = netlbl_sock_setattr(sk, family, secattr);
-	switch (rc) {
-	case 0:
-		sksec->nlbl_state = NLBL_LABELED;
-		break;
-	case -EDESTADDRREQ:
+	if (rc == NETLBL_NLTYPE_ADDRSELECT)
 		sksec->nlbl_state = NLBL_REQSKB;
+	else if (rc >= 0)
+		sksec->nlbl_state = NLBL_LABELED;
+	if (rc > 0)
 		rc = 0;
-		break;
-	}
 
 	return rc;
 }
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f965c9e6287e..20eed64e91de 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2337,6 +2337,8 @@ static int smack_netlabel(struct sock *sk)
 
 	skp = ssp->smk_out;
 	rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
+	if (rc > 0)
+		rc = 0;
 
 	bh_unlock_sock(sk);
 	local_bh_enable();
-- 
2.17.0


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

* [PATCH 89/97] Netlabel: Return the labeling type on socket
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (17 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 88/97] Netlabel: Return the labeling type on socket Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 90/97] " Casey Schaufler
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Change netlbl_conn_setattr() to return the labeling
type of the domain. This allows the labeling types to
be compared when two LSMs want to determine how a socket
should be used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 net/netlabel/netlabel_kapi.c | 20 ++++++++++++--------
 security/selinux/netlabel.c  |  8 ++++++--
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 61766da2cfac..2bd765290550 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1101,14 +1101,16 @@ int netlbl_sock_getattr(struct sock *sk,
  * Description:
  * Attach the correct label to the given connected socket using the security
  * attributes specified in @secattr.  The caller is responsible for ensuring
- * that @sk is locked.  Returns zero on success, negative values on failure.
+ * that @sk is locked.  Returns the NLTYPE on success, negative values on
+ * failure.
  *
  */
 int netlbl_conn_setattr(struct sock *sk,
 			struct sockaddr *addr,
 			const struct netlbl_lsm_secattr *secattr)
 {
-	int ret_val;
+	int rc;
+	int ret_val = 0;
 	struct sockaddr_in *addr4;
 #if IS_ENABLED(CONFIG_IPV6)
 	struct sockaddr_in6 *addr6;
@@ -1125,16 +1127,17 @@ int netlbl_conn_setattr(struct sock *sk,
 			ret_val = -ENOENT;
 			goto conn_setattr_return;
 		}
+		ret_val = entry->type;
 		switch (entry->type) {
 		case NETLBL_NLTYPE_CIPSOV4:
-			ret_val = cipso_v4_sock_setattr(sk,
-							entry->cipso, secattr);
+			rc = cipso_v4_sock_setattr(sk, entry->cipso, secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
 			/* just delete the protocols we support for right now
 			 * but we could remove other protocols if needed */
 			netlbl_sock_delattr(sk);
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
@@ -1149,16 +1152,17 @@ int netlbl_conn_setattr(struct sock *sk,
 			ret_val = -ENOENT;
 			goto conn_setattr_return;
 		}
+		ret_val = entry->type;
 		switch (entry->type) {
 		case NETLBL_NLTYPE_CALIPSO:
-			ret_val = calipso_sock_setattr(sk,
-						       entry->calipso, secattr);
+			rc = calipso_sock_setattr(sk, entry->calipso, secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
 			/* just delete the protocols we support for right now
 			 * but we could remove other protocols if needed */
 			netlbl_sock_delattr(sk);
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 85156a0cdfc3..ca47c99f964a 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -321,8 +321,10 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
 	}
 
 	rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr);
-	if (rc == 0)
+	if (rc >= 0) {
 		sksec->nlbl_state = NLBL_LABELED;
+		rc = 0;
+	}
 
 assoc_request_return:
 	netlbl_secattr_destroy(&secattr);
@@ -576,8 +578,10 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
 		return rc;
 	}
 	rc = netlbl_conn_setattr(sk, addr, secattr);
-	if (rc == 0)
+	if (rc >= 0) {
 		sksec->nlbl_state = NLBL_CONNLABELED;
+		rc = 0;
+	}
 
 	return rc;
 }
-- 
2.17.0


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

* [PATCH 90/97] Netlabel: Return the labeling type on socket
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (18 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 89/97] " Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 91/97] " Casey Schaufler
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Change netlbl_skbuff_setattr() to return the labeling
type of the domain. This allows the labeling types to
be compared when two LSMs want to determine how a socket
should be used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 net/netlabel/netlabel_kapi.c | 7 ++++++-
 security/selinux/netlabel.c  | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 2bd765290550..1d362a38dd05 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1278,7 +1278,8 @@ void netlbl_req_delattr(struct request_sock *req)
  *
  * Description:
  * Attach the correct label to the given packet using the security attributes
- * specified in @secattr.  Returns zero on success, negative values on failure.
+ * specified in @secattr.  Returns the NLTYPE on success, negative values on
+ * failure.
  *
  */
 int netlbl_skbuff_setattr(struct sk_buff *skb,
@@ -1315,6 +1316,8 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
 		default:
 			ret_val = -ENOENT;
 		}
+		if (ret_val == 0)
+			ret_val = entry->type;
 		break;
 #if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6:
@@ -1338,6 +1341,8 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
 		default:
 			ret_val = -ENOENT;
 		}
+		if (ret_val == 0)
+			ret_val = entry->type;
 		break;
 #endif /* IPv6 */
 	default:
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index ca47c99f964a..b6eede4406bd 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -266,6 +266,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
 	}
 
 	rc = netlbl_skbuff_setattr(skb, family, secattr);
+	if (rc > 0)
+		rc = 0;
 
 skbuff_setsid_return:
 	if (secattr == &secattr_storage)
-- 
2.17.0


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

* [PATCH 91/97] Netlabel: Return the labeling type on socket
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (19 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 90/97] " Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 92/97] LSM: Remember the NLTYPE of netlabel sockets Casey Schaufler
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Change netlbl_req_setattr() to return the labeling
type of the domain. This allows the labeling types to
be compared when two LSMs want to determine how a socket
should be used.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 net/netlabel/netlabel_kapi.c | 18 +++++++++++-------
 security/selinux/netlabel.c  |  2 ++
 security/smack/smack_lsm.c   |  2 ++
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 1d362a38dd05..5c5825171281 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -1185,12 +1185,14 @@ int netlbl_conn_setattr(struct sock *sk,
  *
  * Description:
  * Attach the correct label to the given socket using the security attributes
- * specified in @secattr.  Returns zero on success, negative values on failure.
+ * specified in @secattr.  Returns the NLTYPE on success, negative values on
+ * failure.
  *
  */
 int netlbl_req_setattr(struct request_sock *req,
 		       const struct netlbl_lsm_secattr *secattr)
 {
+	int rc;
 	int ret_val;
 	struct netlbl_dommap_def *entry;
 	struct inet_request_sock *ireq = inet_rsk(req);
@@ -1204,14 +1206,15 @@ int netlbl_req_setattr(struct request_sock *req,
 			ret_val = -ENOENT;
 			goto req_setattr_return;
 		}
+		ret_val = entry->type;
 		switch (entry->type) {
 		case NETLBL_NLTYPE_CIPSOV4:
-			ret_val = cipso_v4_req_setattr(req,
-						       entry->cipso, secattr);
+			rc = cipso_v4_req_setattr(req, entry->cipso, secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
 			netlbl_req_delattr(req);
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
@@ -1225,14 +1228,15 @@ int netlbl_req_setattr(struct request_sock *req,
 			ret_val = -ENOENT;
 			goto req_setattr_return;
 		}
+		ret_val = entry->type;
 		switch (entry->type) {
 		case NETLBL_NLTYPE_CALIPSO:
-			ret_val = calipso_req_setattr(req,
-						      entry->calipso, secattr);
+			rc = calipso_req_setattr(req, entry->calipso, secattr);
+			if (rc < 0)
+				ret_val = rc;
 			break;
 		case NETLBL_NLTYPE_UNLABELED:
 			netlbl_req_delattr(req);
-			ret_val = 0;
 			break;
 		default:
 			ret_val = -ENOENT;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index b6eede4406bd..9fbf22a3ca57 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -358,6 +358,8 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
 	if (rc != 0)
 		goto inet_conn_request_return;
 	rc = netlbl_req_setattr(req, &secattr);
+	if (rc > 0)
+		rc = 0;
 inet_conn_request_return:
 	netlbl_secattr_destroy(&secattr);
 	return rc;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 20eed64e91de..086a3f696baa 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4060,6 +4060,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 		rc = netlbl_req_setattr(req, &skp->smk_netlabel);
 	else
 		rc = netlbl_req_setattr(req, &smack_net_ambient->smk_netlabel);
+	if (rc >= 0)
+		return 0;
 
 	return rc;
 }
-- 
2.17.0


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

* [PATCH 92/97] LSM: Remember the NLTYPE of netlabel sockets
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (20 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 91/97] " Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 93/97] Smack: Use the NLTYPE on output Casey Schaufler
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add the NLTYPE returned when setting labels on sockets
to the information retained by SELinux and Smack.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/selinux/include/objsec.h |  1 +
 security/selinux/netlabel.c       | 20 ++++++++++++++------
 security/smack/smack.h            |  1 +
 security/smack/smack_lsm.c        | 10 +++++++---
 4 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index c9a88b7a96a7..a860d9936ec5 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -145,6 +145,7 @@ struct sk_security_struct {
 		NLBL_REQSKB,
 		NLBL_CONNLABELED,
 	} nlbl_state;
+	int nlbl_set;			/* Raw NLTYPE	*/
 	struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
 #endif
 	u32 sid;			/* SID of this object */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 9fbf22a3ca57..b6fd905e6e9e 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -185,6 +185,7 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
 void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec)
 {
 	sksec->nlbl_state = NLBL_UNSET;
+	sksec->nlbl_set = NETLBL_NLTYPE_NONE;
 }
 
 /**
@@ -244,14 +245,14 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
 	int rc;
 	struct netlbl_lsm_secattr secattr_storage;
 	struct netlbl_lsm_secattr *secattr = NULL;
+	struct sk_security_struct *sksec;
 	struct sock *sk;
 
 	/* if this is a locally generated packet check to see if it is already
 	 * being labeled by it's parent socket, if it is just exit */
 	sk = skb_to_full_sk(skb);
 	if (sk != NULL) {
-		struct sk_security_struct *sksec = selinux_sock(sk);
-
+		sksec = selinux_sock(sk);
 		if (sksec->nlbl_state != NLBL_REQSKB)
 			return 0;
 		secattr = selinux_netlbl_sock_getattr(sk, sid);
@@ -266,8 +267,11 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
 	}
 
 	rc = netlbl_skbuff_setattr(skb, family, secattr);
-	if (rc > 0)
+	if (rc >= 0) {
+		if (sk != NULL)
+			sksec->nlbl_set = rc;
 		rc = 0;
+	}
 
 skbuff_setsid_return:
 	if (secattr == &secattr_storage)
@@ -325,6 +329,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
 	rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr);
 	if (rc >= 0) {
 		sksec->nlbl_state = NLBL_LABELED;
+		sksec->nlbl_set = rc;
 		rc = 0;
 	}
 
@@ -428,8 +433,10 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
 		sksec->nlbl_state = NLBL_REQSKB;
 	else if (rc >= 0)
 		sksec->nlbl_state = NLBL_LABELED;
-	if (rc > 0)
+	if (rc >= 0) {
+		sksec->nlbl_set = rc;
 		rc = 0;
+	}
 
 	return rc;
 }
@@ -573,8 +580,8 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
 	if (addr->sa_family == AF_UNSPEC) {
 		netlbl_sock_delattr(sk);
 		sksec->nlbl_state = NLBL_REQSKB;
-		rc = 0;
-		return rc;
+		sksec->nlbl_set = NETLBL_NLTYPE_ADDRSELECT;
+		return 0;
 	}
 	secattr = selinux_netlbl_sock_genattr(sk);
 	if (secattr == NULL) {
@@ -584,6 +591,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
 	rc = netlbl_conn_setattr(sk, addr, secattr);
 	if (rc >= 0) {
 		sksec->nlbl_state = NLBL_CONNLABELED;
+		sksec->nlbl_set = rc;
 		rc = 0;
 	}
 
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 147afb9233b4..8df0744ce38c 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -104,6 +104,7 @@ struct socket_smack {
 	struct smack_known	*smk_out;	/* outbound label */
 	struct smack_known	*smk_in;	/* inbound label */
 	struct smack_known	*smk_packet;	/* TCP peer label */
+	int			smk_set;	/* Netlabel NLTYPE */
 };
 
 /*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 086a3f696baa..1b9c7e5e801a 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2326,7 +2326,7 @@ static int smack_netlabel(struct sock *sk)
 {
 	struct smack_known *skp;
 	struct socket_smack *ssp = smack_sock(sk);
-	int rc = 0;
+	int rc;
 
 	/*
 	 * The netlabel code will handle changing the
@@ -2337,8 +2337,10 @@ static int smack_netlabel(struct sock *sk)
 
 	skp = ssp->smk_out;
 	rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
-	if (rc > 0)
+	if (rc >= 0) {
+		ssp->smk_set = rc;
 		rc = 0;
+	}
 
 	bh_unlock_sock(sk);
 	local_bh_enable();
@@ -4060,8 +4062,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 		rc = netlbl_req_setattr(req, &skp->smk_netlabel);
 	else
 		rc = netlbl_req_setattr(req, &smack_net_ambient->smk_netlabel);
-	if (rc >= 0)
+	if (rc >= 0) {
+		ssp->smk_set = rc;
 		return 0;
+	}
 
 	return rc;
 }
-- 
2.17.0


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

* [PATCH 93/97] Smack: Use the NLTYPE on output
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (21 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 92/97] LSM: Remember the NLTYPE of netlabel sockets Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 94/97] LSM: Hook for netlabel reconciliation Casey Schaufler
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Use the saved NLTYPE to determine if the packet needs to
be labeled in the output path.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_netfilter.c | 42 +++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index ea45b173f8ca..7d202dde75b6 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -26,10 +26,19 @@ static bool smack_checked_secmark;
 
 void smack_secmark_refcount_inc(void)
 {
-        smack_use_secmark = true;
+	smack_use_secmark = true;
 	pr_info("Smack: Using network secmarks.\n");
 }
 
+static void smack_own_secmark(void)
+{
+	if (!smack_checked_secmark) {
+		security_secmark_refcount_inc();
+		security_secmark_refcount_dec();
+		smack_checked_secmark = true;
+	}
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 
 static unsigned int smack_ipv6_output(void *priv,
@@ -40,11 +49,7 @@ static unsigned int smack_ipv6_output(void *priv,
 	struct socket_smack *ssp;
 	struct smack_known *skp;
 
-	if (!smack_checked_secmark) {
-		security_secmark_refcount_inc();
-		security_secmark_refcount_dec();
-		smack_checked_secmark = true;
-	}
+	smack_own_secmark();
 
 	if (smack_use_secmark && sk && smack_sock(sk)) {
 		ssp = smack_sock(sk);
@@ -63,17 +68,26 @@ static unsigned int smack_ipv4_output(void *priv,
 	struct sock *sk = skb_to_full_sk(skb);
 	struct socket_smack *ssp;
 	struct smack_known *skp;
+	int rc = 0;
 
-	if (!smack_checked_secmark) {
-		security_secmark_refcount_inc();
-		security_secmark_refcount_dec();
-		smack_checked_secmark = true;
-	}
+	smack_own_secmark();
 
-	if (smack_use_secmark && sk && smack_sock(sk)) {
-		ssp = smack_sock(sk);
-		skp = ssp->smk_out;
+	if (sk == NULL)
+		return NF_ACCEPT;
+
+	ssp = smack_sock(sk);
+	if (ssp == NULL)
+		return NF_ACCEPT;
+
+	skp = ssp->smk_out;
+	if (smack_use_secmark)
 		skb->secmark = skp->smk_secid;
+
+	if (ssp->smk_set == NETLBL_NLTYPE_ADDRSELECT) {
+		rc = netlbl_skbuff_setattr(skb, PF_INET, &skp->smk_netlabel);
+		if (rc < 0)
+			return NF_DROP;
+		ssp->smk_set = rc;
 	}
 
 	return NF_ACCEPT;
-- 
2.17.0


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

* [PATCH 94/97] LSM: Hook for netlabel reconciliation
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (22 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 93/97] Smack: Use the NLTYPE on output Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 95/97] LSM: Avoid network conflicts in SELinux and Smack Casey Schaufler
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add an LSM function security_reconcile_netlbl() which
uses the new LSM hook socket_netlbl_secattr() to decide
if the active security modules are in agreement regarding
the labeling of a network packet.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hooks.h           | 15 +++++++++
 include/linux/security.h            |  9 ++++++
 security/security.c                 | 50 +++++++++++++++++++++++++++++
 security/selinux/hooks.c            |  3 ++
 security/selinux/include/netlabel.h |  7 ++++
 security/selinux/netlabel.c         |  9 ++++++
 security/smack/smack_lsm.c          |  9 ++++++
 7 files changed, 102 insertions(+)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index fec7f86897ea..2a53465f94da 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -29,6 +29,9 @@
 #include <linux/init.h>
 #include <linux/rculist.h>
 
+#ifdef CONFIG_NETLABEL
+struct netlbl_lsm_secattr;
+#endif
 /**
  * union security_list_options - Linux Security Module hook function list
  *
@@ -1416,6 +1419,10 @@
  * @bpf_prog_free_security:
  *	Clean up the security information stored inside bpf prog.
  *
+ * Security hooks for network labeling (Netlabel) operations.
+ *
+ * @socket_netlbl_secattr:
+ *	Report the netlabel attributes this module wants for this socket.
  */
 union security_list_options {
 	int (*binder_set_context_mgr)(struct task_struct *mgr);
@@ -1772,6 +1779,11 @@ union security_list_options {
 	int (*bpf_prog_alloc_security)(struct bpf_prog_aux *aux);
 	void (*bpf_prog_free_security)(struct bpf_prog_aux *aux);
 #endif /* CONFIG_BPF_SYSCALL */
+#ifdef CONFIG_NETLABEL
+	void (*socket_netlbl_secattr)(struct sock *sk,
+				      struct netlbl_lsm_secattr **secattr,
+				      int *set);
+#endif
 };
 
 struct security_hook_heads {
@@ -2006,6 +2018,9 @@ struct security_hook_heads {
 	struct hlist_head bpf_prog_alloc_security;
 	struct hlist_head bpf_prog_free_security;
 #endif /* CONFIG_BPF_SYSCALL */
+#ifdef CONFIG_NETLABEL
+	struct hlist_head socket_netlbl_secattr;
+#endif
 } __randomize_layout;
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index 7edceb91d77f..c9d7de811b53 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1878,5 +1878,14 @@ static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_BPF_SYSCALL */
 
+#ifdef CONFIG_NETLABEL
+extern int security_reconcile_netlbl(struct sock *sk);
+#else
+static inline int security_reconcile_netlbl(struct sock *sk)
+{
+	return 0;
+}
+#endif
+
 #endif /* ! __LINUX_SECURITY_H */
 
diff --git a/security/security.c b/security/security.c
index ab1050a2dce3..3c1d2f47b09f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -33,6 +33,9 @@
 #include <linux/msg.h>
 #include <net/flow.h>
 #include <net/sock.h>
+#ifdef CONFIG_NETLABEL
+#include <net/netlabel.h>
+#endif
 
 #define MAX_LSM_EVM_XATTR	2
 
@@ -2775,3 +2778,50 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux)
 	call_void_hook(bpf_prog_free_security, aux);
 }
 #endif /* CONFIG_BPF_SYSCALL */
+
+#ifdef CONFIG_NETLABEL
+int security_reconcile_netlbl(struct sock *sk)
+{
+	struct netlbl_lsm_secattr *prev = NULL;
+	struct netlbl_lsm_secattr *this = NULL;
+	int prev_set = 0;
+	int this_set = 0;
+	struct security_hook_list *hp;
+
+	hlist_for_each_entry(hp, &security_hook_heads.socket_netlbl_secattr,
+				list) {
+		hp->hook.socket_netlbl_secattr(sk, &this, &this_set);
+		if (this_set == 0 || this == NULL)
+			continue;
+		if (prev != NULL) {
+			/*
+			 * Both unlabeled is easily acceptable.
+			 */
+			if (prev_set == NETLBL_NLTYPE_UNLABELED &&
+			    this_set == NETLBL_NLTYPE_UNLABELED)
+				continue;
+			/*
+			 * The nltype being different means that
+			 * the secattrs aren't comparible. Except
+			 * that ADDRSELECT means that couldn't know
+			 * when the socket was created.
+			 */
+			if (prev_set != this_set &&
+			    prev_set != NETLBL_NLTYPE_ADDRSELECT &&
+			    this_set != NETLBL_NLTYPE_ADDRSELECT)
+				return -EACCES;
+			/*
+			 * Count on the Netlabel system's judgement.
+			 */
+			if (!netlbl_secattr_equal(prev, this))
+				return -EACCES;
+		}
+		prev = this;
+		prev_set = this_set;
+	}
+	/*
+	 * No conflicts have been found.
+	 */
+	return 0;
+}
+#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 22a190f291c0..84bfcf7ca08b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6769,6 +6769,9 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
 	LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
 #endif
+#ifdef CONFIG_NETLABEL
+	LSM_HOOK_INIT(socket_netlbl_secattr, selinux_socket_netlbl_secattr),
+#endif
 };
 
 static __init int selinux_init(void)
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 8671de09c363..b316c62e7bcc 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -69,6 +69,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr);
 int selinux_netlbl_socket_connect_locked(struct sock *sk,
 					 struct sockaddr *addr);
+void selinux_socket_netlbl_secattr(struct sock *sk,
+				   struct netlbl_lsm_secattr **secattr,
+				   int *set);
 
 #else
 static inline void selinux_netlbl_cache_invalidate(void)
@@ -165,6 +168,10 @@ static inline int selinux_netlbl_socket_connect_locked(struct sock *sk,
 {
 	return 0;
 }
+static inline void selinux_socket_netlbl_secattr(struct sock *sk,
+					struct netlbl_lsm_secattr **secattr)
+{
+}
 #endif /* CONFIG_NETLABEL */
 
 #endif
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index b6fd905e6e9e..56ae261d2805 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -642,3 +642,12 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
 
 	return rc;
 }
+
+void selinux_socket_netlbl_secattr(struct sock *sk,
+				   struct netlbl_lsm_secattr **secattr,
+				   int *set)
+{
+	struct sk_security_struct *sksec = selinux_sock(sk);
+	*secattr = sksec->nlbl_secattr;
+	*set = sksec->nlbl_set;
+}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1b9c7e5e801a..885e1799df00 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4487,6 +4487,14 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
 	}
 	return 0;
 }
+void smack_socket_netlbl_secattr(struct sock *sk,
+				 struct netlbl_lsm_secattr **secattr,
+				 int *set)
+{
+	struct socket_smack *ssp = smack_sock(sk);
+	*secattr = &ssp->smk_out->smk_netlabel;
+	*set = ssp->smk_set;
+}
 
 struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
 	.lbs_cred = sizeof(struct task_smack),
@@ -4638,6 +4646,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(inode_copy_up, smack_inode_copy_up),
 	LSM_HOOK_INIT(inode_copy_up_xattr, smack_inode_copy_up_xattr),
 	LSM_HOOK_INIT(dentry_create_files_as, smack_dentry_create_files_as),
+	LSM_HOOK_INIT(socket_netlbl_secattr, smack_socket_netlbl_secattr),
 };
 
 
-- 
2.17.0


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

* [PATCH 95/97] LSM: Avoid network conflicts in SELinux and Smack
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (23 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 94/97] LSM: Hook for netlabel reconciliation Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 96/97] LSM: Apply Netlabel consitancy checks on send and connect Casey Schaufler
  2019-02-28 22:43 ` [PATCH 97/97] Smack: Remove the exclusive bit Casey Schaufler
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Add calls to security_reconcile_netlbl() in SELinux and
Smack to ensure that only packets that are acceptable to
all active security modules get sent.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/selinux/hooks.c         | 3 +++
 security/smack/smack_netfilter.c | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 84bfcf7ca08b..4a8996b7b477 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5400,6 +5400,9 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
 		sid = SECINITSID_KERNEL;
 	if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
 		return NF_DROP;
+	/* verify that this IP option works with other security modules */
+	if (sk && security_reconcile_netlbl(sk))
+		return NF_DROP;
 
 	return NF_ACCEPT;
 }
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 7d202dde75b6..55cc38ae07f5 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -89,6 +89,8 @@ static unsigned int smack_ipv4_output(void *priv,
 			return NF_DROP;
 		ssp->smk_set = rc;
 	}
+	if (security_reconcile_netlbl(sk))
+		return NF_DROP;
 
 	return NF_ACCEPT;
 }
-- 
2.17.0


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

* [PATCH 96/97] LSM: Apply Netlabel consitancy checks on send and connect
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (24 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 95/97] LSM: Avoid network conflicts in SELinux and Smack Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  2019-02-28 22:43 ` [PATCH 97/97] Smack: Remove the exclusive bit Casey Schaufler
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Verify that all security modules agree on the network labeling
for sendmsg and connect.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/security.c              | 43 ++++++++++++++++++++++----------
 security/selinux/hooks.c         |  2 +-
 security/smack/smack_netfilter.c |  5 ++--
 3 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/security/security.c b/security/security.c
index 3c1d2f47b09f..dfee44ee4d19 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2355,7 +2355,13 @@ int security_socket_bind(struct socket *sock, struct sockaddr *address, int addr
 
 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
 {
-	return call_int_hook(socket_connect, 0, sock, address, addrlen);
+	int rc;
+
+	rc = call_int_hook(socket_connect, 0, sock, address, addrlen);
+	if (rc)
+		return rc;
+
+	return security_reconcile_netlbl(sock->sk);
 }
 
 int security_socket_listen(struct socket *sock, int backlog)
@@ -2370,6 +2376,12 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
 
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
+	int rc;
+
+	rc = security_reconcile_netlbl(sock->sk);
+	if (rc)
+		return rc;
+
 	return call_int_hook(socket_sendmsg, 0, sock, msg, size);
 }
 
@@ -2788,28 +2800,33 @@ int security_reconcile_netlbl(struct sock *sk)
 	int this_set = 0;
 	struct security_hook_list *hp;
 
+	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
+		return 0;
+
 	hlist_for_each_entry(hp, &security_hook_heads.socket_netlbl_secattr,
 				list) {
 		hp->hook.socket_netlbl_secattr(sk, &this, &this_set);
+		/*
+		 * If the NLTYPE has been deferred it's not
+		 * possible to decide now. A decision will be made
+		 * later.
+		 */
+		if (this_set == NETLBL_NLTYPE_ADDRSELECT)
+			return 0;
 		if (this_set == 0 || this == NULL)
 			continue;
 		if (prev != NULL) {
-			/*
-			 * Both unlabeled is easily acceptable.
-			 */
-			if (prev_set == NETLBL_NLTYPE_UNLABELED &&
-			    this_set == NETLBL_NLTYPE_UNLABELED)
-				continue;
 			/*
 			 * The nltype being different means that
-			 * the secattrs aren't comparible. Except
-			 * that ADDRSELECT means that couldn't know
-			 * when the socket was created.
+			 * the secattrs aren't comparible.
 			 */
-			if (prev_set != this_set &&
-			    prev_set != NETLBL_NLTYPE_ADDRSELECT &&
-			    this_set != NETLBL_NLTYPE_ADDRSELECT)
+			if (prev_set != this_set)
 				return -EACCES;
+			/*
+			 * Both unlabeled is easily acceptable.
+			 */
+			if (this_set == NETLBL_NLTYPE_UNLABELED)
+				continue;
 			/*
 			 * Count on the Netlabel system's judgement.
 			 */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4a8996b7b477..c924b454246b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5400,7 +5400,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
 		sid = SECINITSID_KERNEL;
 	if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
 		return NF_DROP;
-	/* verify that this IP option works with other security modules */
+
 	if (sk && security_reconcile_netlbl(sk))
 		return NF_DROP;
 
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 55cc38ae07f5..de4145c2cdd5 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -88,9 +88,10 @@ static unsigned int smack_ipv4_output(void *priv,
 		if (rc < 0)
 			return NF_DROP;
 		ssp->smk_set = rc;
+		rc = security_reconcile_netlbl(sk);
+		if (rc < 0)
+			return NF_DROP;
 	}
-	if (security_reconcile_netlbl(sk))
-		return NF_DROP;
 
 	return NF_ACCEPT;
 }
-- 
2.17.0


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

* [PATCH 97/97] Smack: Remove the exclusive bit
  2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
                   ` (25 preceding siblings ...)
  2019-02-28 22:43 ` [PATCH 96/97] LSM: Apply Netlabel consitancy checks on send and connect Casey Schaufler
@ 2019-02-28 22:43 ` Casey Schaufler
  26 siblings, 0 replies; 28+ messages in thread
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
  To: jmorris, linux-security-module, selinux
  Cc: keescook, john.johansen, penguin-kernel, paul

Smack can now be used with any of the existing security modules,
so remove the exclusive bit.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/smack_lsm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 885e1799df00..0c15e108726e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4727,7 +4727,7 @@ static __init int smack_init(void)
  */
 DEFINE_LSM(smack) = {
 	.name = "smack",
-	.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+	.flags = LSM_FLAG_LEGACY_MAJOR,
 	.blobs = &smack_blob_sizes,
 	.init = smack_init,
 };
-- 
2.17.0


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

end of thread, other threads:[~2019-02-28 22:46 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-28 22:43 [PATCH 00/97] LSM: Complete module stacking Casey Schaufler
2019-02-28 22:43 ` [PATCH 71/97] LSM: Add secmark refcounting to call_one list Casey Schaufler
2019-02-28 22:43 ` [PATCH 72/97] LSM: Add secmark refcounting to call_one list - part 2 Casey Schaufler
2019-02-28 22:43 ` [PATCH 73/97] LSM: refactor security_setprocattr Casey Schaufler
2019-02-28 22:43 ` [PATCH 74/97] Smack: Detect if secmarks can be safely used Casey Schaufler
2019-02-28 22:43 ` [PATCH 75/97] LSM: Support multiple LSMs using inode_init_security Casey Schaufler
2019-02-28 22:43 ` [PATCH 76/97] LSM: Use full security context in security_inode_setsecctx Casey Schaufler
2019-02-28 22:43 ` [PATCH 77/97] LSM: Correct handling of ENOSYS in inode_setxattr Casey Schaufler
2019-02-28 22:43 ` [PATCH 78/97] LSM: Infrastructure security blobs for mount options Casey Schaufler
2019-02-28 22:43 ` [PATCH 79/97] LSM: Fix for security_init_inode_security Casey Schaufler
2019-02-28 22:43 ` [PATCH 80/97] Smack: Advertise the secid to netlabel Casey Schaufler
2019-02-28 22:43 ` [PATCH 81/97] LSM: Change error detection for UDP peer security Casey Schaufler
2019-02-28 22:43 ` [PATCH 82/97] Smack: Fix setting of the CIPSO MLS_CAT flags Casey Schaufler
2019-02-28 22:43 ` [PATCH 83/97] Smack: Set netlabel flags properly on new label import Casey Schaufler
2019-02-28 22:43 ` [PATCH 84/97] Netlabel: Add a secattr comparison API function Casey Schaufler
2019-02-28 22:43 ` [PATCH 85/97] Smack: Let netlabel do the work on the ambient domain Casey Schaufler
2019-02-28 22:43 ` [PATCH 86/97] Smack: Don't set the socket label on each send Casey Schaufler
2019-02-28 22:43 ` [PATCH 87/97] Smack: Let netlabel do the work on connections Casey Schaufler
2019-02-28 22:43 ` [PATCH 88/97] Netlabel: Return the labeling type on socket Casey Schaufler
2019-02-28 22:43 ` [PATCH 89/97] " Casey Schaufler
2019-02-28 22:43 ` [PATCH 90/97] " Casey Schaufler
2019-02-28 22:43 ` [PATCH 91/97] " Casey Schaufler
2019-02-28 22:43 ` [PATCH 92/97] LSM: Remember the NLTYPE of netlabel sockets Casey Schaufler
2019-02-28 22:43 ` [PATCH 93/97] Smack: Use the NLTYPE on output Casey Schaufler
2019-02-28 22:43 ` [PATCH 94/97] LSM: Hook for netlabel reconciliation Casey Schaufler
2019-02-28 22:43 ` [PATCH 95/97] LSM: Avoid network conflicts in SELinux and Smack Casey Schaufler
2019-02-28 22:43 ` [PATCH 96/97] LSM: Apply Netlabel consitancy checks on send and connect Casey Schaufler
2019-02-28 22:43 ` [PATCH 97/97] Smack: Remove the exclusive bit Casey Schaufler

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).