[PATCH v2 bpf-next 2/4] af_unix: Call security_unix_may_send() in sendmsg() for all socket types
From: Kuniyuki Iwashima <hidden>
Date: 2025-06-13 22:24:18
Also in:
bpf, linux-security-module, selinux
Subsystem:
landlock security module, networking [general], networking [unix sockets], security subsystem, selinux security module, smack security module, the rest · Maintainers:
Mickaël Salaün, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Kuniyuki Iwashima, Paul Moore, James Morris, "Serge E. Hallyn", Stephen Smalley, Casey Schaufler, Linus Torvalds
From: Kuniyuki Iwashima <kuniyu@google.com> Currently, security_unix_may_send() is invoked only for SOCK_DGRAM sockets during connect() and sendmsg(). For SOCK_STREAM and SOCK_SEQPACKET sockets, an equivalent check already occurs during connect(), making an additional hook in sendmsg() unnecessary. However, we want to leverage BPF LSM to inspect UNIXCB(skb) during sendmsg(). As a preparation, let's call security_unix_may_send() for SOCK_STREAM and SOCK_SEQPACKET in sendmsg(). Note that SELinux, SMACK, and Landlock use security_unix_may_send(). To avoid unintentionally triggering the hook for SOCK_STREAM and SOCK_SEQPACKET, the socket type check is added in each LSM hooks. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> --- net/unix/af_unix.c | 30 +++++++++++++++++++++--------- security/landlock/task.c | 3 +++ security/selinux/hooks.c | 3 +++ security/smack/smack_lsm.c | 3 +++ 4 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6865da79ad1c..bcbe0c86e001 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c@@ -2170,11 +2170,9 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, goto out_unlock; } - if (sk->sk_type != SOCK_SEQPACKET) { - err = security_unix_may_send(sk, other); - if (err) - goto out_unlock; - } + err = security_unix_may_send(sk, other); + if (err) + goto out_unlock; /* other == sk && unix_peer(other) != sk if * - unix_peer(sk) == NULL, destination address bound to sk
@@ -2280,6 +2278,12 @@ static int queue_oob(struct sock *sk, struct msghdr *msg, struct sock *other, goto out_unlock; } + if (!fds_sent) { + err = security_unix_may_send(sk, other); + if (err) + goto out_unlock; + } + unix_maybe_add_creds(skb, sk, other); scm_stat_add(other, skb);
@@ -2372,8 +2376,6 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, if (err < 0) goto out_free; - fds_sent = true; - if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) { skb->ip_summed = CHECKSUM_UNNECESSARY; err = skb_splice_from_iter(skb, &msg->msg_iter, size,
@@ -2399,9 +2401,16 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, goto out_pipe_unlock; if (UNIXCB(skb).fp && !other->sk_scm_rights) { - unix_state_unlock(other); err = -EPERM; - goto out_free; + goto out_unlock; + } + + if (!fds_sent) { + err = security_unix_may_send(sk, other); + if (err) + goto out_unlock; + + fds_sent = true; } unix_maybe_add_creds(skb, sk, other);
@@ -2425,6 +2434,9 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, return sent; +out_unlock: + unix_state_unlock(other); + goto out_free; out_pipe_unlock: unix_state_unlock(other); out_pipe:
diff --git a/security/landlock/task.c b/security/landlock/task.c
index d7db70790a33..6bc6f3027790 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c@@ -305,6 +305,9 @@ static int hook_unix_may_send(struct sock *const sk, if (!subject) return 0; + if (sk->sk_type != SOCK_DGRAM) + return 0; + /* * Checks if this datagram socket was already allowed to be connected * to other.
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 07101a2bf942..904926ef9ee8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c@@ -5184,6 +5184,9 @@ static int selinux_socket_unix_may_send(struct sock *sk, struct common_audit_data ad; struct lsm_network_audit net; + if (sk->sk_type != SOCK_DGRAM) + return 0; + ad_net_init_from_sk(&ad, &net, other); return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 9bb00c0df373..20fe1d22210e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c@@ -3903,6 +3903,9 @@ static int smack_unix_may_send(struct sock *sk, struct sock *other) smk_ad_setfield_u_net_sk(&ad, other); #endif + if (sk->sk_type != SOCK_DGRAM) + return 0; + if (smack_privileged(CAP_MAC_OVERRIDE)) return 0;
--
2.49.0