]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
linux: use PIDFD_GET_INFO ioctl for pidfd_getpid() if available
authorLuca Boccassi <luca.boccassi@gmail.com>
Wed, 28 Jan 2026 15:37:56 +0000 (15:37 +0000)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 2 Feb 2026 17:37:04 +0000 (14:37 -0300)
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>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
sysdeps/unix/sysv/linux/kernel-features.h
sysdeps/unix/sysv/linux/pidfd_getpid.c
sysdeps/unix/sysv/linux/tst-pidfd_getpid.c

index 01c865e2d5966f2e46bd951b5076103b3d9e013b..94bdbbb730aeb21ff009263895f4718f52174cfc 100644 (file)
 # 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 */
index 860829cf07da2267484299ccb02861822c0d07b4..6bf6590877224d2691e8c6fd25356a59d69ed818 100644 (file)
 #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;
+}
index 597a140330794a9d2156fe72a901e91c264faa63..0a5f4c9d9c3857d28499867bc05fe30ef4ef14f3 100644 (file)
@@ -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);
       }