[4/4] linux: Add pidfd_getpid

Message ID 20230418213505.3834934-5-adhemerval.zanella@linaro.org
State Superseded
Headers
Series Add pidfd_spawn, pidfd_spawnp, pidfd_fork, and pidfd_getpid |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Adhemerval Zanella Netto April 18, 2023, 9:35 p.m. UTC
  This interface allows to obtain the associated pid ID from the
process file descriptor.  It is done by parsing the procps fdinfo
information.

Checked on x86_64-linux-gnu on Linux 4.15 (no CLONE_PID or waitid
support), Linux 5.15 (only clone support), and Linux 5.19 (full
support including clone3).
---
 NEWS                                          |  4 +
 sysdeps/unix/sysv/linux/Makefile              |  2 +
 sysdeps/unix/sysv/linux/Versions              |  1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |  1 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |  1 +
 .../sysv/linux/loongarch/lp64/libc.abilist    |  1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |  1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  1 +
 .../sysv/linux/microblaze/be/libc.abilist     |  1 +
 .../sysv/linux/microblaze/le/libc.abilist     |  1 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  1 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |  1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/pidfd_getpid.c        | 70 +++++++++++++
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |  1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |  1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/procutils.c           | 99 +++++++++++++++++++
 sysdeps/unix/sysv/linux/procutils.h           | 37 +++++++
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |  1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  1 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |  1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |  1 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |  1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/sys/pidfd.h           |  4 +
 sysdeps/unix/sysv/linux/tst-pidfd.c           |  7 ++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  1 +
 42 files changed, 258 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/pidfd_getpid.c
 create mode 100644 sysdeps/unix/sysv/linux/procutils.c
 create mode 100644 sysdeps/unix/sysv/linux/procutils.h
  

Comments

