]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-daemon: add sd_pidfd_get_inode_id()
authorMike Yuan <me@yhndnzj.com>
Sun, 1 Jun 2025 07:12:13 +0000 (09:12 +0200)
committerMike Yuan <me@yhndnzj.com>
Wed, 4 Jun 2025 23:35:08 +0000 (01:35 +0200)
We nowadays expose pidfdid at various places, e.g. envvars
and dbus properties. Also the sd_notify() MAINPID= message
has been complemented with MAINPIDFDID=. But acquiring
pidfdid is actually non-trivial especially considering
the 32-bit case, hence let's introduce a public helper
in sd-daemon specifically for that purpose.

NEWS
man/rules/meson.build
man/sd-daemon.xml
man/sd_notify.xml
man/sd_pidfd_get_inode_id.xml [new file with mode: 0644]
src/libsystemd/libsystemd.sym
src/libsystemd/sd-daemon/sd-daemon.c
src/systemd/sd-daemon.h

diff --git a/NEWS b/NEWS
index 9e5f4e5e2746a807e1a30007b1f83d23ed689b59..6f4e43da4b39075350abb8bad316eb27fd5eed1c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1208,6 +1208,11 @@ CHANGES WITH 258 in spe:
         * sd-bus: a new API call sd_bus_message_dump_json() returns a JSON
           representation of a D-Bus message.
 
+        * sd-daemon: a new call sd_pidfd_get_inode_id() has been added
+          for acquiring the unique inode ID of a pidfd, coupling the
+          $MAINPIDFDID/$MANAGERPIDFDID and session/machine leader pidfd IDs
+          exposed as described above.
+
         — <place>, <date>
 
 CHANGES WITH 257:
index 7f64f28596317bd102dfd77f6e1b848f9d6ed429..b5dfdb925c45c261fcf26eb5bcc6d75859a1dfa0 100644 (file)
@@ -882,6 +882,7 @@ manpages = [
    'sd_pidfd_get_user_slice',
    'sd_pidfd_get_user_unit'],
   'HAVE_PAM'],
