From: Mike Yuan Date: Wed, 22 Jan 2025 02:00:32 +0000 (+0100) Subject: pidfd-util: preferably acquire pidfd inode id through name_to_handle_at() X-Git-Tag: v258-rc1~1530 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c039ef5ff7f683aa9f7a36cb39bac94a12964b2;p=thirdparty%2Fsystemd.git pidfd-util: preferably acquire pidfd inode id through name_to_handle_at() See rationales described in kernel commit: https://github.com/torvalds/linux/commit/b3caba8f7a34a2bbaf45ffc6ff3a49b70afeb192 --- diff --git a/man/sd_notify.xml b/man/sd_notify.xml index cf19ba01da7..c017f484870 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -306,7 +306,8 @@ The pidfd inode number of the new main process (specified through MAINPID=). This information can be acquired through - fstat2 + name_to_handle_at2 + or fstat2 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/src/basic/pidfd-util.c b/src/basic/pidfd-util.c index 36fe224324a..82064e162a5 100644 --- a/src/basic/pidfd-util.c +++ b/src/basic/pidfd-util.c @@ -8,8 +8,10 @@ #include "fileio.h" #include "macro.h" #include "memory-util.h" +#include "missing_fs.h" #include "missing_magic.h" #include "missing_threads.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "pidfd-util.h" @@ -226,6 +228,7 @@ int pidfd_get_cgroupid(int fd, uint64_t *ret) { } int pidfd_get_inode_id(int fd, uint64_t *ret) { + static bool file_handle_supported = true; int r; assert(fd >= 0); @@ -236,6 +239,30 @@ int pidfd_get_inode_id(int fd, uint64_t *ret) { if (r == 0) return -EOPNOTSUPP; + if (file_handle_supported) { + union { + struct file_handle file_handle; + uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)]; + } fh = { + .file_handle.handle_bytes = sizeof(uint64_t), + .file_handle.handle_type = FILEID_KERNFS, + }; + int mnt_id; + + r = RET_NERRNO(name_to_handle_at(fd, "", &fh.file_handle, &mnt_id, AT_EMPTY_PATH)); + if (r >= 0) { + if (ret) + *ret = *(uint64_t*) fh.file_handle.f_handle; + return 0; + } + assert(r != -EOVERFLOW); + if (is_name_to_handle_at_fatal_error(r)) + return r; + + file_handle_supported = false; + } + +#if SIZEOF_INO_T == 8 struct stat st; if (fstat(fd, &st) < 0) return -errno; @@ -243,6 +270,16 @@ int pidfd_get_inode_id(int fd, uint64_t *ret) { if (ret) *ret = (uint64_t) st.st_ino; return 0; + +#elif SIZEOF_INO_T == 4 + /* On 32-bit systems (where sizeof(ino_t) == 4), the inode id returned by fstat() cannot be used to + * reliably identify the process, nor can we communicate the origin of the id with the clients. + * Hence let's just refuse to acquire pidfdid through fstat() here. All clients shall also insist on + * the 64-bit id from name_to_handle_at(). */ + return -EOPNOTSUPP; +#else +# error Unsupported ino_t size +#endif } int pidfd_get_inode_id_self_cached(uint64_t *ret) {