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

luca.boccassi@gmail.com luca.boccassi@gmail.com
Mon Jan 26 19:34:15 GMT 2026


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>
---
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

 sysdeps/unix/sysv/linux/kernel-features.h |  8 +++++
 sysdeps/unix/sysv/linux/pidfd_getpid.c    | 44 ++++++++++++++++++-----
 2 files changed, 44 insertions(+), 8 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..e0f1b7bf2b 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;
+}
-- 
2.47.3



More information about the Libc-alpha mailing list