[PATCH v2 bpf-next 1/4] af_unix: Don't pass struct socket to security_unix_may_send().
From: Kuniyuki Iwashima <hidden>
Date: 2025-06-13 22:24:17
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> The next patch will invoke security_unix_may_send() in unix_stream_sendmsg(). At that point, the peer socket may not have sk->sk_socket if it has not been accept()ed yet, which would cause null-ptr-deref. Currently, all security_unix_may_send() hooks fetch struct sock from struct socket but do not use struct socket itself. Let's pass struct sock directly to security_unix_may_send(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> --- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 6 +++--- net/unix/af_unix.c | 4 ++-- security/landlock/task.c | 12 ++++++------ security/security.c | 4 ++-- security/selinux/hooks.c | 10 +++++----- security/smack/smack_lsm.c | 8 ++++---- 7 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index bf3bbac4e02a..9be001922e0b 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h@@ -318,7 +318,7 @@ LSM_HOOK(int, 0, watch_key, struct key *key) #ifdef CONFIG_SECURITY_NETWORK LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other, struct sock *newsk) -LSM_HOOK(int, 0, unix_may_send, struct socket *sock, struct socket *other) +LSM_HOOK(int, 0, unix_may_send, struct sock *sock, struct sock *other) LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern) LSM_HOOK(int, 0, socket_post_create, struct socket *sock, int family, int type, int protocol, int kern)
diff --git a/include/linux/security.h b/include/linux/security.h
index dba349629229..36aa7030e16d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h@@ -1625,7 +1625,7 @@ static inline int security_watch_key(struct key *key) int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk); -int security_unix_may_send(struct socket *sock, struct socket *other); +int security_unix_may_send(struct sock *sk, struct sock *other); int security_socket_create(int family, int type, int protocol, int kern); int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern);
@@ -1691,8 +1691,8 @@ static inline int security_unix_stream_connect(struct sock *sock, return 0; } -static inline int security_unix_may_send(struct socket *sock, - struct socket *other) +static inline int security_unix_may_send(struct sock *sk, + struct sock *other) { return 0; }
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2e2e9997a68e..6865da79ad1c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c@@ -1516,7 +1516,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, if (!unix_may_send(sk, other)) goto out_unlock; - err = security_unix_may_send(sk->sk_socket, other->sk_socket); + err = security_unix_may_send(sk, other); if (err) goto out_unlock;
@@ -2171,7 +2171,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, } if (sk->sk_type != SOCK_SEQPACKET) { - err = security_unix_may_send(sk->sk_socket, other->sk_socket); + err = security_unix_may_send(sk, other); if (err) goto out_unlock; }
diff --git a/security/landlock/task.c b/security/landlock/task.c
index 2385017418ca..d7db70790a33 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c@@ -294,8 +294,8 @@ static int hook_unix_stream_connect(struct sock *const sock, return -EPERM; } -static int hook_unix_may_send(struct socket *const sock, - struct socket *const other) +static int hook_unix_may_send(struct sock *const sk, + struct sock *const other) { size_t handle_layer; const struct landlock_cred_security *const subject =
@@ -309,13 +309,13 @@ static int hook_unix_may_send(struct socket *const sock, * Checks if this datagram socket was already allowed to be connected * to other. */ - if (unix_peer(sock->sk) == other->sk) + if (unix_peer(sk) == other) return 0; - if (!is_abstract_socket(other->sk)) + if (!is_abstract_socket(other)) return 0; - if (!sock_is_scoped(other->sk, subject->domain)) + if (!sock_is_scoped(other, subject->domain)) return 0; landlock_log_denial(subject, &(struct landlock_request) {
@@ -323,7 +323,7 @@ static int hook_unix_may_send(struct socket *const sock, .audit = { .type = LSM_AUDIT_DATA_NET, .u.net = &(struct lsm_network_audit) { - .sk = other->sk, + .sk = other, }, }, .layer_plus_one = handle_layer + 1,
diff --git a/security/security.c b/security/security.c
index 596d41818577..3bd8eec01d05 100644
--- a/security/security.c
+++ b/security/security.c@@ -4531,9 +4531,9 @@ EXPORT_SYMBOL(security_unix_stream_connect); * * Return: Returns 0 if permission is granted. */ -int security_unix_may_send(struct socket *sock, struct socket *other) +int security_unix_may_send(struct sock *sk, struct sock *other) { - return call_int_hook(unix_may_send, sock, other); + return call_int_hook(unix_may_send, sk, other); } EXPORT_SYMBOL(security_unix_may_send);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 595ceb314aeb..07101a2bf942 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c@@ -5176,15 +5176,15 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, return 0; } -static int selinux_socket_unix_may_send(struct socket *sock, - struct socket *other) +static int selinux_socket_unix_may_send(struct sock *sk, + struct sock *other) { - struct sk_security_struct *ssec = selinux_sock(sock->sk); - struct sk_security_struct *osec = selinux_sock(other->sk); + struct sk_security_struct *ssec = selinux_sock(sk); + struct sk_security_struct *osec = selinux_sock(other); struct common_audit_data ad; struct lsm_network_audit net; - ad_net_init_from_sk(&ad, &net, other->sk); + ad_net_init_from_sk(&ad, &net, other); return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, &ad);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index fc340a6f0dde..9bb00c0df373 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c@@ -3889,10 +3889,10 @@ static int smack_unix_stream_connect(struct sock *sock, * Return 0 if a subject with the smack of sock could access * an object with the smack of other, otherwise an error code */ -static int smack_unix_may_send(struct socket *sock, struct socket *other) +static int smack_unix_may_send(struct sock *sk, struct sock *other) { - struct socket_smack *ssp = smack_sock(sock->sk); - struct socket_smack *osp = smack_sock(other->sk); + struct socket_smack *ssp = smack_sock(sk); + struct socket_smack *osp = smack_sock(other); struct smk_audit_info ad; int rc;
@@ -3900,7 +3900,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) struct lsm_network_audit net; smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - smk_ad_setfield_u_net_sk(&ad, other->sk); + smk_ad_setfield_u_net_sk(&ad, other); #endif if (smack_privileged(CAP_MAC_OVERRIDE))
--
2.49.0