Re: selinux: support IPPROTO_SMC in socket_type_to_security_class()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Aug 15, 2024 at 10:32 AM Jeongjun Park <aha310510@xxxxxxxxx> wrote:
>
> IPPROTO_SMC feature has been added to net/smc. It is now possible to
> create smc sockets in the following way:
>
>   /* create v4 smc sock */
>   v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_SMC);
>
>   /* create v6 smc sock */
>   v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_SMC);
>
> Therefore, we need to add code to support IPPROTO_SMC in
> socket_type_to_security_class().
>
> Signed-off-by: Jeongjun Park <aha310510@xxxxxxxxx>
> ---
>  security/selinux/hooks.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index bfa61e005aac..36f951f0c574 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -1176,6 +1176,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
>                                 return SECCLASS_TCP_SOCKET;
>                         else if (extsockclass && protocol == IPPROTO_SCTP)
>                                 return SECCLASS_SCTP_SOCKET;
> +                       else if (extsockclass && protocol == IPPROTO_SMC)
> +                               return SECCLASS_SMC_SOCKET;
>                         else
>                                 return SECCLASS_RAWIP_SOCKET;
>                 case SOCK_DGRAM:
> --
>

I'm not sure if this is the solution we want to go with... Consider
the following from af_smc(7):

>   Usage modes
>      Two usage modes are possible:
>
>      AF_SMC native usage
>             uses the socket domain AF_SMC instead of AF_INET and AF_INET6.  Specify SMCPROTO_SMC for AF_INET compatible socket semantics, and SMC_PROTO_SMC6 for AF_INET6 respectively.
>
>      Usage of AF_INET socket applications with SMC preload library
>             converts AF_INET and AF_INET6 sockets to AF_SMC sockets.  The SMC preload library is part of the SMC tools package.
>
>      SMC socket capabilities are negotiated at connection setup. If one peer is not SMC capable, further socket processing falls back to TCP usage automatically.

This means that the SMC sockets are intended to be used (also) as a
drop-in compatible replacement for normal TCP sockets in applications
and they even fall back to TCP when the endpoints fail to negotiate
communication via SMC. That's a situation similar to MPTCP, where we
just mapped MPTCP sockets to the tcp_socket SELinux class, so that
MPTCP can be swapped in place of TCP transparently without having to
do extensive policy changes. We may want to consider the same/similar
approach here.

I briefly played with this idea a couple of months ago, when I was
asked by someone at Red Hat about SMC sockets and their integration
with SELinux. IIRC, when I tried to implement the MPTCP approach and
adjusted the selinux-testsuite to test SMC similarly as TCP and MPTCP,
I saw that the netlabel-related tests (may have been more, I don't
remember) weren't passing out of the box like with MPTCP. However, the
person then didn't follow up on my questions, so I didn't look into it
further...

I'm attaching the WIP patches I worked with, in case someone would
like to continue the experiments.

--
Ondrej Mosnacek
Senior Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.
commit e6dca1fd3c713eaf69ff16fb23c6dc683082a2f8
Author: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
Date:   Tue Feb 6 15:39:21 2024 +0100

    TEST

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 55c78c318ccd..a5db62130d41 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1292,7 +1292,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
 		case PF_QIPCRTR:
 			return SECCLASS_QIPCRTR_SOCKET;
 		case PF_SMC:
-			return SECCLASS_SMC_SOCKET;
+			return SECCLASS_TCP_SOCKET;
 		case PF_XDP:
 			return SECCLASS_XDP_SOCKET;
 		case PF_MCTP:
@@ -4772,6 +4772,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 			}
 		}
 
