[PATCH v8] linux: use PIDFD_GET_INFO ioctl for pidfd_getpid() if available

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Fri Jan 30 13:58:14 GMT 2026



On 28/01/26 12:37, luca.boccassi@gmail.com wrote:
> From: Luca Boccassi <luca.boccassi@gmail.com>
> 
> Linux v6.13 introduced a new ioctl to query info from a pidfd.
> The advantage of this vs. parsing /proc/ is that it works even
> when procfs is not mounted. It's also a single syscall, and doesn't
> need manual string parsing. Use it when available.
> 
> Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>

This version look ok to me. I though about documenting the possible errno
value different when ioctl is used, but since you state that it being
changed on kernel I think it is not really worth.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
> v2: use sys/pidfd.h instead of installed kernel headers
> 
> v3: add __ASSUME_PIDFD_GET_INFO
>     use atomics for support cache var
> 
> v4: drop support cache var
> 
> v5: drop static helper given it's just the ioctl call now, simplifies the flow
> 
> v6: map ENOTTY to EBADF to avoid breaking documented behaviour
> 
> v7: switch from ioctl() to __ioctl()
> 
> v8: adapt tst-pidfd_getpid to PIDFD_GET_INFO which might return ESRCH
>     when querying a pid in another namespace. A fix has been sent, but
>     existing kernels need to be supported too.
> 
>  sysdeps/unix/sysv/linux/kernel-features.h  |  8 ++++
>  sysdeps/unix/sysv/linux/pidfd_getpid.c     | 44 ++++++++++++++++++----
>  sysdeps/unix/sysv/linux/tst-pidfd_getpid.c |  4 +-
>  3 files changed, 47 insertions(+), 9 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
> index 01c865e2d5..94bdbbb730 100644
> --- a/sysdeps/unix/sysv/linux/kernel-features.h
> +++ b/sysdeps/unix/sysv/linux/kernel-features.h
> @@ -269,4 +269,12 @@
>  # define __ASSUME_MSEAL 0
>  #endif
>  
> +/* The PIDFD_GET_INFO ioctl was introduced across all architectures in Linux
> +   6.13.  */
> +#if __LINUX_KERNEL_VERSION >= 0x060D00
> +# define __ASSUME_PIDFD_GET_INFO 1
> +#else
> +# define __ASSUME_PIDFD_GET_INFO 0
> +#endif
> +
>  #endif /* kernel-features.h */
> diff --git a/sysdeps/unix/sysv/linux/pidfd_getpid.c b/sysdeps/unix/sysv/linux/pidfd_getpid.c
> index 860829cf07..6bf6590877 100644
> --- a/sysdeps/unix/sysv/linux/pidfd_getpid.c
> +++ b/sysdeps/unix/sysv/linux/pidfd_getpid.c
> @@ -23,8 +23,11 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <sysdep.h>
> +#include <sys/ioctl.h>
> +#include <sys/pidfd.h>
>  #include <unistd.h>
>  
> +#if !__ASSUME_PIDFD_GET_INFO
>  #define FDINFO_TO_FILENAME_PREFIX "/proc/self/fdinfo/"
>  
>  #define FDINFO_FILENAME_LEN \
> @@ -91,15 +94,9 @@ parse_fdinfo (const char *l, void *arg)
>    return 1;
>  }
>  
> -pid_t
> -pidfd_getpid (int fd)
> +static pid_t
> +getpid_fdinfo (int fd)
>  {
> -  if (__glibc_unlikely (fd < 0))
> -    {
> -      __set_errno (EBADF);
> -      return -1;
> -    }
> -
>    char fdinfoname[FDINFO_FILENAME_LEN];
>  
>    char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
> @@ -126,3 +123,34 @@ pidfd_getpid (int fd)
>  
>    return fdinfo.pid;
>  }
> +#endif
> +
> +pid_t
> +pidfd_getpid (int fd)
> +{
> +  struct pidfd_info info = { .mask = PIDFD_INFO_PID };
> +
> +  if (__glibc_unlikely (fd < 0))
> +    {
> +      __set_errno (EBADF);
> +      return -1;
> +    }
> +
> +  /* New in kernel 6.13 */
> +  if (__ioctl (fd, PIDFD_GET_INFO, &info) < 0)
> +    {
> +#if __ASSUME_PIDFD_GET_INFO
> +      /* The procfs implementation returns EBADF when called with a non-pidfd
> +         fd, change the errno to keep it consistent across implementations.  */
> +      if (errno == ENOTTY)
> +        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
> +#else
> +      if (errno == ENOTTY || errno == EINVAL)
> +        return getpid_fdinfo (fd);
> +#endif
> +
> +      return INLINE_SYSCALL_ERROR_RETURN_VALUE (errno);
> +    }
> +
> +  return info.pid;
> +}
> diff --git a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> index 597a140330..0a5f4c9d9c 100644
> --- a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> +++ b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> @@ -100,7 +100,9 @@ do_test (void)
>  	  }
>  
>  	TEST_COMPARE (pidfd_getpid (child1_pidfd), -1);
> -	TEST_COMPARE (errno, EREMOTE);
> +	/* The kernel PIDFD_GET_INFO used to return ESRCH in this case.  */
> +	if (errno != EREMOTE)
> +		TEST_COMPARE (errno, ESRCH);
>  
>  	_exit (EXIT_SUCCESS);
>        }



More information about the Libc-alpha mailing list