From: Mike Yuan Date: Sun, 1 Jun 2025 07:12:13 +0000 (+0200) Subject: sd-daemon: add sd_pidfd_get_inode_id() X-Git-Tag: v258-rc1~390^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46b0844743f653b880df6b0dc94447f9327787dc;p=thirdparty%2Fsystemd.git sd-daemon: add sd_pidfd_get_inode_id() 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. --- diff --git a/NEWS b/NEWS index 9e5f4e5e274..6f4e43da4b3 100644 --- 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. + — , CHANGES WITH 257: diff --git a/man/rules/meson.build b/man/rules/meson.build index 7f64f285963..b5dfdb925c4 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -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'], diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml index ed7905afe58..45f06caa02c 100644 --- a/man/sd-daemon.xml +++ b/man/sd-daemon.xml @@ -55,10 +55,10 @@ sd_notify3, sd_booted3, sd_is_fifo3, - sd_watchdog_enabled3 - for more information about the functions implemented. In addition - to these functions, a couple of logging prefixes are defined as - macros: + sd_watchdog_enabled3, + and sd_pidfd_get_inode_id3 + for more information about the functions implemented. In addition to these functions, a couple of + logging prefixes are defined as macros: #define SD_EMERG "<0>" /* system is unusable */ #define SD_ALERT "<1>" /* action must be taken immediately */ @@ -104,6 +104,7 @@ sd_booted3 sd_is_fifo3 sd_watchdog_enabled3 + sd_pidfd_get_inode_id3 daemon7 systemd.service5 systemd.socket5 diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 746789e955e..f9bb56b2d47 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -306,8 +306,7 @@ The pidfd inode number of the new main process (specified through MAINPID=). This information can be acquired through - name_to_handle_at2 - or fstat2 + sd_pidfd_get_inode_id3 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 MAINPIDFD=1 below). diff --git a/man/sd_pidfd_get_inode_id.xml b/man/sd_pidfd_get_inode_id.xml new file mode 100644 index 00000000000..d8dbad13750 --- /dev/null +++ b/man/sd_pidfd_get_inode_id.xml @@ -0,0 +1,107 @@ + + + + + + + + sd_pidfd_get_inode_id + systemd + + + + sd_pidfd_get_inode_id + 3 + + + + sd_pidfd_get_inode_id + Acquire the 64-bit inode ID of a PID file descriptor (PIDFD) + + + + + #include <systemd/sd-daemon.h> + + + int sd_pidfd_get_inode_id + int pidfd + uint64_t *ret + + + + + + Description + + sd_pidfd_get_inode_id() 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. + + As a typical example, the service manager sets $MAINPIDFDID and $MANAGERPIDFDID + 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. + + On 64-bit architectures, the inode ID can be directly obtained via a call to + fstat2 + on a given pidfd. However, on 32-bit architectures struct stat's .st_ino + field is also 32-bit, which similar to PIDs is subject to reuse. Therefore, a second mechanism leveraging + name_to_handle_at2 + has been added to kernel in v6.14. This helper is added to simplify downstream handling of pidfd/pidfs internals. + + + + + Return Value + + On success, the function returns 0 or a positive integer. On failure, a negative errno-style + error code is returned. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EOPNOTSUPP + + The stable PIDFD inode ID is not supported by the running kernel, or the system + is 32-bit and name_to_handle_at() is unavailable. + + + + -EBADF + + The specified file descriptor is invalid, or is not a PIDFD. + + + + + + + + Notes + + + + + + History + sd_pidfd_get_inode_id() was added in version 258. + + + + See Also + + + systemd1 + sd-daemon3 + sd_notify3 + systemd.exec5 + + + + diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index d16c7265f2d..2cdb9152a78 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -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; diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 14733d0f175..d7ed4e88e8c 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -18,8 +18,10 @@ #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; diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h index 932e8ea53e0..cd9b401e926 100644 --- a/src/systemd/sd-daemon.h +++ b/src/systemd/sd-daemon.h @@ -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