pidfd-util: preferably acquire pidfd inode id through name_to_handle_at()

See rationales described in kernel commit:
b3caba8f7a
This commit is contained in:
Mike Yuan
2025-01-22 03:00:32 +01:00
committed by Lennart Poettering
parent cc524bc1fe
commit 9c039ef5ff
2 changed files with 39 additions and 1 deletions

View File

@@ -306,7 +306,8 @@
<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>fstat</refentrytitle><manvolnum>2</manvolnum></citerefentry>
<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>
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>

View File

@@ -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) {