+ ['sd_pidfd_get_inode_id', '3', [], ''],
  ['sd_seat_get_active',
   '3',
   ['sd_seat_can_graphical', 'sd_seat_can_tty', 'sd_seat_get_sessions'],
index ed7905afe5842439a5fcfd86f23bc773ef54690c..45f06caa02c70f5354707ed613637de95c3c7ab7 100644 (file)
     <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_is_fifo</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-    <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    for more information about the functions implemented. In addition
-    to these functions, a couple of logging prefixes are defined as
-    macros:</para>
+    <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    and <citerefentry><refentrytitle>sd_pidfd_get_inode_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for more information about the functions implemented. In addition to these functions, a couple of
+    logging prefixes are defined as macros:</para>
 
     <programlisting>#define SD_EMERG   "&lt;0&gt;"  /* system is unusable */
 #define SD_ALERT   "&lt;1&gt;"  /* action must be taken immediately */
       <member><citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>sd_is_fifo</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>sd_pidfd_get_inode_id</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
index 746789e955e6d5169d5d1e14868d2811022f9920..f9bb56b2d4730eb8e72f4108a69df12e0a4be774 100644 (file)
 
         <listitem><para>The pidfd inode number of the new main process (specified through <varname>MAINPID=</varname>).
         This information can be acquired through
-        <citerefentry project='man-pages'><refentrytitle>name_to_handle_at</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        or <citerefentry project='man-pages'><refentrytitle>fstat</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        <citerefentry><refentrytitle>sd_pidfd_get_inode_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>
         on the pidfd and is used to identify the process in a race-free fashion. Alternatively,
         a pidfd can be sent directly to the service manager (see <varname>MAINPIDFD=1</varname> below).</para>
 
diff --git a/man/sd_pidfd_get_inode_id.xml b/man/sd_pidfd_get_inode_id.xml
new file mode 100644 (file)
index 0000000..d8dbad1
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
+
+<refentry id="sd_pidfd_get_inode_id"
+  xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_pidfd_get_inode_id</title>
+    <productname>systemd</productname>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_pidfd_get_inode_id</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_pidfd_get_inode_id</refname>
+    <refpurpose>Acquire the 64-bit inode ID of a PID file descriptor (PIDFD)</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-daemon.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_pidfd_get_inode_id</function></funcdef>
+        <paramdef>int <parameter>pidfd</parameter></paramdef>
+        <paramdef>uint64_t *<parameter>ret</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_pidfd_get_inode_id()</function> may be invoked to acquire the 64-bit inode ID of
+    a PID file descriptor (PIDFD), which can be used to reliably identify a process for the current boot.</para>
+
+    <para>As a typical example, the service manager sets <varname>$MAINPIDFDID</varname> and <varname>$MANAGERPIDFDID</varname>
+    environment variables to the inode IDs of the service main process and the service manager itself, respectively,
+    if such functionality is supported by the kernel.</para>
+
+    <para>On 64-bit architectures, the inode ID can be directly obtained via a call to
+    <citerefentry project='man-pages'><refentrytitle>fstat</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    on a given pidfd. However, on 32-bit architectures <structname>struct stat</structname>'s .st_ino
+    field is also 32-bit, which similar to PIDs is subject to reuse. Therefore, a second mechanism leveraging
+    <citerefentry project='man-pages'><refentrytitle>name_to_handle_at</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    has been added to kernel in v6.14. This helper is added to simplify downstream handling of pidfd/pidfs internals.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, the function returns 0 or a positive integer. On failure, a negative errno-style
+    error code is returned.</para>
+
+    <refsect2>
+      <title>Errors</title>
+
+      <para>Returned errors may indicate the following problems:</para>
+
+      <variablelist>
+
+        <varlistentry>
+          <term><constant>-EOPNOTSUPP</constant></term>
+
+          <listitem><para>The stable PIDFD inode ID is not supported by the running kernel, or the system
+          is 32-bit and <function>name_to_handle_at()</function> is unavailable.</para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>-EBADF</constant></term>
+
+          <listitem><para>The specified file descriptor is invalid, or is not a PIDFD.</para></listitem>
+        </varlistentry>
+
+      </variablelist>
+    </refsect2>
+  </refsect1>
+
+  <refsect1>
+    <title>Notes</title>
+
+    <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
+  </refsect1>
+
+  <refsect1>
+    <title>History</title>
+    <para><function>sd_pidfd_get_inode_id()</function> was added in version 258.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para><simplelist type="inline">
+      <member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
+    </simplelist></para>
+  </refsect1>
+
+</refentry>
index d16c7265f2db238373d388f92673a6865c347c40..2cdb9152a78920205c626e6257dee7c1e7887d19 100644 (file)
@@ -1067,6 +1067,7 @@ global:
         sd_device_get_sysattr_value_with_size;
         sd_json_variant_type_from_string;
         sd_json_variant_type_to_string;
+        sd_pidfd_get_inode_id;
         sd_varlink_get_current_method;
         sd_varlink_get_description;
         sd_varlink_get_input_fd;
index 14733d0f175bfe0bd9638cc64fee4e63ef261d03..d7ed4e88e8ce004721065fc4c6c3e9f0435adbd1 100644 (file)
 #include "io-util.h"
 #include "iovec-util.h"
 #include "log.h"
+#include "missing_magic.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "pidfd-util.h"
 #include "process-util.h"
 #include "socket-util.h"
 #include "stat-util.h"
@@ -752,6 +754,27 @@ finish:
         return r;
 }
 
+_public_ int sd_pidfd_get_inode_id(int pidfd, uint64_t *ret) {
+        int r;
+
+        assert_return(pidfd >= 0, -EBADF);
+
+        /* Are pidfds backed by pidfs where the unique inode id is relevant? Note that the pidfd
+         * passed to us is extrinsic and hence cannot be trusted to initialize our "have_pidfs" cache,
+         * instead pidfd_check_pidfs() will allocate one internally. */
+        r = pidfd_check_pidfs(/* pid_fd = */ -EBADF);
+        if (r <= 0)
+                return -EOPNOTSUPP;
+
+        r = fd_is_fs_type(pidfd, PID_FS_MAGIC);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EBADF; /* pidfs is definitely around, so it's the fd that's of invalid type */
+
+        return pidfd_get_inode_id_impl(pidfd, ret);
+}
+
 _public_ int sd_booted(void) {
         int r;
 
index 932e8ea53e0da0c02d914f6731aa56a500ed7701..cd9b401e92643818f509a21c675ef21445747bf0 100644 (file)
@@ -311,6 +311,8 @@ int sd_notify_barrier(int unset_environment, uint64_t timeout);
 */
 int sd_pid_notify_barrier(pid_t pid, int unset_environment, uint64_t timeout);
 
+int sd_pidfd_get_inode_id(int pidfd, uint64_t *ret);
+
 /*
   Returns > 0 if the system was booted with systemd. Returns < 0 on
   error. Returns 0 if the system was not booted with systemd. Note