[PATCH] selinux: use socket SID for SCTP bind/connect permission checks in softirq

Tristan Madani <[email protected]>
Newsgroups org.kernel.vger.selinux,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
__selinux_socket_bind() and selinux_socket_connect_helper() call
sock_has_perm() which uses current_sid() as the AVC subject.  When
selinux_sctp_bind_connect() is invoked from the ASCONF softirq path
(sctp_process_asconf), current is whichever process was interrupted,
so the permission check uses an unrelated subject SID.

Thread an explicit caller SID through __selinux_socket_bind() and
selinux_socket_connect_helper().  The process-context wrappers
(selinux_socket_bind, selinux_socket_connect) pass current_sid(), and
selinux_sctp_bind_connect() passes the socket own SID (sksec->sid),
consistent with other softirq-context hooks such as
selinux_socket_sock_rcv_skb() and selinux_sctp_assoc_request().

Factor out __sock_has_perm() with an explicit subject SID parameter
so that sock_has_perm() remains unchanged for all other callers.

Fixes: d452930fd3b9 ("selinux: Add SCTP support")
Cc: [email protected]
Signed-off-by: Tristan Madani <[email protected]>
---
 security/selinux/hooks.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8d6945edae7a..1071c304faba 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4916,7 +4916,7 @@ static bool sock_skip_has_perm(u32 sid)
 }
 
 
-static int sock_has_perm(struct sock *sk, u32 perms)
+static int __sock_has_perm(struct sock *sk, u32 sid, u32 perms)
 {
 	struct sk_security_struct *sksec = selinux_sock(sk);
 	struct common_audit_data ad;
@@ -4927,10 +4927,15 @@ static int sock_has_perm(struct sock *sk, u32 perms)
 
 	ad_net_init_from_sk(&ad, &net, sk);
 
-	return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
+	return avc_has_perm(sid, sksec->sid, sksec->sclass, perms,
 			    &ad);
 }
 
+static int sock_has_perm(struct sock *sk, u32 perms)
+{
+	return __sock_has_perm(sk, current_sid(), perms);
+}
+
 static int selinux_socket_create(int family, int type,
 				 int protocol, int kern)
 {
@@ -5000,13 +5005,14 @@ static int selinux_socket_socketpair(struct socket *socka,
    Need to determine whether we should perform a name_bind
    permission check between the socket and the port number. */
 
-static int __selinux_socket_bind(struct sock *sk, struct sockaddr *address, int addrlen)
+static int __selinux_socket_bind(struct sock *sk, u32 caller_sid,
+				struct sockaddr *address, int addrlen)
 {
 	struct sk_security_struct *sksec = selinux_sock(sk);
 	u16 family;
 	int err;
 
-	err = sock_has_perm(sk, SOCKET__BIND);
+	err = __sock_has_perm(sk, caller_sid, SOCKET__BIND);
 	if (err)
 		goto out;
 
@@ -5133,19 +5139,19 @@ static int __selinux_socket_bind(struct sock *sk, struct sockaddr *address, int
 
 static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
 {
-	return __selinux_socket_bind(sock->sk, address, addrlen);
+	return __selinux_socket_bind(sock->sk, current_sid(), address, addrlen);
 }
 
 /* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
  * and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
  */
-static int selinux_socket_connect_helper(struct sock *sk,
+static int selinux_socket_connect_helper(struct sock *sk, u32 caller_sid,
 					 struct sockaddr *address, int addrlen)
 {
 	struct sk_security_struct *sksec = selinux_sock(sk);
 	int err;
 
-	err = sock_has_perm(sk, SOCKET__CONNECT);
+	err = __sock_has_perm(sk, caller_sid, SOCKET__CONNECT);
 	if (err)
 		return err;
 	if (addrlen < offsetofend(struct sockaddr, sa_family))
@@ -5230,7 +5236,7 @@ static int selinux_socket_connect(struct socket *sock,
 	int err;
 	struct sock *sk = sock->sk;
 
-	err = selinux_socket_connect_helper(sk, address, addrlen);
+	err = selinux_socket_connect_helper(sk, current_sid(), address, addrlen);
 	if (err)
 		return err;
 
@@ -5729,6 +5735,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
 				     struct sockaddr *address,
 				     int addrlen)
 {
+	struct sk_security_struct *sksec = selinux_sock(sk);
 	int len, err = 0, walk_size = 0;
 	void *addr_buf;
 	struct sockaddr *addr;
@@ -5765,14 +5772,14 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
 		case SCTP_PRIMARY_ADDR:
 		case SCTP_SET_PEER_PRIMARY_ADDR:
 		case SCTP_SOCKOPT_BINDX_ADD:
-			err = __selinux_socket_bind(sk, addr, len);
+			err = __selinux_socket_bind(sk, sksec->sid, addr, len);
 			break;
 		/* Connect checks */
 		case SCTP_SOCKOPT_CONNECTX:
 		case SCTP_PARAM_SET_PRIMARY:
 		case SCTP_PARAM_ADD_IP:
 		case SCTP_SENDMSG_CONNECT:
-			err = selinux_socket_connect_helper(sk, addr, len);
+			err = selinux_socket_connect_helper(sk, sksec->sid, addr, len);
 			if (err)
 				return err;
 
-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.