diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-03-13 11:21:49 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-03-13 12:16:38 +0100 |
commit | 0cb8e3d1180330345088e68517700b950569386d (patch) | |
tree | f70e91030f741ec47b842fe5249df701558dc23c | |
parent | test: don't overwrite TESTDIR if already set (diff) | |
download | systemd-0cb8e3d1180330345088e68517700b950569386d.tar.xz systemd-0cb8e3d1180330345088e68517700b950569386d.zip |
util: split out namespace related stuff into a new namespace-util.[ch] pair
Just some minor reorganiztion.
Diffstat (limited to '')
-rw-r--r-- | src/basic/meson.build | 2 | ||||
-rw-r--r-- | src/basic/namespace-util.c | 172 | ||||
-rw-r--r-- | src/basic/namespace-util.h | 9 | ||||
-rw-r--r-- | src/basic/process-util.c | 1 | ||||
-rw-r--r-- | src/basic/process-util.h | 1 | ||||
-rw-r--r-- | src/basic/stat-util.c | 46 | ||||
-rw-r--r-- | src/basic/stat-util.h | 2 | ||||
-rw-r--r-- | src/basic/terminal-util.c | 1 | ||||
-rw-r--r-- | src/basic/util.c | 115 | ||||
-rw-r--r-- | src/basic/util.h | 3 | ||||
-rw-r--r-- | src/core/machine-id-setup.c | 1 | ||||
-rw-r--r-- | src/core/namespace.c | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-container.c | 1 | ||||
-rw-r--r-- | src/machine/machine-dbus.c | 1 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 1 | ||||
-rw-r--r-- | src/shared/logs-show.c | 1 | ||||
-rw-r--r-- | src/test/test-stat-util.c | 1 |
17 files changed, 193 insertions, 166 deletions
diff --git a/src/basic/meson.build b/src/basic/meson.build index c62e4a3b59..4cfd3c861d 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -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 diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c new file mode 100644 index 0000000000..67bdaa19d5 --- /dev/null +++ b/src/basic/namespace-util.c @@ -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; +} diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h new file mode 100644 index 0000000000..8c17ce91b2 --- /dev/null +++ b/src/basic/namespace-util.h @@ -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); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 78ce43b944..615b6d4044 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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" diff --git a/src/basic/process-util.h b/src/basic/process-util.h index c85ea30ecc..9950723996 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-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" diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index ea2bbc368b..2cd722c106 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -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; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 74fb7251b3..5aca17c04a 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -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 diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 0f38120729..4702e91732 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -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" diff --git a/src/basic/util.c b/src/basic/util.c index e577c93e60..6f68bc404e 100644 --- a/src/basic/util.c +++ b/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; diff --git a/src/basic/util.h b/src/basic/util.h index dc33d66067..82851e910c 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -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); diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index aae548064e..9d3096e3ac 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -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" diff --git a/src/core/namespace.c b/src/core/namespace.c index 4ee2b78653..3657e935ee 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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" diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c index 2cfeefc2c3..40b0e8a947 100644 --- a/src/libsystemd/sd-bus/bus-container.c +++ b/src/libsystemd/sd-bus/bus-container.c @@ -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" diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 7a558df898..1ee878055e 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -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" diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 64a30a5b9a..c6cc82b12f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -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" diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 15ef0f19ff..5fb736f633 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -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" diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index 0e2155e911..e3d89d6e26 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -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" |