pidfd-util: introduce helper for obtaining ns fd using PIDFD_GET_*_NAMESPACE directly

This commit is contained in:
Mike Yuan
2024-11-20 00:14:12 +01:00
parent 9a7b20b6a6
commit 72661e0091
2 changed files with 37 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/ioctl.h>
#include <unistd.h>
#include "errno-util.h"
@@ -33,6 +34,40 @@ static int pidfd_check_pidfs(void) {
return (have_pidfs = fd_is_fs_type(fd, PID_FS_MAGIC));
}
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) {
static bool cached_supported = true;
/* Obtain the namespace fd from pidfd directly through ioctl(PIDFD_GET_*_NAMESPACE).
*
* Returns -EOPNOTSUPP if ioctl on pidfds are not supported, -ENOPKG if the requested namespace
* is disabled in kernel. (The errno used are different from what kernel returns via ioctl(),
* see below) */
assert(fd >= 0);
/* If we know ahead of time that pidfs is unavailable, shortcut things. But otherwise we don't
* call pidfd_check_pidfs() here, which is kinda extraneous and our own cache is required
* anyways (pidfs is introduced in kernel 6.9 while ioctl support there is added in 6.11). */
if (have_pidfs == 0 || !cached_supported)
return -EOPNOTSUPP;
int nsfd = ioctl(fd, ns_type_cmd);
if (nsfd < 0) {
/* Kernel returns EOPNOTSUPP if the ns type in question is disabled. Hence we need to look
* at precise errno instead of generic ERRNO_IS_(IOCTL_)NOT_SUPPORTED. */
if (IN_SET(errno, ENOTTY, EINVAL)) {
cached_supported = false;
return -EOPNOTSUPP;
}
if (errno == EOPNOTSUPP) /* Translate to something more recognizable */
return -ENOPKG;
return -errno;
}
return nsfd;
}
int pidfd_get_pid(int fd, pid_t *ret) {
char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *fdinfo = NULL;

View File

@@ -7,6 +7,8 @@
#include "missing_pidfd.h"
#include "missing_syscall.h"
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd);
int pidfd_get_pid(int fd, pid_t *ret);
int pidfd_verify_pid(int pidfd, pid_t pid);