mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] tomoyo: fix socket permission checks
@ 2026-09-22 15:57 Tetsuo Handa
  2026-09-24  0:34 ` kernel test robot
  0 siblings, 1 reply; 2+ messages in thread
From: Tetsuo Handa @ 2026-09-22 15:57 UTC (permalink / raw)
  To: LKML; +Cc: Matthieu Buffet

This is a squashed patch addressing three problems.

[PATCH 1/3] tomoyo: Enforce connect policy in TCP Fast Open

  Tomoyo restricted TCP connections in 2011 in commit
  059d84dbb389 ("TOMOYO: Add socket operation restriction support.")
  using the socket_connect() LSM hook.

  However, the MSG_FASTOPEN sendmsg() flag was added in 2012 to allow
  combining connect() and the first sendmsg(). Tomoyo was not updated to
  take this into account in its send hook.

  This resulted in a TCP connect policy bypass similar to that reported in
  Landlock in 2024 (see Link below), with the difference that Tomoyo was
  fine when originally merged, and the problem got introduced when adding
  fastopen support, possibly due to lack of synchronization between lsm
  and netdev worlds.

  Add MSG_FASTOPEN handling in Tomoyo's existing send hook.

  Link: https://github.com/landlock-lsm/linux/issues/41
  Link: https://lore.kernel.org/all/20260616201615.275032-1-hexlabsecurity@proton.me/
  Fixes: cf60af03ca4e ("net-tcp: Fast Open client - sendmsg(MSG_FASTOPEN)")
  Cc: stable@kernel.org
  Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
  [penguin-kernel: Modified to use tomoyo_sock_family() in order to exempt
  kernel services. Also, modified not to check sk->sk_protocol because
  conditions to check became too complicated and error prone because of
  the second patch.]

[PATCH 2/3] tomoyo: Handle SMC socket

  During the sashiko's review on the first patch, sashiko pointed out that
  TOMOYO is not checking PF_SMC sockets. If a socket was created using
  socket(PF_SMC, SOCK_STREAM) instead of socket(PF_INET, SOCK_STREAM),
  tomoyo_sock_family() was returning 0 despite PF_SMC sockets can communicate
  like PF_INET socket. Check permissions on PF_SMC sockets, by adding PF_SMC
  to tomoyo_sock_family() and tomoyo_socket_sendmsg_permission().

  Link: https://sashiko.dev/#/patchset/20260619002207.61104-1-matthieu%40buffet.re

[PATCH 3/3] tomoyo: Handle SCTP socket

  During the sashiko's review on the first patch, sashiko pointed out that
  TOMOYO is not checking SCTP sockets. Implement sctp_bind_connect callback,
  using selinux_sctp_bind_connect() as template. Since sctp_bind_connect
  callback receives pointer to "struct sock", update existing socket hooks
  to receive pointer to "struct sock". Also, extend policy profile structure
  because SCTP allows socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP).

  Link: https://sashiko.dev/#/patchset/20260619002207.61104-1-matthieu%40buffet.re

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/common.c  |  3 ++
 security/tomoyo/common.h  | 12 +++----
 security/tomoyo/network.c | 52 ++++++++++++++++------------
 security/tomoyo/tomoyo.c  | 73 +++++++++++++++++++++++++++++++++++++--
 security/tomoyo/util.c    |  3 ++
 5 files changed, 112 insertions(+), 31 deletions(-)

diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index fdaeaff01fc1..d645a17d7348 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -54,6 +54,9 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
 	[TOMOYO_MAC_NETWORK_INET_DGRAM_SEND]        = "inet_dgram_send",
 	[TOMOYO_MAC_NETWORK_INET_RAW_BIND]          = "inet_raw_bind",
 	[TOMOYO_MAC_NETWORK_INET_RAW_SEND]          = "inet_raw_send",
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_BIND]    = "inet_seqpacket_bind",
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_LISTEN]  = "inet_seqpacket_listen",
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_CONNECT] = "inet_seqpacket_connect",
 	[TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND]       = "unix_stream_bind",
 	[TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN]     = "unix_stream_listen",
 	[TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT]    = "unix_stream_connect",
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index d098cf8aae61..6db83be62077 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -354,6 +354,9 @@ enum tomoyo_mac_index {
 	TOMOYO_MAC_NETWORK_INET_DGRAM_SEND,
 	TOMOYO_MAC_NETWORK_INET_RAW_BIND,
 	TOMOYO_MAC_NETWORK_INET_RAW_SEND,
+	TOMOYO_MAC_NETWORK_INET_SEQPACKET_BIND,
+	TOMOYO_MAC_NETWORK_INET_SEQPACKET_LISTEN,
+	TOMOYO_MAC_NETWORK_INET_SEQPACKET_CONNECT,
 	TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND,
 	TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN,
 	TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT,
@@ -1023,13 +1026,10 @@ int tomoyo_path_perm(const u8 operation, const struct path *path,
 		     const char *target);
 __poll_t tomoyo_poll_control(struct file *file, poll_table *wait);
 __poll_t tomoyo_poll_log(struct file *file, poll_table *wait);
-int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
-				  int addr_len);
-int tomoyo_socket_connect_permission(struct socket *sock,
-				     struct sockaddr *addr, int addr_len);
+int tomoyo_socket_bind_permission(struct sock *sk, struct sockaddr *addr, int addr_len);
+int tomoyo_socket_connect_permission(struct sock *sk, struct sockaddr *addr, int addr_len);
 int tomoyo_socket_listen_permission(struct socket *sock);
-int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
-				     int size);
+int tomoyo_socket_sendmsg_permission(struct sock *sk, struct msghdr *msg, int size);
 int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 	__must_hold_shared(&tomoyo_ss)
 	__printf(2, 3);
diff --git a/security/tomoyo/network.c b/security/tomoyo/network.c
index cfc2a019de1e..938e10613bb5 100644
--- a/security/tomoyo/network.c
+++ b/security/tomoyo/network.c
@@ -152,6 +152,11 @@ static const u8 tomoyo_inet2mac
 		[TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_INET_RAW_BIND,
 		[TOMOYO_NETWORK_SEND]    = TOMOYO_MAC_NETWORK_INET_RAW_SEND,
 	},
+	[SOCK_SEQPACKET] = {
+		[TOMOYO_NETWORK_BIND]    = TOMOYO_MAC_NETWORK_INET_SEQPACKET_BIND,
+		[TOMOYO_NETWORK_LISTEN]  = TOMOYO_MAC_NETWORK_INET_SEQPACKET_LISTEN,
+		[TOMOYO_NETWORK_CONNECT] = TOMOYO_MAC_NETWORK_INET_SEQPACKET_CONNECT,
+	},
 };
 
 /*
@@ -636,6 +641,7 @@ static u8 tomoyo_sock_family(struct sock *sk)
 	switch (family) {
 	case PF_INET:
 	case PF_INET6:
+	case PF_SMC:
 	case PF_UNIX:
 		return family;
 	default:
@@ -680,18 +686,17 @@ int tomoyo_socket_listen_permission(struct socket *sock)
 /**
  * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket.
  *
- * @sock:     Pointer to "struct socket".
+ * @sk:       Pointer to "struct sock".
  * @addr:     Pointer to "struct sockaddr".
  * @addr_len: Size of @addr.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_socket_connect_permission(struct socket *sock,
-				     struct sockaddr *addr, int addr_len)
+int tomoyo_socket_connect_permission(struct sock *sk, struct sockaddr *addr, int addr_len)
 {
 	struct tomoyo_addr_info address;
-	const u8 family = tomoyo_sock_family(sock->sk);
-	const unsigned int type = sock->type;
+	const u8 family = tomoyo_sock_family(sk);
+	const unsigned int type = sk->sk_type;
 
 	if (!family)
 		return 0;
@@ -710,25 +715,23 @@ int tomoyo_socket_connect_permission(struct socket *sock,
 	}
 	if (family == PF_UNIX)
 		return tomoyo_check_unix_address(addr, addr_len, &address);
-	return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
-					 &address);
+	return tomoyo_check_inet_address(addr, addr_len, sk->sk_protocol, &address);
 }
 
 /**
  * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket.
  *
- * @sock:     Pointer to "struct socket".
+ * @sk:       Pointer to "struct sock".
  * @addr:     Pointer to "struct sockaddr".
  * @addr_len: Size of @addr.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
-				  int addr_len)
+int tomoyo_socket_bind_permission(struct sock *sk, struct sockaddr *addr, int addr_len)
 {
 	struct tomoyo_addr_info address;
-	const u8 family = tomoyo_sock_family(sock->sk);
-	const unsigned int type = sock->type;
+	const u8 family = tomoyo_sock_family(sk);
+	const unsigned int type = sk->sk_type;
 
 	if (!family)
 		return 0;
@@ -745,28 +748,33 @@ int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
 	}
 	if (family == PF_UNIX)
 		return tomoyo_check_unix_address(addr, addr_len, &address);
-	return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
-					 &address);
+	return tomoyo_check_inet_address(addr, addr_len, sk->sk_protocol, &address);
 }
 
 /**
  * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram.
  *
- * @sock: Pointer to "struct socket".
+ * @sk:   Pointer to "struct sock".
  * @msg:  Pointer to "struct msghdr".
  * @size: Unused.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
-				     int size)
+int tomoyo_socket_sendmsg_permission(struct sock *sk, struct msghdr *msg, int size)
 {
 	struct tomoyo_addr_info address;
-	const u8 family = tomoyo_sock_family(sock->sk);
-	const unsigned int type = sock->type;
+	const u8 family = tomoyo_sock_family(sk);
+	const unsigned int type = sk->sk_type;
 
-	if (!msg->msg_name || !family ||
-	    (type != SOCK_DGRAM && type != SOCK_RAW))
+	if (!msg->msg_name || !family)
+		return 0;
+	if ((msg->msg_flags & MSG_FASTOPEN) && type == SOCK_STREAM && family != PF_UNIX) {
+		address.protocol = SOCK_STREAM;
+		address.operation = TOMOYO_NETWORK_CONNECT;
+		return tomoyo_check_inet_address((struct sockaddr *)msg->msg_name,
+						 msg->msg_namelen, 0, &address);
+	}
+	if (type != SOCK_DGRAM && type != SOCK_RAW)
 		return 0;
 	address.protocol = type;
 	address.operation = TOMOYO_NETWORK_SEND;
@@ -776,5 +784,5 @@ int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
 						 msg->msg_namelen, &address);
 	return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
 					 msg->msg_namelen,
-					 sock->sk->sk_protocol, &address);
+					 sk->sk_protocol, &address);
 }
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index c66e02ed8ee3..2968a8ce14e1 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -8,6 +8,7 @@
 #include <linux/lsm_hooks.h>
 #include <uapi/linux/lsm.h>
 #include "common.h"
+#include <linux/sctp.h>
 
 /**
  * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread.
@@ -468,7 +469,7 @@ static int tomoyo_socket_listen(struct socket *sock, int backlog)
 static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr,
 				 int addr_len)
 {
-	return tomoyo_socket_connect_permission(sock, addr, addr_len);
+	return tomoyo_socket_connect_permission(sock->sk, addr, addr_len);
 }
 
 /**
@@ -483,7 +484,7 @@ static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr,
 static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr,
 			      int addr_len)
 {
-	return tomoyo_socket_bind_permission(sock, addr, addr_len);
+	return tomoyo_socket_bind_permission(sock->sk, addr, addr_len);
 }
 
 /**
@@ -498,7 +499,72 @@ static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr,
 static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
 				 int size)
 {
-	return tomoyo_socket_sendmsg_permission(sock, msg, size);
+	return tomoyo_socket_sendmsg_permission(sock->sk, msg, size);
+}
+
+/**
+ * tomoyo_sctp_bind_connect - Check permission for sctp's bind or connext.
+ *
+ * @sk:      Pointer to "struct sock".
+ * @optname: Type of operation.
+ * @address: Pointer to "struct sockaddr".
+ * @addrlen: Size of @address.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address,
+				    int addrlen)
+{
+	int len, err, walk_size = 0;
+	void *addr_buf;
+	struct sockaddr *addr;
+
+	/* Process one or more addresses that may be IPv4 or IPv6 */
+	addr_buf = address;
+
+	while (walk_size < addrlen) {
+		if (walk_size + sizeof(sa_family_t) > addrlen)
+			return -EINVAL;
+
+		addr = addr_buf;
+		switch (addr->sa_family) {
+		case AF_INET:
+			len = sizeof(struct sockaddr_in);
+			break;
+		case AF_INET6:
+			len = sizeof(struct sockaddr_in6);
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (walk_size + len > addrlen)
+			return -EINVAL;
+
+		switch (optname) {
+		/* Bind checks */
+		case SCTP_PRIMARY_ADDR:
+		case SCTP_SET_PEER_PRIMARY_ADDR:
+		case SCTP_SOCKOPT_BINDX_ADD:
+			err = tomoyo_socket_bind_permission(sk, addr, len);
+			if (err)
+				return err;
+			break;
+		/* Connect checks */
+		case SCTP_SOCKOPT_CONNECTX:
+		case SCTP_PARAM_SET_PRIMARY:
+		case SCTP_PARAM_ADD_IP:
+		case SCTP_SENDMSG_CONNECT:
+			err = tomoyo_socket_connect_permission(sk, addr, len);
+			if (err)
+				return err;
+			break;
+		}
+
+		addr_buf += len;
+		walk_size += len;
+	}
+
+	return 0;
 }
 
 struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
@@ -583,6 +649,7 @@ static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect),
 	LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen),
 	LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg),
+	LSM_HOOK_INIT(sctp_bind_connect, tomoyo_sctp_bind_connect),
 };
 
 /* Lock for GC. */
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 6799b1122c9d..b27b7036e860 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -60,6 +60,9 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
 	TOMOYO_MAC_CATEGORY_NETWORK,
 	[TOMOYO_MAC_NETWORK_INET_RAW_SEND]          =
 	TOMOYO_MAC_CATEGORY_NETWORK,
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_BIND]    = TOMOYO_MAC_CATEGORY_NETWORK,
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_LISTEN]  = TOMOYO_MAC_CATEGORY_NETWORK,
+	[TOMOYO_MAC_NETWORK_INET_SEQPACKET_CONNECT] = TOMOYO_MAC_CATEGORY_NETWORK,
 	[TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND]       =
 	TOMOYO_MAC_CATEGORY_NETWORK,
 	[TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN]     =
-- 
2.52.0


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

* Re: [PATCH] tomoyo: fix socket permission checks
  2026-09-22 15:57 [PATCH] tomoyo: fix socket permission checks Tetsuo Handa
@ 2026-09-24  0:34 ` kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-09-24  0:34 UTC (permalink / raw)
  To: Tetsuo Handa, LKML; +Cc: oe-kbuild-all, Matthieu Buffet