+		// FIXME: do the same here
 		switch (sksec->sclass) {
 		case SECCLASS_TCP_SOCKET:
 			node_perm = TCP_SOCKET__NODE_BIND;
@@ -4852,6 +4853,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
 		struct sockaddr_in6 *addr6 = NULL;
 		unsigned short snum;
 		u32 sid, perm;
+		u8 protocol;
 
 		/* sctp_connectx(3) calls via selinux_sctp_bind_connect()
 		 * that validates multiple connect addresses. Because of this
@@ -4881,22 +4883,25 @@ static int selinux_socket_connect_helper(struct socket *sock,
 				return -EAFNOSUPPORT;
 		}
 
-		err = sel_netport_sid(sk->sk_protocol, snum, &sid);
-		if (err)
-			return err;
-
 		switch (sksec->sclass) {
 		case SECCLASS_TCP_SOCKET:
+			protocol = IPPROTO_TCP;
 			perm = TCP_SOCKET__NAME_CONNECT;
 			break;
 		case SECCLASS_DCCP_SOCKET:
+			protocol = IPPROTO_DCCP;
 			perm = DCCP_SOCKET__NAME_CONNECT;
 			break;
 		case SECCLASS_SCTP_SOCKET:
+			protocol = IPPROTO_SCTP;
 			perm = SCTP_SOCKET__NAME_CONNECT;
 			break;
 		}
 
+		err = sel_netport_sid(protocol, snum, &sid);
+		if (err)
+			return err;
+
 		ad.type = LSM_AUDIT_DATA_NET;
 		ad.u.net = &net;
 		ad.u.net->dport = htons(snum);
commit 23fd91fff6b4004a3e0e5e7a0b6ca5a97be3d20b
Author: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
Date:   Tue Feb 6 15:12:39 2024 +0100

    WIP

diff --git a/tests/inet_socket/client.c b/tests/inet_socket/client.c
index d3fedf4..188d8ce 100644
--- a/tests/inet_socket/client.c
+++ b/tests/inet_socket/client.c
@@ -64,6 +64,9 @@ int main(int argc, char **argv)
 		hints.ai_socktype = SOCK_STREAM;
 		hints.ai_protocol = IPPROTO_TCP;
 		sockprotocol      = IPPROTO_MPTCP;
+	} else if (!strcmp(argv[optind], "smc")) {
+		hints.ai_socktype = SOCK_STREAM;
+		hints.ai_protocol = IPPROTO_TCP;
 	} else if (!strcmp(argv[optind], "udp")) {
 		hints.ai_socktype = SOCK_DGRAM;
 		hints.ai_protocol = IPPROTO_UDP;
@@ -79,6 +82,20 @@ int main(int argc, char **argv)
 		exit(2);
 	}
 
+	if (!strcmp(argv[optind], "smc")) {
+		switch (serverinfo->ai_family) {
+		case AF_INET:
+			sockprotocol = 0; /* SMC_PROTO_SMC */
+			break;
+		case AF_INET6:
+			sockprotocol = 1; /* SMC_PROTO_SMC6 */
+			break;
+		default:
+			usage(argv[0]);
+		}
+		serverinfo->ai_family = AF_SMC;
+	}
+
 	sock = socket(serverinfo->ai_family, serverinfo->ai_socktype,
 		      sockprotocol);
 	if (sock < 0) {
diff --git a/tests/inet_socket/server.c b/tests/inet_socket/server.c
index 63b6849..baa3c93 100644
--- a/tests/inet_socket/server.c
+++ b/tests/inet_socket/server.c
@@ -74,6 +74,10 @@ int main(int argc, char **argv)
 		hints.ai_socktype = SOCK_STREAM;
 		hints.ai_protocol = IPPROTO_TCP;
 		sockprotocol      = IPPROTO_MPTCP;
+	} else if (!strcmp(argv[optind], "smc")) {
+		hints.ai_socktype = SOCK_STREAM;
+		hints.ai_protocol = IPPROTO_TCP;
+		sockprotocol      = 1; /* SMC_PROTO_SMC6 */
 	} else if (!strcmp(argv[optind], "udp")) {
 		hints.ai_socktype = SOCK_DGRAM;
 		hints.ai_protocol = IPPROTO_UDP;
@@ -88,6 +92,9 @@ int main(int argc, char **argv)
 		exit(1);
 	}
 
+	if (!strcmp(argv[optind], "smc"))
+		res->ai_family = AF_SMC;
+
 	sock = socket(res->ai_family, res->ai_socktype, sockprotocol);
 	if (sock < 0) {
 		perror("socket");
diff --git a/tests/inet_socket/smc b/tests/inet_socket/smc
new file mode 120000
index 0000000..945c9b4
--- /dev/null
+++ b/tests/inet_socket/smc
@@ -0,0 +1 @@
+.
\ No newline at end of file
diff --git a/tests/inet_socket/test b/tests/inet_socket/test
index 08c7b1d..545988a 100755
--- a/tests/inet_socket/test
+++ b/tests/inet_socket/test
@@ -8,7 +8,12 @@ BEGIN {
     chomp($basedir);
     $proto = basename($basedir);
 
-    if ( $proto eq "tcp" or $proto eq "mptcp" ) {
+    # check if SMC is enabled
+    if ( $proto eq "smc" and system("modprobe smc 2>/dev/null") != 0 ) {
+        plan skip_all => "SMC protocol not supported";
+    }
+
+    if ( $proto eq "tcp" or $proto eq "mptcp" or $proto eq "smc" ) {
         $is_stream   = 1;
         $fail_value1 = 5;
         $fail_value2 = 5;

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux