Re: [PATCH 08/10] selftests/net: SO_PEERPIDFD_THREAD
From: Alexander Mikhalitsyn
Date: Mon Sep 07 2026 - 07:00:45 EST
Am Mo., 31. Aug. 2026 um 13:21 Uhr schrieb Christian Brauner
<brauner@xxxxxxxxxx>:
>
> Add tests for SO_PEERPIDFD_THREAD.
>
> Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
LGTM
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@xxxxxxxxxxxxxx>
> ---
> tools/testing/selftests/net/af_unix/scm_pidfd.c | 97 +++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/tools/testing/selftests/net/af_unix/scm_pidfd.c b/tools/testing/selftests/net/af_unix/scm_pidfd.c
> index 019c48e1cdcd..bbbd5e7b4fa7 100644
> --- a/tools/testing/selftests/net/af_unix/scm_pidfd.c
> +++ b/tools/testing/selftests/net/af_unix/scm_pidfd.c
> @@ -32,6 +32,10 @@
> #define SO_PASSPIDFD_THREAD 86
> #endif
>
> +#ifndef SO_PEERPIDFD_THREAD
> +#define SO_PEERPIDFD_THREAD 87
> +#endif
> +
> #define CHILD_EXIT_CODE_OK 123
>
> static void child_die()
> @@ -822,4 +826,97 @@ TEST(scm_pidfd_thread_creds)
> EXPECT_EQ(ids.pid, info.tgid);
> }
>
> +static void *peer_connect_thread(void *arg)
> +{
> + struct sock_addr *sa = arg;
> + struct thread_ids ids = {
> + .pid = getpid(),
> + .tid = gettid(),
> + };
> + int fd;
> + char sync;
> +
> + fd = socket(AF_UNIX, SOCK_STREAM, 0);
> + if (fd < 0)
> + return (void *)1;
> +
> + if (connect(fd, (struct sockaddr *)&sa->listen_addr, sa->addrlen))
> + return (void *)1;
> +
> + if (send(fd, &ids, sizeof(ids), 0) != sizeof(ids))
> + return (void *)1;
> +
> + /* stay alive until the server has looked at our pidfd */
> + if (read(fd, &sync, 1) != 1)
> + return (void *)1;
> +
> + close(fd);
> + return NULL;
> +}
> +
> +static int peer_pidfd_info(int fd, int optname, struct pidfd_info *info)
> +{
> + int pidfd;
> + socklen_t len = sizeof(pidfd);
> +
> + if (getsockopt(fd, SOL_SOCKET, optname, &pidfd, &len)) {
> + log_err("getsockopt(SO_PEERPIDFD*)");
> + return -1;
> + }
> +
> + info->mask = PIDFD_INFO_PID;
> + if (ioctl(pidfd, PIDFD_GET_INFO, info)) {
> + log_err("ioctl(PIDFD_GET_INFO)");
> + close(pidfd);
> + return -1;
> + }
> +
> + close(pidfd);
> + return 0;
> +}
> +
> +/* SO_PEERPIDFD_THREAD returns a pidfd for the peer's connecting thread. */
> +TEST(so_peerpidfd_thread)
> +{
> + struct sock_addr sa;
> + struct thread_ids ids;
> + struct pidfd_info info;
> + pthread_t thread;
> + void *tret;
> + int server, cfd;
> +
> + server = socket(AF_UNIX, SOCK_STREAM, 0);
> + ASSERT_LE(0, server);
> +
> + fill_sockaddr(&sa, true);
> + ASSERT_EQ(0, bind(server, (struct sockaddr *)&sa.listen_addr, sa.addrlen));
> + ASSERT_EQ(0, listen(server, 1));
> +
> + ASSERT_EQ(0, pthread_create(&thread, NULL, peer_connect_thread, &sa));
> +
> + cfd = accept(server, NULL, NULL);
> + ASSERT_LE(0, cfd);
> +
> + ASSERT_EQ(sizeof(ids), recv(cfd, &ids, sizeof(ids), MSG_WAITALL));
> + ASSERT_NE(ids.pid, ids.tid);
> +
> + /* SO_PEERPIDFD refers to the peer's thread-group. */
> + ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD, &info));
> + EXPECT_EQ(ids.pid, info.pid);
> + EXPECT_EQ(ids.pid, info.tgid);
> +
> + /* SO_PEERPIDFD_THREAD refers to the connecting thread. */
> + ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD_THREAD, &info));
> + EXPECT_EQ(ids.tid, info.pid);
> + EXPECT_EQ(ids.pid, info.tgid);
> +
> + /* release the connecting thread */
> + ASSERT_EQ(1, write(cfd, "x", 1));
> + ASSERT_EQ(0, pthread_join(thread, &tret));
> + ASSERT_EQ(NULL, tret);
> +
> + close(cfd);
> + close(server);
> +}
> +
> TEST_HARNESS_MAIN
>
> --
> 2.53.0
>