Re: [PATCH 07/10] net: add SO_PEERPIDFD_THREAD to get a thread-specific pidfd

From: Alexander Mikhalitsyn

Date: Mon Sep 07 2026 - 07:05:02 EST


Am Mo., 31. Aug. 2026 um 13:21 Uhr schrieb Christian Brauner
<brauner@xxxxxxxxxx>:
>
> SO_PEERPIDFD hands out a pidfd for the thread-group that called
> connect() or socketpair(). Enable workloads such as the coredump server
> or a broker to get a pidfd of the specific thread that connected to the
> socket.
>
> Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>

LGTM

Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@xxxxxxxxxxxxxx>

> ---
> arch/alpha/include/uapi/asm/socket.h | 2 +
> arch/mips/include/uapi/asm/socket.h | 2 +
> arch/parisc/include/uapi/asm/socket.h | 2 +
> arch/sparc/include/uapi/asm/socket.h | 2 +
> include/uapi/asm-generic/socket.h | 2 +
> net/core/sock.c | 87 ++++++++++++++++++++---------------
> net/unix/af_unix.c | 1 +
> 7 files changed, 61 insertions(+), 37 deletions(-)
>
> diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
> index bb3d534826bb..5d3524c26b2b 100644
> --- a/arch/alpha/include/uapi/asm/socket.h
> +++ b/arch/alpha/include/uapi/asm/socket.h
> @@ -159,6 +159,8 @@
>
> #define SO_PASSPIDFD_THREAD 86
>
> +#define SO_PEERPIDFD_THREAD 87
> +
> #if !defined(__KERNEL__)
>
> #if __BITS_PER_LONG == 64
> diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
> index 269badcaa086..245a43f52fb1 100644
> --- a/arch/mips/include/uapi/asm/socket.h
> +++ b/arch/mips/include/uapi/asm/socket.h
> @@ -170,6 +170,8 @@
>
> #define SO_PASSPIDFD_THREAD 86
>
> +#define SO_PEERPIDFD_THREAD 87
> +
> #if !defined(__KERNEL__)
>
> #if __BITS_PER_LONG == 64
> diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
> index 313aee10a52c..f23710e1c671 100644
> --- a/arch/parisc/include/uapi/asm/socket.h
> +++ b/arch/parisc/include/uapi/asm/socket.h
> @@ -151,6 +151,8 @@
>
> #define SO_PASSPIDFD_THREAD 0x4054
>
> +#define SO_PEERPIDFD_THREAD 0x4055
> +
> #if !defined(__KERNEL__)
>
> #if __BITS_PER_LONG == 64
> diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
> index bd3e69bcce7a..b35b25bdefc2 100644
> --- a/arch/sparc/include/uapi/asm/socket.h
> +++ b/arch/sparc/include/uapi/asm/socket.h
> @@ -152,6 +152,8 @@
>
> #define SO_PASSPIDFD_THREAD 0x005f
>
> +#define SO_PEERPIDFD_THREAD 0x0060
> +
> #if !defined(__KERNEL__)
>
>
> diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
> index d1e5c6de146d..56fed7ab27ab 100644
> --- a/include/uapi/asm-generic/socket.h
> +++ b/include/uapi/asm-generic/socket.h
> @@ -154,6 +154,8 @@
>
> #define SO_PASSPIDFD_THREAD 86
>
> +#define SO_PEERPIDFD_THREAD 87
> +
> #if !defined(__KERNEL__)
>
> #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 6ada7e7eb7d7..cb2ffd329bc6 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1743,6 +1743,50 @@ static int groups_to_user(sockptr_t dst, const struct group_info *src)
> return 0;
> }
>
> +/* Hand out a pidfd for @type of the socket's peer via SO_PEERPIDFD*. */
> +static int sk_getsockopt_peerpidfd(struct sock *sk, enum pid_type type,
> + sockptr_t optval, sockptr_t optlen, int len)
> +{
> + struct file *pidfd_file = NULL;
> + unsigned int flags = 0;
> + struct pid *peer_pid;
> + int pidfd;
> +
> + if (len > sizeof(pidfd))
> + len = sizeof(pidfd);
> +
> + spin_lock(&sk->sk_peer_lock);
> + peer_pid = get_pid(sk->sk_peer_pid[type]);
> + spin_unlock(&sk->sk_peer_lock);
> +
> + if (!peer_pid)
> + return -ENODATA;
> +
> + /* The use of PIDFD_STALE requires stashing of struct pid on pidfs
> + * with pidfs_register_pid() and only AF_UNIX were prepared for this.
> + */
> + if (sk->sk_family == AF_UNIX)
> + flags |= PIDFD_STALE;
> + if (type == PIDTYPE_PID)
> + flags |= PIDFD_THREAD;
> +
> + pidfd = pidfd_prepare(peer_pid, flags, &pidfd_file);
> + put_pid(peer_pid);
> + if (pidfd < 0)
> + return pidfd;
> +
> + if (copy_to_sockptr(optval, &pidfd, len) ||
> + copy_to_sockptr(optlen, &len, sizeof(int))) {
> + put_unused_fd(pidfd);
> + fput(pidfd_file);
> +
> + return -EFAULT;
> + }
> +
> + fd_install(pidfd, pidfd_file);
> + return 0;
> +}
> +
> int sk_getsockopt(struct sock *sk, int level, int optname,
> sockptr_t optval, sockptr_t optlen)
> {
> @@ -1938,45 +1982,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
> }
>
> case SO_PEERPIDFD:
> - {
> - struct pid *peer_pid;
> - struct file *pidfd_file = NULL;
> - unsigned int flags = 0;
> - int pidfd;
> -
> - if (len > sizeof(pidfd))
> - len = sizeof(pidfd);
> -
> - spin_lock(&sk->sk_peer_lock);
> - peer_pid = get_pid(sk->sk_peer_pid[PIDTYPE_TGID]);
> - spin_unlock(&sk->sk_peer_lock);
> -
> - if (!peer_pid)
> - return -ENODATA;
> -
> - /* The use of PIDFD_STALE requires stashing of struct pid
> - * on pidfs with pidfs_register_pid() and only AF_UNIX
> - * were prepared for this.
> - */
> - if (sk->sk_family == AF_UNIX)
> - flags = PIDFD_STALE;
> + return sk_getsockopt_peerpidfd(sk, PIDTYPE_TGID, optval, optlen, len);
>
> - pidfd = pidfd_prepare(peer_pid, flags, &pidfd_file);
> - put_pid(peer_pid);
> - if (pidfd < 0)
> - return pidfd;
> -
> - if (copy_to_sockptr(optval, &pidfd, len) ||
> - copy_to_sockptr(optlen, &len, sizeof(int))) {
> - put_unused_fd(pidfd);
> - fput(pidfd_file);
> -
> - return -EFAULT;
> - }
> + case SO_PEERPIDFD_THREAD:
> + /* Only AF_UNIX records the peer's connecting thread. */
> + if (!sk_is_unix(sk))
> + return -EOPNOTSUPP;
>
> - fd_install(pidfd, pidfd_file);
> - return 0;
> - }
> + return sk_getsockopt_peerpidfd(sk, PIDTYPE_PID, optval, optlen, len);
>
> case SO_PEERGROUPS:
> {
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index d01ee76c8026..563d9827c5cc 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1056,6 +1056,7 @@ static bool unix_bpf_bypass_getsockopt(int level, int optname)
> if (level == SOL_SOCKET) {
> switch (optname) {
> case SO_PEERPIDFD:
> + case SO_PEERPIDFD_THREAD:
> return true;
> default:
> return false;
>
> --
> 2.53.0
>