Luca Boccassi April 19, 2023, 10:29 a.m. UTC | #1
> +parse_fdinfo (const char *l, void *arg)
> +{
> +  enum { fieldlen = sizeof ("Pid:") - 1 };
> +  if (strncmp (l, "Pid:", fieldlen) != 0)
> +    return true;
> +
> +  l += fieldlen;
> +
> +  char *endp;
> +  unsigned long int n = strtoul (l, &endp, 10);
> +  if (l == endp || n > INT_MAX)
> +    return true;
> +
> +  *(pid_t *)arg = n;
> +  return false;
> +}
> +
> +pid_t
> +pidfd_getpid (int fd)
> +{
> +  if (__glibc_unlikely (fd < 0))
> +    {
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +
> +  char fdinfoname[FDINFO_FILENAME_LEN];
> +
> +  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
> +		     strlen (FDINFO_TO_FILENAME_PREFIX));
> +  *_fitoa_word (fd, p, 10, 0) = '\0';
> +
> +  pid_t pid;
> +  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
> +    return -1;
> +
> +  return pid;

Having implemented this parsing by hand across 3 projects, it is great
to see a glibc helper coming.

However, please handle the case of Pid being 0 and -1 explicitly, and
return a recognizable errno. fdinfo listing 0 means the pidfd cannot be
resolved because it's in a separate pid namespace, so something EREMOTE
would suffice. -1 means the process exited, so ESRCH seems like the
right error. The distiction between these cases and other errors is
important to userspace where we do process tracking, like
systemd/dbus/polkit.

> +   The CLOSURE should return false if the read should continue, or false
> +   if the function should stop.

Did you mean "true if the read should continue"?

> +  TEST_COMPARE (pidfd_getpid (INT_MAX), -1);
> +  {
> +    pid_t querypid = pidfd_getpid (pidfd);
> +    TEST_COMPARE (querypid, pid);
> +  }

I think it would be a good idea to add a negative test, eg for a
process that exited or so.

(I am not subscribed to the list, so please CC directly if needed)
  
Adhemerval Zanella Netto April 19, 2023, 1:56 p.m. UTC | #2
On 19/04/23 07:29, Luca Boccassi wrote:
>> +parse_fdinfo (const char *l, void *arg)
>> +{
>> +  enum { fieldlen = sizeof ("Pid:") - 1 };
>> +  if (strncmp (l, "Pid:", fieldlen) != 0)
>> +    return true;
>> +
>> +  l += fieldlen;
>> +
>> +  char *endp;
>> +  unsigned long int n = strtoul (l, &endp, 10);
>> +  if (l == endp || n > INT_MAX)
>> +    return true;
>> +
>> +  *(pid_t *)arg = n;
>> +  return false;
>> +}
>> +
>> +pid_t
>> +pidfd_getpid (int fd)
>> +{
>> +  if (__glibc_unlikely (fd < 0))
>> +    {
>> +      __set_errno (EINVAL);
>> +      return -1;
>> +    }
>> +
>> +  char fdinfoname[FDINFO_FILENAME_LEN];
>> +
>> +  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
>> +		     strlen (FDINFO_TO_FILENAME_PREFIX));
>> +  *_fitoa_word (fd, p, 10, 0) = '\0';
>> +
>> +  pid_t pid;
>> +  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
>> +    return -1;
>> +
>> +  return pid;
> 
> Having implemented this parsing by hand across 3 projects, it is great
> to see a glibc helper coming.
> 
> However, please handle the case of Pid being 0 and -1 explicitly, and
> return a recognizable errno. fdinfo listing 0 means the pidfd cannot be
> resolved because it's in a separate pid namespace, so something EREMOTE
> would suffice. -1 means the process exited, so ESRCH seems like the
> right error. The distiction between these cases and other errors is
> important to userspace where we do process tracking, like
> systemd/dbus/polkit.

Ok, it should a matter to handle the 'Pid:' as signed. However, I am not
sure if it is really worth to set the errno in cases, since the information
will already available from the function return itself.

> 
>> +   The CLOSURE should return false if the read should continue, or false
>> +   if the function should stop.
> 
> Did you mean "true if the read should continue"?

Indeed.

> 
>> +  TEST_COMPARE (pidfd_getpid (INT_MAX), -1);
>> +  {
>> +    pid_t querypid = pidfd_getpid (pidfd);
>> +    TEST_COMPARE (querypid, pid);
>> +  }
> 
> I think it would be a good idea to add a negative test, eg for a
> process that exited or so.

Alright, I will add a more comprehensible test.

> 
> (I am not subscribed to the list, so please CC directly if needed)
>
  
Luca Boccassi April 19, 2023, 2:01 p.m. UTC | #3
On Wed, 19 Apr 2023 at 14:56, Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
> On 19/04/23 07:29, Luca Boccassi wrote:
> >> +parse_fdinfo (const char *l, void *arg)
> >> +{
> >> +  enum { fieldlen = sizeof ("Pid:") - 1 };
> >> +  if (strncmp (l, "Pid:", fieldlen) != 0)
> >> +    return true;
> >> +
> >> +  l += fieldlen;
> >> +
> >> +  char *endp;
> >> +  unsigned long int n = strtoul (l, &endp, 10);
> >> +  if (l == endp || n > INT_MAX)
> >> +    return true;
> >> +
> >> +  *(pid_t *)arg = n;
> >> +  return false;
> >> +}
> >> +
> >> +pid_t
> >> +pidfd_getpid (int fd)
> >> +{
> >> +  if (__glibc_unlikely (fd < 0))
> >> +    {
> >> +      __set_errno (EINVAL);
> >> +      return -1;
> >> +    }
> >> +
> >> +  char fdinfoname[FDINFO_FILENAME_LEN];
> >> +
> >> +  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
> >> +                 strlen (FDINFO_TO_FILENAME_PREFIX));
> >> +  *_fitoa_word (fd, p, 10, 0) = '\0';
> >> +
> >> +  pid_t pid;
> >> +  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
> >> +    return -1;
> >> +
> >> +  return pid;
> >
> > Having implemented this parsing by hand across 3 projects, it is great
> > to see a glibc helper coming.
> >
> > However, please handle the case of Pid being 0 and -1 explicitly, and
> > return a recognizable errno. fdinfo listing 0 means the pidfd cannot be
> > resolved because it's in a separate pid namespace, so something EREMOTE
> > would suffice. -1 means the process exited, so ESRCH seems like the
> > right error. The distiction between these cases and other errors is
> > important to userspace where we do process tracking, like
> > systemd/dbus/polkit.
>
> Ok, it should a matter to handle the 'Pid:' as signed. However, I am not
> sure if it is really worth to set the errno in cases, since the information
> will already available from the function return itself.

The function returns the pid, so the same information wouldn't be
available. Eg. returning -1 because you can't read proc because of
selinux permissions is different from returning -1 because the process
was reaped and fdinfo contained -1 so it was just passed through. We
need to know this distinction in userspace to handle it properly.
Setting the errno accordingly seems the best way to do that to me.

Kind regards,
Luca Boccassi
  
Adhemerval Zanella Netto April 19, 2023, 2:11 p.m. UTC | #4
On 19/04/23 11:01, Luca Boccassi wrote:
> On Wed, 19 Apr 2023 at 14:56, Adhemerval Zanella Netto
> <adhemerval.zanella@linaro.org> wrote:
>> On 19/04/23 07:29, Luca Boccassi wrote:
>>>> +parse_fdinfo (const char *l, void *arg)
>>>> +{
>>>> +  enum { fieldlen = sizeof ("Pid:") - 1 };
>>>> +  if (strncmp (l, "Pid:", fieldlen) != 0)
>>>> +    return true;
>>>> +
>>>> +  l += fieldlen;
>>>> +
>>>> +  char *endp;
>>>> +  unsigned long int n = strtoul (l, &endp, 10);
>>>> +  if (l == endp || n > INT_MAX)
>>>> +    return true;
>>>> +
>>>> +  *(pid_t *)arg = n;
>>>> +  return false;
>>>> +}
>>>> +
>>>> +pid_t
>>>> +pidfd_getpid (int fd)
>>>> +{
>>>> +  if (__glibc_unlikely (fd < 0))
>>>> +    {
>>>> +      __set_errno (EINVAL);
>>>> +      return -1;
>>>> +    }
>>>> +
>>>> +  char fdinfoname[FDINFO_FILENAME_LEN];
>>>> +
>>>> +  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
>>>> +                 strlen (FDINFO_TO_FILENAME_PREFIX));
>>>> +  *_fitoa_word (fd, p, 10, 0) = '\0';
>>>> +
>>>> +  pid_t pid;
>>>> +  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
>>>> +    return -1;
>>>> +
>>>> +  return pid;
>>>
>>> Having implemented this parsing by hand across 3 projects, it is great
>>> to see a glibc helper coming.
>>>
>>> However, please handle the case of Pid being 0 and -1 explicitly, and
>>> return a recognizable errno. fdinfo listing 0 means the pidfd cannot be
>>> resolved because it's in a separate pid namespace, so something EREMOTE
>>> would suffice. -1 means the process exited, so ESRCH seems like the
>>> right error. The distiction between these cases and other errors is
>>> important to userspace where we do process tracking, like
>>> systemd/dbus/polkit.
>>
>> Ok, it should a matter to handle the 'Pid:' as signed. However, I am not
>> sure if it is really worth to set the errno in cases, since the information
>> will already available from the function return itself.
> 
> The function returns the pid, so the same information wouldn't be
> available. Eg. returning -1 because you can't read proc because of
> selinux permissions is different from returning -1 because the process
> was reaped and fdinfo contained -1 so it was just passed through. We
> need to know this distinction in userspace to handle it properly.
> Setting the errno accordingly seems the best way to do that to me.

I am kind worried where such errors might clash with other open/read/close
used in parsing, but at least it seems ESRCH should not be generated in such 
cases.  I am still not sure about EREMOTE, maybe we should just map the
pid equal 0 to -1/EREMOTE.
  
Luca Boccassi April 19, 2023, 2:13 p.m. UTC | #5
On Wed, 19 Apr 2023 at 15:11, Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
> On 19/04/23 11:01, Luca Boccassi wrote:
> > On Wed, 19 Apr 2023 at 14:56, Adhemerval Zanella Netto
> > <adhemerval.zanella@linaro.org> wrote:
> >> On 19/04/23 07:29, Luca Boccassi wrote:
> >>>> +parse_fdinfo (const char *l, void *arg)
> >>>> +{
> >>>> +  enum { fieldlen = sizeof ("Pid:") - 1 };
> >>>> +  if (strncmp (l, "Pid:", fieldlen) != 0)
> >>>> +    return true;
> >>>> +
> >>>> +  l += fieldlen;
> >>>> +
> >>>> +  char *endp;
> >>>> +  unsigned long int n = strtoul (l, &endp, 10);
> >>>> +  if (l == endp || n > INT_MAX)
> >>>> +    return true;
> >>>> +
> >>>> +  *(pid_t *)arg = n;
> >>>> +  return false;
> >>>> +}
> >>>> +
> >>>> +pid_t
> >>>> +pidfd_getpid (int fd)
> >>>> +{
> >>>> +  if (__glibc_unlikely (fd < 0))
> >>>> +    {
> >>>> +      __set_errno (EINVAL);
> >>>> +      return -1;
> >>>> +    }
> >>>> +
> >>>> +  char fdinfoname[FDINFO_FILENAME_LEN];
> >>>> +
> >>>> +  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
> >>>> +                 strlen (FDINFO_TO_FILENAME_PREFIX));
> >>>> +  *_fitoa_word (fd, p, 10, 0) = '\0';
> >>>> +
> >>>> +  pid_t pid;
> >>>> +  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
> >>>> +    return -1;
> >>>> +
> >>>> +  return pid;
> >>>
> >>> Having implemented this parsing by hand across 3 projects, it is great
> >>> to see a glibc helper coming.
> >>>
> >>> However, please handle the case of Pid being 0 and -1 explicitly, and
> >>> return a recognizable errno. fdinfo listing 0 means the pidfd cannot be
> >>> resolved because it's in a separate pid namespace, so something EREMOTE
> >>> would suffice. -1 means the process exited, so ESRCH seems like the
> >>> right error. The distiction between these cases and other errors is
> >>> important to userspace where we do process tracking, like
> >>> systemd/dbus/polkit.
> >>
> >> Ok, it should a matter to handle the 'Pid:' as signed. However, I am not
> >> sure if it is really worth to set the errno in cases, since the information
> >> will already available from the function return itself.
> >
> > The function returns the pid, so the same information wouldn't be
> > available. Eg. returning -1 because you can't read proc because of
> > selinux permissions is different from returning -1 because the process
> > was reaped and fdinfo contained -1 so it was just passed through. We
> > need to know this distinction in userspace to handle it properly.
> > Setting the errno accordingly seems the best way to do that to me.
>
> I am kind worried where such errors might clash with other open/read/close
> used in parsing, but at least it seems ESRCH should not be generated in such
> cases.  I am still not sure about EREMOTE, maybe we should just map the
> pid equal 0 to -1/EREMOTE.

Yes, -1/EREMOTE makes sense to me.

Kind regards,
Luca Boccassi
  

Patch

diff --git a/NEWS b/NEWS
index 2ac69a8a2c..39b5f8beb0 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,10 @@  Major new features:
   return a process ID, it returns a file descriptor that can be used along
   other pidfd functions.
 
+* On Linux, the pidfd_getpid has been added.  It allows to retrieve the
+  process ID associated with process file descriptor created with
+  pid_spawn or pidfd_fork.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * In the Linux kernel for the hppa/parisc architecture some of the
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 7f0233449f..ab309b13a9 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -441,8 +441,10 @@  sysdep_routines += \
   oldglob \
   sched_getcpu \
   pidfd_fork \
+  pidfd_getpid \
   pidfd_spawn \
   pidfd_spawnp \
+  procutils \
   # sysdep_routines
 
 tests += \
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 7e4109e9c5..047bc0c92a 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -323,6 +323,7 @@  libc {
   }
   GLIBC_2.38 {
     pidfd_fork;
+    pidfd_getpid;
     pidfd_spawn;
     pidfd_spawnp;
   }
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index dbf7c44319..febfc78f29 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2666,5 +2666,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index a9d6ffce14..87f93beeb8 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2775,6 +2775,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index c08d548556..dd33567a75 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2427,5 +2427,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index f348336ee7..2344b8ae48 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -547,6 +547,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _Exit F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 5aed593521..b34ec3e9cc 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -544,6 +544,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _Exit F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 8a7022aaa8..f59d84fdb0 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2703,5 +2703,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index e2ac6949df..f6527bb9db 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2652,6 +2652,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 5e8d49fc1f..28ccb54206 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2836,6 +2836,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 3cd3c80334..aabf217819 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2601,6 +2601,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
index 0965db2ff0..8b53d82e8c 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
@@ -2187,5 +2187,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 1ec24886a3..66bf4532ab 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -548,6 +548,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _Exit F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 239b1d70be..0ee9fef825 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2779,6 +2779,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index dd41d63394..8861ebb4ca 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2752,5 +2752,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 55c3dcd471..008dda3746 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2749,5 +2749,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 295e4d8608..2d0af493ed 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2744,6 +2744,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 19fb1aebe7..ae82d18edb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2742,6 +2742,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 2dd6ef5416..87aee7f86d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2750,6 +2750,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 6445d27220..c0d1fd370a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2652,6 +2652,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index c1cc5134c9..06092621b9 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2791,5 +2791,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index 293643346a..88dcdd8b98 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2173,5 +2173,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/pidfd_getpid.c b/sysdeps/unix/sysv/linux/pidfd_getpid.c
new file mode 100644
index 0000000000..09cd81f863
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/pidfd_getpid.c
@@ -0,0 +1,70 @@ 
+/* pidfd_getpid - Get the associated pid from the pid file descriptor.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <_itoa.h>
+#include <errno.h>
+#include <intprops.h>
+#include <procutils.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define FDINFO_TO_FILENAME_PREFIX "/proc/self/fdinfo/"
+
+#define FDINFO_FILENAME_LEN \
+  (sizeof (FDINFO_TO_FILENAME_PREFIX) + INT_STRLEN_BOUND (int))
+
+static bool
+parse_fdinfo (const char *l, void *arg)
+{
+  enum { fieldlen = sizeof ("Pid:") - 1 };
+  if (strncmp (l, "Pid:", fieldlen) != 0)
+    return true;
+
+  l += fieldlen;
+
+  char *endp;
+  unsigned long int n = strtoul (l, &endp, 10);
+  if (l == endp || n > INT_MAX)
+    return true;
+
+  *(pid_t *)arg = n;
+  return false;
+}
+
+pid_t
+pidfd_getpid (int fd)
+{
+  if (__glibc_unlikely (fd < 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  char fdinfoname[FDINFO_FILENAME_LEN];
+
+  char *p = mempcpy (fdinfoname, FDINFO_TO_FILENAME_PREFIX,
+		     strlen (FDINFO_TO_FILENAME_PREFIX));
+  *_fitoa_word (fd, p, 10, 0) = '\0';
+
+  pid_t pid;
+  if (procutils_read_file (fdinfoname, parse_fdinfo, &pid) == -1)
+    return -1;
+
+  return pid;
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 03a35e860d..ce885f9136 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2818,6 +2818,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index a91af4245b..8063a0606e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2851,6 +2851,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index c15137b9ad..21fb95a352 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2572,6 +2572,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 12c0f4cfba..14bda5b5b8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2886,5 +2886,6 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/procutils.c b/sysdeps/unix/sysv/linux/procutils.c
new file mode 100644
index 0000000000..4909afeae1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/procutils.c
@@ -0,0 +1,99 @@ 
+/* Utilities functions to read/parse Linux procfs and sysfs.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <not-cancel.h>
+#include <procutils.h>
+#include <string.h>
+
+static char *
+next_line (int fd, char *const buffer, char **cp, char **re,
+           char *const buffer_end)
+{
+  char *res = *cp;
+  char *nl = memchr (*cp, '\n', *re - *cp);
+  if (nl == NULL)
+    {
+      if (*cp != buffer)
+        {
+          if (*re == buffer_end)
+            {
+              memmove (buffer, *cp, *re - *cp);
+              *re = buffer + (*re - *cp);
+              *cp = buffer;
+
+              ssize_t n = __read_nocancel (fd, *re, buffer_end - *re);
+              if (n < 0)
+                return NULL;
+
+              *re += n;
+
+              nl = memchr (*cp, '\n', *re - *cp);
+              while (nl == NULL && *re == buffer_end)
+                {
+                  /* Truncate too long lines.  */
+                  *re = buffer + 3 * (buffer_end - buffer) / 4;
+                  n = __read_nocancel (fd, *re, buffer_end - *re);
+                  if (n < 0)
+                    return NULL;
+
+                  nl = memchr (*re, '\n', n);
+                  **re = '\0';
+                  *re += n;
+                }
+            }
+          else
+            nl = memchr (*cp, '\n', *re - *cp);
+
+          res = *cp;
+        }
+
+      if (nl == NULL)
+        nl = *re - 1;
+    }
+
+  *nl = '\0';
+  *cp = nl + 1;
+  assert (*cp <= *re);
+
+  return res == *re ? NULL : res;
+}
+
+int
+procutils_read_file (const char *filename, procutils_closure_t closure,
+		     void *arg)
+{
+  enum { buffer_size = 1024 };
+  char buffer[buffer_size];
+  char *buffer_end = buffer + buffer_size;
+  char *cp = buffer_end;
+  char *re = buffer_end;
+
+  int fd = __open64_nocancel (filename, O_RDONLY | O_CLOEXEC);
+  if (fd == -1)
+    return -1;
+
+  char *l;
+  while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
+    if (!closure (l, arg))
+      break;
+
+  __close_nocancel_nostatus (fd);
+
+  return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/procutils.h b/sysdeps/unix/sysv/linux/procutils.h
new file mode 100644
index 0000000000..afb2d43bed
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/procutils.h
@@ -0,0 +1,37 @@ 
+/* Utilities functions to read/parse Linux procfs and sysfs.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _PROCUTILS_H
+#define _PROCUTILS_H
+
+#include <stdbool.h>
+
+typedef bool (*procutils_closure_t)(const char *line, void *arg);
+
+/* Open and read the path FILENAME, line per line, and call CLOSURE with
+   argument ARG on each line.  The read is done with a static buffer,
+   with non-cancellable calls, and the line is null terminated.
+
+   The CLOSURE should return false if the read should continue, or false
+   if the function should stop.
+
+   It returns 0 in case of success, or -1 otherwise.  */
+int procutils_read_file (const char *filename, procutils_closure_t closure,
+			 void *arg) attribute_hidden;
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 9537dac42d..b294ec1021 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2429,5 +2429,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index ea72e6b648..61921a02d4 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2629,5 +2629,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index d6c895b487..fbc2d5826f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2816,6 +2816,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index b375f5a7ab..45ab26d7a7 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2609,6 +2609,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 7b2266ecb3..8de69e0057 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2659,6 +2659,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 2f9f732044..3821ce3676 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2656,6 +2656,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 144d54ebf2..7be5b0c125 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2811,6 +2811,7 @@  GLIBC_2.38 __nldbl___isoc23_vswscanf F
 GLIBC_2.38 __nldbl___isoc23_vwscanf F
 GLIBC_2.38 __nldbl___isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 _IO_fprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index bc8bd8ff54..a09b2efc90 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2624,6 +2624,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/sys/pidfd.h b/sysdeps/unix/sysv/linux/sys/pidfd.h
index ed1d3b0ab4..f111a7d8d6 100644
--- a/sysdeps/unix/sysv/linux/sys/pidfd.h
+++ b/sysdeps/unix/sysv/linux/sys/pidfd.h
@@ -59,4 +59,8 @@  extern int pidfd_send_signal (int __pidfd, int __sig, siginfo_t *__info,
    of the new process to the parent process.  */
 extern int pidfd_fork (unsigned int __flags) __THROW;
 
+/* Query the process ID (PID) from process descriptor __FD.  Return the PID
+   or -1 in case of an error.  */
+extern pid_t pidfd_getpid (int __fd) __THROW;
+
 #endif /* _PIDFD_H  */
diff --git a/sysdeps/unix/sysv/linux/tst-pidfd.c b/sysdeps/unix/sysv/linux/tst-pidfd.c
index 64d8a2ef40..39d86fb668 100644
--- a/sysdeps/unix/sysv/linux/tst-pidfd.c
+++ b/sysdeps/unix/sysv/linux/tst-pidfd.c
@@ -18,6 +18,7 @@ 
 
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <support/capture_subprocess.h>
 #include <support/check.h>
 #include <support/process_state.h>
@@ -118,6 +119,12 @@  do_test (void)
   int pidfd = pidfd_open (pid, 0);
   TEST_VERIFY (pidfd != -1);
 
+  TEST_COMPARE (pidfd_getpid (INT_MAX), -1);
+  {
+    pid_t querypid = pidfd_getpid (pidfd);
+    TEST_COMPARE (querypid, pid);
+  }
+
   /* Wait for first sigtimedwait.  */
   support_process_state_wait (pid, support_process_state_sleeping);
   TEST_COMPARE (pidfd_send_signal (pidfd, SIGUSR1, NULL, 0), 0);
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 045205de0c..0726b6e8d0 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2575,6 +2575,7 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F
 GLIBC_2.4 __confstr_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 5a67604948..9c1f6830ba 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2681,5 +2681,6 @@  GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
 GLIBC_2.38 pidfd_fork F
+GLIBC_2.38 pidfd_getpid F
 GLIBC_2.38 pidfd_spawn F
 GLIBC_2.38 pidfd_spawnp F