[PATCH v1 bpf-next 1/5] af_unix: Call security_unix_may_send() in sendmsg() for all socket types
Kuniyuki Iwashima
kuniyu at amazon.com
Mon May 5 21:56:46 UTC 2025
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 the skb during
sendmsg(), either to scrub file descriptors passed via SCM_RIGHTS
or to reject such an skb.
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, an additional socket type check is added in each LSM.
Signed-off-by: Kuniyuki Iwashima <kuniyu at amazon.com>
---
net/unix/af_unix.c | 31 ++++++++++++++++++++++---------
security/landlock/task.c | 3 +++
security/selinux/hooks.c | 3 +++
security/smack/smack_lsm.c | 3 +++
4 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f78a2492826f..769db3f8f41b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2101,11 +2101,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->sk_socket, other->sk_socket);
- if (err)
- goto out_unlock;
- }
+ err = security_unix_may_send(sk->sk_socket, other->sk_socket);
+ if (err)
+ goto out_unlock;
/* other == sk && unix_peer(other) != sk if
* - unix_peer(sk) == NULL, destination address bound to sk
@@ -2201,9 +2199,14 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
if (sock_flag(other, SOCK_DEAD) ||
(other->sk_shutdown & RCV_SHUTDOWN)) {
- unix_state_unlock(other);
err = -EPIPE;
- goto out;
+ goto out_unlock;
+ }
+
+ if (!fds_sent) {
+ err = security_unix_may_send(sock, other->sk_socket);
+ if (err)
+ goto out_unlock;
}
maybe_add_creds(skb, sock, other);
@@ -2219,6 +2222,8 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
other->sk_data_ready(other);
return 0;
+out_unlock:
+ unix_state_unlock(other);
out:
consume_skb(skb);
return err;
@@ -2296,8 +2301,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,
@@ -2322,6 +2325,16 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
(other->sk_shutdown & RCV_SHUTDOWN))
goto out_pipe_unlock;
+ if (!fds_sent) {
+ err = security_unix_may_send(sock, other->sk_socket);
+ if (err) {
+ unix_state_unlock(other);
+ goto out_free;
+ }
+ }
+
+ fds_sent = true;
+
maybe_add_creds(skb, sock, other);
scm_stat_add(other, skb);
skb_queue_tail(&other->sk_receive_queue, skb);
diff --git a/security/landlock/task.c b/security/landlock/task.c
index 2385017418ca..f15e6b0c56f8 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -305,6 +305,9 @@ static int hook_unix_may_send(struct socket *const sock,
if (!subject)
return 0;
+ if (sock->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 e7a7dcab81db..9fb4cd442ffd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5106,6 +5106,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
struct common_audit_data ad;
struct lsm_network_audit net;
+ if (sock->sk->sk_type != SOCK_DGRAM)
+ return 0;
+
ad_net_init_from_sk(&ad, &net, other->sk);
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 99833168604e..00aa1e7513c1 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3904,6 +3904,9 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
smk_ad_setfield_u_net_sk(&ad, other->sk);
#endif
+ if (sock->sk->sk_type != SOCK_DGRAM)
+ return 0;
+
if (smack_privileged(CAP_MAC_OVERRIDE))
return 0;
--
2.49.0
More information about the Linux-security-module-archive
mailing list