/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include <sys/ioctl.h>
#include <unistd.h>
#include "errno-util.h"
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;
#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);