From: Kuniyuki Iwashima <kuniyu@amazon.com>
To: Martin KaFai Lau <martin.lau@linux.dev>,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>,
"Alexei Starovoitov" <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>
Cc: "Eduard Zingerman" <eddyz87@gmail.com>,
"Song Liu" <song@kernel.org>,
"Yonghong Song" <yonghong.song@linux.dev>,
"KP Singh" <kpsingh@kernel.org>,
"Stanislav Fomichev" <sdf@fomichev.me>,
"Hao Luo" <haoluo@google.com>, "Jiri Olsa" <jolsa@kernel.org>,
"Mickaël Salaün" <mic@digikod.net>,
"Günther Noack" <gnoack@google.com>,
"Paul Moore" <paul@paul-moore.com>,
"James Morris" <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
"Stephen Smalley" <stephen.smalley.work@gmail.com>,
"Ondrej Mosnacek" <omosnace@redhat.com>,
"Casey Schaufler" <casey@schaufler-ca.com>,
"Christian Brauner" <brauner@kernel.org>,
"Kuniyuki Iwashima" <kuniyu@amazon.com>,
"Kuniyuki Iwashima" <kuni1840@gmail.com>,
bpf@vger.kernel.org, netdev@vger.kernel.org,
linux-security-module@vger.kernel.org, selinux@vger.kernel.org
Subject: [PATCH v1 bpf-next 2/5] af_unix: Pass skb to security_unix_may_send().
Date: Mon, 5 May 2025 14:56:47 -0700 [thread overview]
Message-ID: <20250505215802.48449-3-kuniyu@amazon.com> (raw)
In-Reply-To: <20250505215802.48449-1-kuniyu@amazon.com>
As long as recvmsg() or recvmmsg() is used with cmsg, it is not
possible to avoid receiving file descriptors via SCM_RIGHTS.
This behaviour has occasionally been flagged as problematic.
For instance, as noted on the uAPI Group page [0], an untrusted peer
could send a file descriptor pointing to a hung NFS mount and then
close it. Once the receiver calls recvmsg() with msg_control, the
descriptor is automatically installed, and then the responsibility
for the final close() now falls on the receiver, which may result
in blocking the process for a long time.
Let's pass the skb to security_unix_may_send() so that BPF LSM can
inspect it and selectively prevent such a sendmsg().
Note that only the LSM_HOOK() macro uses the __nullable suffix for
skb to inform the verifier that the skb could be NULL at connect().
Without it, I was able to load a bpf prog without NULL check
against skb.
Sample:
SEC("lsm/unix_may_send")
int BPF_PROG(unix_refuse_scm_rights,
struct socket *sock, struct socket *other, struct sk_buff *skb)
{
struct unix_skb_parms *cb;
if (!skb)
return 0;
cb = (struct unix_skb_parms *)skb->cb;
if (!cb->fp)
return 0;
return -EPERM;
}
Link: https://uapi-group.org/kernel-features/#disabling-reception-of-scm_rights-for-af_unix-sockets #[0]
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
I guess there is no generic version of raw_tp_null_args[] ?
---
include/linux/lsm_hook_defs.h | 3 ++-
include/linux/security.h | 5 +++--
net/unix/af_unix.c | 8 ++++----
security/landlock/task.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
security/smack/smack_lsm.c | 3 ++-
7 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index bf3bbac4e02a..762c7f2f7dee 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -318,7 +318,8 @@ 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 socket *sock, struct socket *other,
+ struct sk_buff *skb__nullable)
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 cc9b54d95d22..5de77accee80 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1630,7 +1630,7 @@ static inline int security_watch_key(struct key *key)
#ifdef CONFIG_SECURITY_NETWORK
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 socket *sock, struct socket *other, struct sk_buff *skb);
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);
@@ -1692,7 +1692,8 @@ static inline int security_unix_stream_connect(struct sock *sock,
}
static inline int security_unix_may_send(struct socket *sock,
- struct socket *other)
+ struct socket *other,
+ struct sk_buff *skb)
{
return 0;
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 769db3f8f41b..692cce579c89 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1447,7 +1447,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->sk_socket, other->sk_socket, NULL);
if (err)
goto out_unlock;
@@ -2101,7 +2101,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out_unlock;
}
- err = security_unix_may_send(sk->sk_socket, other->sk_socket);
+ err = security_unix_may_send(sk->sk_socket, other->sk_socket, skb);
if (err)
goto out_unlock;
@@ -2204,7 +2204,7 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
}
if (!fds_sent) {
- err = security_unix_may_send(sock, other->sk_socket);
+ err = security_unix_may_send(sock, other->sk_socket, skb);
if (err)
goto out_unlock;
}
@@ -2326,7 +2326,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
goto out_pipe_unlock;
if (!fds_sent) {
- err = security_unix_may_send(sock, other->sk_socket);
+ err = security_unix_may_send(sock, other->sk_socket, skb);
if (err) {
unix_state_unlock(other);
goto out_free;
diff --git a/security/landlock/task.c b/security/landlock/task.c
index f15e6b0c56f8..aeb712d3fa8f 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -295,7 +295,8 @@ static int hook_unix_stream_connect(struct sock *const sock,
}
static int hook_unix_may_send(struct socket *const sock,
- struct socket *const other)
+ struct socket *const other,
+ struct sk_buff *skb)
{
size_t handle_layer;
const struct landlock_cred_security *const subject =
diff --git a/security/security.c b/security/security.c
index fb57e8fddd91..875dbc7ba34f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -4531,9 +4531,10 @@ 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 socket *sock, struct socket *other,
+ struct sk_buff *skb)
{
- return call_int_hook(unix_may_send, sock, other);
+ return call_int_hook(unix_may_send, sock, other, skb);
}
EXPORT_SYMBOL(security_unix_may_send);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9fb4cd442ffd..fcf14fb76e7f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5099,7 +5099,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
}
static int selinux_socket_unix_may_send(struct socket *sock,
- struct socket *other)
+ struct socket *other,
+ struct sk_buff *skb)
{
struct sk_security_struct *ssec = selinux_sock(sock->sk);
struct sk_security_struct *osec = selinux_sock(other->sk);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 00aa1e7513c1..33827f4c5c76 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3890,7 +3890,8 @@ 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 socket *sock, struct socket *other,
+ struct sk_buff *skb)
{
struct socket_smack *ssp = smack_sock(sock->sk);
struct socket_smack *osp = smack_sock(other->sk);
--
2.49.0
next prev parent reply other threads:[~2025-05-05 21:59 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-05 21:56 [PATCH v1 bpf-next 0/5] af_unix: Allow BPF LSM to scrub SCM_RIGHTS at sendmsg() Kuniyuki Iwashima
2025-05-05 21:56 ` [PATCH v1 bpf-next 1/5] af_unix: Call security_unix_may_send() in sendmsg() for all socket types Kuniyuki Iwashima
2025-05-05 21:56 ` Kuniyuki Iwashima [this message]
2025-05-05 21:56 ` [PATCH v1 bpf-next 3/5] af_unix: Remove redundant scm->fp check in __scm_destroy() Kuniyuki Iwashima
2025-05-09 14:13 ` kernel test robot
2025-05-05 21:56 ` [PATCH v1 bpf-next 4/5] bpf: Add kfunc to scrub SCM_RIGHTS at security_unix_may_send() Kuniyuki Iwashima
2025-05-06 0:13 ` Alexei Starovoitov
2025-05-06 8:25 ` Mickaël Salaün
2025-05-09 15:06 ` kernel test robot
2025-05-05 21:56 ` [PATCH v1 bpf-next 5/5] selftest: bpf: Add test for bpf_unix_scrub_fds() Kuniyuki Iwashima
2025-05-05 22:49 ` [PATCH v1 bpf-next 0/5] af_unix: Allow BPF LSM to scrub SCM_RIGHTS at sendmsg() Kumar Kartikeya Dwivedi
2025-05-06 0:21 ` Kuniyuki Iwashima
2025-05-06 16:25 ` Kumar Kartikeya Dwivedi
2025-05-06 18:16 ` Kuniyuki Iwashima
2025-05-06 9:15 ` Christian Brauner
2025-05-06 16:08 ` Kumar Kartikeya Dwivedi
2025-05-06 18:14 ` Kuniyuki Iwashima
2025-05-05 23:21 ` Paul Moore
2025-05-06 0:35 ` Kuniyuki Iwashima
2025-05-06 14:57 ` Paul Moore
2025-05-06 12:17 ` Lennart Poettering
2025-05-06 18:19 ` Kuniyuki Iwashima
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250505215802.48449-3-kuniyu@amazon.com \
--to=kuniyu@amazon.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=casey@schaufler-ca.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=gnoack@google.com \
--cc=haoluo@google.com \
--cc=jmorris@namei.org \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=kuni1840@gmail.com \
--cc=linux-security-module@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=mic@digikod.net \
--cc=netdev@vger.kernel.org \
--cc=omosnace@redhat.com \
--cc=paul@paul-moore.com \
--cc=sdf@fomichev.me \
--cc=selinux@vger.kernel.org \
--cc=serge@hallyn.com \
--cc=song@kernel.org \
--cc=stephen.smalley.work@gmail.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.