From 50985ada2c1c9327ad59992cc0fa4ea7f9396d2c Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Tue, 3 Jun 2025 22:10:24 +0200 Subject: [PATCH 1/2] utils: Differentiate between pidfd and /proc/$pid dirfds It's really confusing when those different things are all called pidfds. --- src/xdp-app-info.c | 2 +- src/xdp-utils.c | 23 ++++++++++++----------- src/xdp-utils.h | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/xdp-app-info.c b/src/xdp-app-info.c index 1eb7b2bf1..d924f2167 100644 --- a/src/xdp-app-info.c +++ b/src/xdp-app-info.c @@ -393,7 +393,7 @@ xdp_app_info_get_pidns (XdpAppInfo *app_info, return FALSE; } - if (!xdp_pidfd_get_namespace (priv->pidfd, &ns, error)) + if (!xdp_pid_dirfd_get_pidns (priv->pidfd, &ns, error)) return FALSE; priv->pidns_id = ns; diff --git a/src/xdp-utils.c b/src/xdp-utils.c index 902bb3199..f22cad95a 100644 --- a/src/xdp-utils.c +++ b/src/xdp-utils.c @@ -908,17 +908,17 @@ xdp_pidfds_to_pids (const int *pidfds, } gboolean -xdp_pidfd_get_namespace (int pidfd, +xdp_pid_dirfd_get_pidns (int pid_dirfd, ino_t *ns, GError **error) { struct stat st; int r; - g_return_val_if_fail (pidfd >= 0, FALSE); + g_return_val_if_fail (pid_dirfd >= 0, FALSE); g_return_val_if_fail (ns != NULL, FALSE); - r = fstatat (pidfd, "ns/pid", &st, 0); + r = fstatat (pid_dirfd, "ns/pid", &st, 0); if (r == -1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), @@ -966,7 +966,7 @@ parse_status_field_uid (const char *val, } static int -parse_status_file (int pid_fd, +parse_status_file (int pid_dirfd, pid_t *pid_out, uid_t *uid_out) { @@ -981,9 +981,9 @@ parse_status_file (int pid_fd, int fd; int r = 0; - g_return_val_if_fail (pid_fd > -1, FALSE); + g_return_val_if_fail (pid_dirfd > -1, FALSE); - fd = openat (pid_fd, "status", O_RDONLY | O_CLOEXEC | O_NOCTTY); + fd = openat (pid_dirfd, "status", O_RDONLY | O_CLOEXEC | O_NOCTTY); if (fd == -1) return -errno; @@ -1074,7 +1074,7 @@ xdp_map_pids_full (DIR *proc, while ((de = readdir (proc)) != NULL) { - g_autofd int pid_fd = -1; + g_autofd int pid_dirfd = -1; pid_t outside = 0; pid_t inside = 0; uid_t uid = 0; @@ -1085,11 +1085,12 @@ xdp_map_pids_full (DIR *proc, if (de->d_type != DT_DIR) continue; - pid_fd = openat (dirfd (proc), de->d_name, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); - if (pid_fd == -1) + pid_dirfd = openat (dirfd (proc), de->d_name, + O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); + if (pid_dirfd == -1) continue; - if (!xdp_pidfd_get_namespace (pid_fd, &ns, NULL)) + if (!xdp_pid_dirfd_get_pidns (pid_dirfd, &ns, NULL)) continue; if (pidns != ns) @@ -1099,7 +1100,7 @@ xdp_map_pids_full (DIR *proc, if (r < 0) continue; - r = parse_status_file (pid_fd, &inside, &uid); + r = parse_status_file (pid_dirfd, &inside, &uid); if (r < 0) continue; diff --git a/src/xdp-utils.h b/src/xdp-utils.h index fa1c6c7c3..74105a6a9 100644 --- a/src/xdp-utils.h +++ b/src/xdp-utils.h @@ -130,7 +130,7 @@ gboolean xdp_pidfds_to_pids (const int *pidfds, gint count, GError **error); -gboolean xdp_pidfd_get_namespace (int pidfd, +gboolean xdp_pid_dirfd_get_pidns (int pid_dirfd, ino_t *ns, GError **error); From d7f8e732c4dbf3d3444f450979c00f5aaf59f02c Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Tue, 3 Jun 2025 22:19:24 +0200 Subject: [PATCH 2/2] utils: Add new function to get the pidns from an actual pidfd Calling xdp_pid_dirfd_get_pidns with an actual pidfd, as is done in XdpAppInfo.get_pidns will fail because it expects a dirfd of /proc/$PID. The new function knows how to get the pidns from a pidfd. --- src/xdp-app-info.c | 2 +- src/xdp-utils.c | 39 +++++++++++++++++++++++++++++++++++++++ src/xdp-utils.h | 6 +++--- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/xdp-app-info.c b/src/xdp-app-info.c index d924f2167..7bbb8f38c 100644 --- a/src/xdp-app-info.c +++ b/src/xdp-app-info.c @@ -393,7 +393,7 @@ xdp_app_info_get_pidns (XdpAppInfo *app_info, return FALSE; } - if (!xdp_pid_dirfd_get_pidns (priv->pidfd, &ns, error)) + if (!xdp_pidfd_get_pidns (priv->pidfd, &ns, error)) return FALSE; priv->pidns_id = ns; diff --git a/src/xdp-utils.c b/src/xdp-utils.c index f22cad95a..a9f094666 100644 --- a/src/xdp-utils.c +++ b/src/xdp-utils.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,9 @@ #define DBUS_INTERFACE_DBUS DBUS_NAME_DBUS #define DBUS_PATH_DBUS "/org/freedesktop/DBus" +#define PIDFS_IOCTL_MAGIC 0xFF +#define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5) + /* Based on g_mkstemp from glib */ gint xdp_mkstempat (int dir_fd, @@ -908,6 +912,41 @@ xdp_pidfds_to_pids (const int *pidfds, } gboolean +xdp_pidfd_get_pidns (int pidfd, + ino_t *ns, + GError **error) +{ + g_autofd int pidns_fd = -1; + struct stat st; + + g_return_val_if_fail (pidfd >= 0, FALSE); + g_return_val_if_fail (ns != NULL, FALSE); + + pidns_fd = ioctl (pidfd, PIDFD_GET_PID_NAMESPACE, 0); + if (pidns_fd < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "PIDFD_GET_PID_NAMESPACE ioctl failed: %s", + g_strerror (errno)); + return FALSE; + } + + if (fstat (pidns_fd, &st) != 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "fstat on pidns fd failed: %s", + g_strerror (errno)); + return FALSE; + } + + /* The inode number (together with the device ID) encode + * the identity of the pid namespace, see namespaces(7) + */ + *ns = st.st_ino; + return TRUE; +} + +static gboolean xdp_pid_dirfd_get_pidns (int pid_dirfd, ino_t *ns, GError **error) diff --git a/src/xdp-utils.h b/src/xdp-utils.h index 74105a6a9..1c339c28d 100644 --- a/src/xdp-utils.h +++ b/src/xdp-utils.h @@ -130,9 +130,9 @@ gboolean xdp_pidfds_to_pids (const int *pidfds, gint count, GError **error); -gboolean xdp_pid_dirfd_get_pidns (int pid_dirfd, - ino_t *ns, - GError **error); +gboolean xdp_pidfd_get_pidns (int pidfd, + ino_t *ns, + GError **error); gboolean xdp_map_pids_full (DIR *proc, ino_t pidns,