Hi Tetsuo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v7.3-rc4 next-20260922]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tetsuo-Handa/tomoyo-fix-socket-permission-checks/20260923-005744
base:   linus/master
patch link:    https://lore.kernel.org/r/db497449-b16b-4a61-9f06-fbbe7a3dcc73%40I-love.SAKURA.ne.jp
patch subject: [PATCH] tomoyo: fix socket permission checks
config: i386-randconfig-1300-20260924 (https://download.01.org/0day-ci/archive/20260924/202609240841.x5ug9vqH-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260924/202609240841.x5ug9vqH-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609240841.x5ug9vqH-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> security/tomoyo/tomoyo.c:554:22: sparse: sparse: restricted __be16 degrades to integer
   security/tomoyo/tomoyo.c:555:22: sparse: sparse: restricted __be16 degrades to integer

vim +554 security/tomoyo/tomoyo.c

   504	
   505	/**
   506	 * tomoyo_sctp_bind_connect - Check permission for sctp's bind or connext.
   507	 *
   508	 * @sk:      Pointer to "struct sock".
   509	 * @optname: Type of operation.
   510	 * @address: Pointer to "struct sockaddr".
   511	 * @addrlen: Size of @address.
   512	 *
   513	 * Returns 0 on success, negative value otherwise.
   514	 */
   515	static int tomoyo_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address,
   516					    int addrlen)
   517	{
   518		int len, err, walk_size = 0;
   519		void *addr_buf;
   520		struct sockaddr *addr;
   521	
   522		/* Process one or more addresses that may be IPv4 or IPv6 */
   523		addr_buf = address;
   524	
   525		while (walk_size < addrlen) {
   526			if (walk_size + sizeof(sa_family_t) > addrlen)
   527				return -EINVAL;
   528	
   529			addr = addr_buf;
   530			switch (addr->sa_family) {
   531			case AF_INET:
   532				len = sizeof(struct sockaddr_in);
   533				break;
   534			case AF_INET6:
   535				len = sizeof(struct sockaddr_in6);
   536				break;
   537			default:
   538				return -EINVAL;
   539			}
   540			if (walk_size + len > addrlen)
   541				return -EINVAL;
   542	
   543			switch (optname) {
   544			/* Bind checks */
   545			case SCTP_PRIMARY_ADDR:
   546			case SCTP_SET_PEER_PRIMARY_ADDR:
   547			case SCTP_SOCKOPT_BINDX_ADD:
   548				err = tomoyo_socket_bind_permission(sk, addr, len);
   549				if (err)
   550					return err;
   551				break;
   552			/* Connect checks */
   553			case SCTP_SOCKOPT_CONNECTX:
 > 554			case SCTP_PARAM_SET_PRIMARY:
   555			case SCTP_PARAM_ADD_IP:
   556			case SCTP_SENDMSG_CONNECT:
   557				err = tomoyo_socket_connect_permission(sk, addr, len);
   558				if (err)
   559					return err;
   560				break;
   561			}
   562	
   563			addr_buf += len;
   564			walk_size += len;
   565		}
   566	
   567		return 0;
   568	}
   569	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2026-09-24  0:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-22 15:57 [PATCH] tomoyo: fix socket permission checks Tetsuo Handa
2026-09-24  0:34 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®