All of lore.kernel.org
 help / color / mirror / Atom feed
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 5/5] selftest: bpf: Add test for bpf_unix_scrub_fds().
Date: Mon, 5 May 2025 14:56:50 -0700	[thread overview]
Message-ID: <20250505215802.48449-6-kuniyu@amazon.com> (raw)
In-Reply-To: <20250505215802.48449-1-kuniyu@amazon.com>

This test performs the following for all AF_UNIX socket types

  1. Create a socket pair (sender and receiver)
  2. Send the receiver's fd from the sender to the receiver
  3. Receive the fd
  4. Attach a BPF LSM prog that scrubs SCM_RIGHTS fds
  5. Send the receiver's fd from the sender to the receiver
  6. Check if the fd was scrubbed
  7. Detach the LSM prog

How to run:

  # make -C tools/testing/selftests/bpf/
  # ./tools/testing/selftests/bpf/test_progs -t lsm_unix_may_send
  ...
  #175/1   lsm_unix_may_send/SOCK_STREAM:OK
  #175/2   lsm_unix_may_send/SOCK_DGRAM:OK
  #175/3   lsm_unix_may_send/SOCK_SEQPACKET:OK
  #175     lsm_unix_may_send:OK
  Summary: 1/3 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 .../bpf/prog_tests/lsm_unix_may_send.c        | 160 ++++++++++++++++++
 .../selftests/bpf/progs/lsm_unix_may_send.c   |  30 ++++
 2 files changed, 190 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_unix_may_send.c
 create mode 100644 tools/testing/selftests/bpf/progs/lsm_unix_may_send.c

diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_unix_may_send.c b/tools/testing/selftests/bpf/prog_tests/lsm_unix_may_send.c
new file mode 100644
index 000000000000..50b2547e63cf
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/lsm_unix_may_send.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright Amazon.com Inc. or its affiliates. */
+
+#include "test_progs.h"
+#include "lsm_unix_may_send.skel.h"
+
+#define MSG_HELLO "Hello"
+#define MSG_WORLD "World"
+#define MSG_LEN 5
+
+struct scm_rights {
+	struct cmsghdr cmsghdr;
+	int fd;
+};
+
+static int send_fd(int sender_fd, int receiver_fd)
+{
+	struct scm_rights cmsg = {};
+	struct msghdr msg = {};
+	struct iovec iov = {};
+	int ret;
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = &cmsg;
+	msg.msg_controllen = CMSG_SPACE(sizeof(cmsg.fd));
+
+	iov.iov_base = MSG_HELLO;
+	iov.iov_len = MSG_LEN;
+
+	cmsg.cmsghdr.cmsg_len = CMSG_LEN(sizeof(cmsg.fd));
+	cmsg.cmsghdr.cmsg_level = SOL_SOCKET;
+	cmsg.cmsghdr.cmsg_type = SCM_RIGHTS;
+	cmsg.fd = receiver_fd;
+
+	ret = sendmsg(sender_fd, &msg, 0);
+	if (!ASSERT_EQ(ret, MSG_LEN, "sendmsg(Hello)"))
+		return -EINVAL;
+
+	ret = send(sender_fd, MSG_WORLD, MSG_LEN, 0);
+	if (!ASSERT_EQ(ret, MSG_LEN, "sendmsg(World)"))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int recv_fd(int receiver_fd, bool lsm_attached)
+{
+	struct scm_rights cmsg = {};
+	struct msghdr msg = {};
+	char buf[MSG_LEN] = {};
+	struct iovec iov = {};
+	int ret;
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = &cmsg;
+	msg.msg_controllen = CMSG_SPACE(sizeof(cmsg.fd));
+
+	iov.iov_base = buf;
+	iov.iov_len = sizeof(buf);
+
+	ret = recvmsg(receiver_fd, &msg, 0);
+	if (!ASSERT_EQ(ret, MSG_LEN, "recvmsg(Hello) length") ||
+	    !ASSERT_STRNEQ(buf, MSG_HELLO, MSG_LEN, "recvmsg(Hello) data"))
+		return -EINVAL;
+
+	if (lsm_attached) {
+		if (!ASSERT_ERR_PTR(CMSG_FIRSTHDR(&msg), "cmsg filtered"))
+			return -EINVAL;
+	} else {
+		if (!ASSERT_OK_PTR(CMSG_FIRSTHDR(&msg), "cmsg sent") ||
+		    !ASSERT_EQ(cmsg.cmsghdr.cmsg_len, CMSG_LEN(sizeof(cmsg.fd)), "cmsg_len") ||
+		    !ASSERT_EQ(cmsg.cmsghdr.cmsg_level, SOL_SOCKET, "cmsg_level") ||
+		    !ASSERT_EQ(cmsg.cmsghdr.cmsg_type, SCM_RIGHTS, "cmsg_type"))
+			return -EINVAL;
+
+		receiver_fd = cmsg.fd;
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = recv(receiver_fd, buf, sizeof(buf), 0);
+	if (!ASSERT_EQ(ret, MSG_LEN, "recvmsg(World) length") ||
+	    !ASSERT_STRNEQ(buf, MSG_WORLD, MSG_LEN, "recvmsg(World) data"))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void test_scm_rights(struct lsm_unix_may_send *skel, int type)
+{
+	struct bpf_link *link;
+	int socket_fds[2];
+	int err;
+
+	err = socketpair(AF_UNIX, type, 0, socket_fds);
+	if (!ASSERT_EQ(err, 0, "socketpair"))
+		return;
+
+	err = send_fd(socket_fds[0], socket_fds[1]);
+	if (err)
+		goto close;
+
+	err = recv_fd(socket_fds[1], false);
+	if (err)
+		goto close;
+
+	link = bpf_program__attach_lsm(skel->progs.unix_scrub_scm_rights);
+	if (!ASSERT_OK_PTR(link, "attach lsm"))
+		goto close;
+
+	err = send_fd(socket_fds[0], socket_fds[1]);
+	if (err)
+		goto close;
+
+	err = recv_fd(socket_fds[1], true);
+	if (err)
+		goto close;
+
+	err = bpf_link__destroy(link);
+	ASSERT_EQ(err, 0, "destroy lsm");
+close:
+	close(socket_fds[0]);
+	close(socket_fds[1]);
+}
+
+struct sk_type {
+	char name[16];
+	int type;
+} sk_types[] = {
+	{
+		.name = "SOCK_STREAM",
+		.type = SOCK_STREAM,
+	},
+	{
+		.name = "SOCK_DGRAM",
+		.type = SOCK_DGRAM,
+	},
+	{
+		.name = "SOCK_SEQPACKET",
+		.type = SOCK_SEQPACKET,
+	},
+};
+
+void test_lsm_unix_may_send(void)
+{
+	struct lsm_unix_may_send *skel;
+	int i;
+
+	skel = lsm_unix_may_send__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "load skel"))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(sk_types); i++)
+		if (test__start_subtest(sk_types[i].name))
+			test_scm_rights(skel, sk_types[i].type);
+
+	lsm_unix_may_send__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/lsm_unix_may_send.c b/tools/testing/selftests/bpf/progs/lsm_unix_may_send.c
new file mode 100644
index 000000000000..c2459ba2c33d
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/lsm_unix_may_send.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright Amazon.com Inc. or its affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_tracing.h>
+
+#ifndef EPERM
+#define EPERM 1
+#endif
+
+SEC("lsm/unix_may_send")
+int BPF_PROG(unix_scrub_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;
+
+	if (bpf_unix_scrub_fds(skb))
+		return -EPERM;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.49.0


  parent reply	other threads:[~2025-05-05 22:00 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 ` [PATCH v1 bpf-next 2/5] af_unix: Pass skb to security_unix_may_send() Kuniyuki Iwashima
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 ` Kuniyuki Iwashima [this message]
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-6-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.