util: split out namespace related stuff into a new namespace-util.[ch] pair
Just some minor reorganiztion.
This commit is contained in:
parent
3f50fff536
commit
0cb8e3d118
|
@ -127,6 +127,8 @@ basic_sources = files('''
|
|||
mkdir.h
|
||||
mountpoint-util.c
|
||||
mountpoint-util.h
|
||||
namespace-util.c
|
||||
namespace-util.h
|
||||
nss-util.h
|
||||
ordered-set.c
|
||||
ordered-set.h
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "missing.h"
|
||||
#include "namespace-util.h"
|
||||
#include "process-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
|
||||
int rfd = -1;
|
||||
|
||||
assert(pid >= 0);
|
||||
|
||||
if (mntns_fd) {
|
||||
const char *mntns;
|
||||
|
||||
mntns = procfs_file_alloca(pid, "ns/mnt");
|
||||
mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (mntnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd) {
|
||||
const char *pidns;
|
||||
|
||||
pidns = procfs_file_alloca(pid, "ns/pid");
|
||||
pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (pidnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (netns_fd) {
|
||||
const char *netns;
|
||||
|
||||
netns = procfs_file_alloca(pid, "ns/net");
|
||||
netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (netnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (userns_fd) {
|
||||
const char *userns;
|
||||
|
||||
userns = procfs_file_alloca(pid, "ns/user");
|
||||
usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (usernsfd < 0 && errno != ENOENT)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (root_fd) {
|
||||
const char *root;
|
||||
|
||||
root = procfs_file_alloca(pid, "root");
|
||||
rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (rfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd)
|
||||
*pidns_fd = pidnsfd;
|
||||
|
||||
if (mntns_fd)
|
||||
*mntns_fd = mntnsfd;
|
||||
|
||||
if (netns_fd)
|
||||
*netns_fd = netnsfd;
|
||||
|
||||
if (userns_fd)
|
||||
*userns_fd = usernsfd;
|
||||
|
||||
if (root_fd)
|
||||
*root_fd = rfd;
|
||||
|
||||
pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
if (userns_fd >= 0) {
|
||||
/* Can't setns to your own userns, since then you could
|
||||
* escalate from non-root to root in your own namespace, so
|
||||
* check if namespaces equal before attempting to enter. */
|
||||
_cleanup_free_ char *userns_fd_path = NULL;
|
||||
int r;
|
||||
if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = files_same(userns_fd_path, "/proc/self/ns/user", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r)
|
||||
userns_fd = -1;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0)
|
||||
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
||||
return -errno;
|
||||
|
||||
if (mntns_fd >= 0)
|
||||
if (setns(mntns_fd, CLONE_NEWNS) < 0)
|
||||
return -errno;
|
||||
|
||||
if (netns_fd >= 0)
|
||||
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (userns_fd >= 0)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (root_fd >= 0) {
|
||||
if (fchdir(root_fd) < 0)
|
||||
return -errno;
|
||||
|
||||
if (chroot(".") < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return reset_uid_gid();
|
||||
}
|
||||
|
||||
int fd_is_network_ns(int fd) {
|
||||
struct statfs s;
|
||||
int r;
|
||||
|
||||
/* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice
|
||||
* way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle
|
||||
* this somewhat nicely.
|
||||
*
|
||||
* This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not
|
||||
* refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */
|
||||
|
||||
if (fstatfs(fd, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!is_fs_type(&s, NSFS_MAGIC)) {
|
||||
/* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs
|
||||
* instead. Handle that in a somewhat smart way. */
|
||||
|
||||
if (is_fs_type(&s, PROC_SUPER_MAGIC)) {
|
||||
struct statfs t;
|
||||
|
||||
/* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the
|
||||
* passed fd might refer to a network namespace, but we can't know for sure. In that case,
|
||||
* return a recognizable error. */
|
||||
|
||||
if (statfs("/proc/self/ns/net", &t) < 0)
|
||||
return -errno;
|
||||
|
||||
if (s.f_type == t.f_type)
|
||||
return -EUCLEAN; /* It's possible, we simply don't know */
|
||||
}
|
||||
|
||||
return 0; /* No! */
|
||||
}
|
||||
|
||||
r = ioctl(fd, NS_GET_NSTYPE);
|
||||
if (r < 0) {
|
||||
if (errno == ENOTTY) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */
|
||||
return -EUCLEAN;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return r == CLONE_NEWNET;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
int fd_is_network_ns(int fd);
|
|
@ -33,6 +33,7 @@
|
|||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "namespace-util.h"
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
#include "rlimit-util.h"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "format-util.h"
|
||||
#include "ioprio.h"
|
||||
#include "macro.h"
|
||||
|
|
|
@ -223,52 +223,6 @@ int fd_is_network_fs(int fd) {
|
|||
return is_network_fs(&s);
|
||||
}
|
||||
|
||||
int fd_is_network_ns(int fd) {
|
||||
struct statfs s;
|
||||
int r;
|
||||
|
||||
/* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice
|
||||
* way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle
|
||||
* this somewhat nicely.
|
||||
*
|
||||
* This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not
|
||||
* refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */
|
||||
|
||||
if (fstatfs(fd, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!is_fs_type(&s, NSFS_MAGIC)) {
|
||||
/* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs
|
||||
* instead. Handle that in a somewhat smart way. */
|
||||
|
||||
if (is_fs_type(&s, PROC_SUPER_MAGIC)) {
|
||||
struct statfs t;
|
||||
|
||||
/* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the
|
||||
* passed fd might refer to a network namespace, but we can't know for sure. In that case,
|
||||
* return a recognizable error. */
|
||||
|
||||
if (statfs("/proc/self/ns/net", &t) < 0)
|
||||
return -errno;
|
||||
|
||||
if (s.f_type == t.f_type)
|
||||
return -EUCLEAN; /* It's possible, we simply don't know */
|
||||
}
|
||||
|
||||
return 0; /* No! */
|
||||
}
|
||||
|
||||
r = ioctl(fd, NS_GET_NSTYPE);
|
||||
if (r < 0) {
|
||||
if (errno == ENOTTY) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */
|
||||
return -EUCLEAN;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return r == CLONE_NEWNET;
|
||||
}
|
||||
|
||||
int path_is_temporary_fs(const char *path) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
|
|
|
@ -50,8 +50,6 @@ bool is_network_fs(const struct statfs *s) _pure_;
|
|||
int fd_is_temporary_fs(int fd);
|
||||
int fd_is_network_fs(int fd);
|
||||
|
||||
int fd_is_network_ns(int fd);
|
||||
|
||||
int path_is_temporary_fs(const char *path);
|
||||
|
||||
/* Because statfs.t_type can be int on some architectures, we have to cast
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "proc-cmdline.h"
|
||||
|
|
115
src/basic/util.c
115
src/basic/util.c
|
@ -294,121 +294,6 @@ int container_get_leader(const char *machine, pid_t *pid) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
|
||||
int rfd = -1;
|
||||
|
||||
assert(pid >= 0);
|
||||
|
||||
if (mntns_fd) {
|
||||
const char *mntns;
|
||||
|
||||
mntns = procfs_file_alloca(pid, "ns/mnt");
|
||||
mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (mntnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd) {
|
||||
const char *pidns;
|
||||
|
||||
pidns = procfs_file_alloca(pid, "ns/pid");
|
||||
pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (pidnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (netns_fd) {
|
||||
const char *netns;
|
||||
|
||||
netns = procfs_file_alloca(pid, "ns/net");
|
||||
netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (netnsfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (userns_fd) {
|
||||
const char *userns;
|
||||
|
||||
userns = procfs_file_alloca(pid, "ns/user");
|
||||
usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (usernsfd < 0 && errno != ENOENT)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (root_fd) {
|
||||
const char *root;
|
||||
|
||||
root = procfs_file_alloca(pid, "root");
|
||||
rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (rfd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd)
|
||||
*pidns_fd = pidnsfd;
|
||||
|
||||
if (mntns_fd)
|
||||
*mntns_fd = mntnsfd;
|
||||
|
||||
if (netns_fd)
|
||||
*netns_fd = netnsfd;
|
||||
|
||||
if (userns_fd)
|
||||
*userns_fd = usernsfd;
|
||||
|
||||
if (root_fd)
|
||||
*root_fd = rfd;
|
||||
|
||||
pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
if (userns_fd >= 0) {
|
||||
/* Can't setns to your own userns, since then you could
|
||||
* escalate from non-root to root in your own namespace, so
|
||||
* check if namespaces equal before attempting to enter. */
|
||||
_cleanup_free_ char *userns_fd_path = NULL;
|
||||
int r;
|
||||
if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = files_same(userns_fd_path, "/proc/self/ns/user", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r)
|
||||
userns_fd = -1;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0)
|
||||
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
||||
return -errno;
|
||||
|
||||
if (mntns_fd >= 0)
|
||||
if (setns(mntns_fd, CLONE_NEWNS) < 0)
|
||||
return -errno;
|
||||
|
||||
if (netns_fd >= 0)
|
||||
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (userns_fd >= 0)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (root_fd >= 0) {
|
||||
if (fchdir(root_fd) < 0)
|
||||
return -errno;
|
||||
|
||||
if (chroot(".") < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return reset_uid_gid();
|
||||
}
|
||||
|
||||
uint64_t physical_memory(void) {
|
||||
_cleanup_free_ char *root = NULL, *value = NULL;
|
||||
uint64_t mem, lim;
|
||||
|
|
|
@ -237,9 +237,6 @@ static inline unsigned log2u_round_up(unsigned x) {
|
|||
|
||||
int container_get_leader(const char *machine, pid_t *pid);
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "macro.h"
|
||||
#include "mkdir.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "stat-util.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "namespace.h"
|
||||
#include "path-util.h"
|
||||
#include "selinux-util.h"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "bus-internal.h"
|
||||
#include "bus-socket.h"
|
||||
#include "fd-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "process-util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "machine.h"
|
||||
#include "missing_capability.h"
|
||||
#include "mkdir.h"
|
||||
#include "namespace-util.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "nspawn-cgroup.h"
|
||||
#include "nspawn-def.h"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "log.h"
|
||||
#include "logs-show.h"
|
||||
#include "macro.h"
|
||||
#include "namespace-util.h"
|
||||
#include "output-mode.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
|
Loading…
Reference in New Issue