[v7,15/16] LSM: Avoid network conflicts in SELinux and Smack
diff mbox series

Message ID 20190807224245.10798-17-casey@schaufler-ca.com
State New
Headers show
Series
  • LSM: Full module stacking
Related show

Commit Message

Casey Schaufler Aug. 7, 2019, 10:42 p.m. UTC
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. 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         |  3 +++
 security/smack/smack_netfilter.c |  8 ++++--
 3 files changed, 39 insertions(+), 15 deletions(-)

Patch
diff mbox series

diff --git a/security/security.c b/security/security.c
index bfe40c11f5bf..4897c68cdb71 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2496,7 +2496,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)
@@ -2511,6 +2517,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);
 }
 
@@ -3016,28 +3028,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 48468a4b478c..293350b672a8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5522,6 +5522,9 @@  static unsigned int selinux_ip_output(struct sk_buff *skb,
 	if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
 		return NF_DROP;
 
+	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 7b9c8d5d8408..92aeffbbb27c 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -75,7 +75,7 @@  static unsigned int smack_ipv4_output(void *priv,
 					const struct nf_hook_state *state)
 {
 	struct sock *sk = skb_to_full_sk(skb);
-	struct socket_smack *ssp;
+	struct socket_smack *ssp = NULL;
 	struct smack_known *skp;
 
 	if (!smack_checked_secmark) {
@@ -84,11 +84,15 @@  static unsigned int smack_ipv4_output(void *priv,
 		smack_checked_secmark = true;
 	}
 
-	if (smack_use_secmark && sk && smack_sock(sk)) {
+	if (sk && smack_sock(sk))
 		ssp = smack_sock(sk);
+
+	if (smack_use_secmark && ssp) {
 		skp = ssp->smk_out;
 		skb->secmark = skp->smk_secid;
 	}
+	if (sk && security_reconcile_netlbl(sk))
+		return NF_DROP;
 
 	return NF_ACCEPT;
 }