From e2ec9c4d3abf49e95565574214f8979d819e3f48 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 2 Feb 2020 18:56:12 +0100 Subject: [PATCH] namespace-util: introduce helper for combining unshare() + MS_SLAVE remount We have multiple places we do these two non-trivial operations together, let's introduce a unified helper for doing both at once. --- src/basic/namespace-util.c | 14 ++++++++++++++ src/basic/namespace-util.h | 2 ++ src/core/machine-id-setup.c | 8 +++----- src/shared/tests.c | 6 ++---- src/test/test-udev.c | 13 ++++++------- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index b0168ae227..b34c532604 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -2,6 +2,7 @@ #include #include +#include #include "fd-util.h" #include "missing_fs.h" @@ -169,3 +170,16 @@ int fd_is_network_ns(int fd) { return r == CLONE_NEWNET; } + +int detach_mount_namespace(void) { + + /* Detaches the mount namespace, disabling propagation from our namespace to the host */ + + if (unshare(CLONE_NEWNS) < 0) + return -errno; + + if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) + return -errno; + + return 0; +} diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index 8c17ce91b2..99d9b977ed 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -7,3 +7,5 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int * 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); + +int detach_mount_namespace(void); diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index 284b77c1fc..f76b82a8a4 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -223,11 +223,9 @@ int machine_id_commit(const char *root) { return log_error_errno(r, "Can't fetch current mount namespace: %m"); /* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */ - if (unshare(CLONE_NEWNS) < 0) - return log_error_errno(errno, "Failed to enter new namespace: %m"); - - if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) - return log_error_errno(errno, "Couldn't make-rslave / mountpoint in our private namespace: %m"); + r = detach_mount_namespace(); + if (r < 0) + return log_error_errno(r, "Failed to set up new mount namespace: %m"); if (umount(etc_machine_id) < 0) return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id); diff --git a/src/shared/tests.c b/src/shared/tests.c index ecf8e8f623..ff662ecfe0 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -21,6 +21,7 @@ #include "env-util.h" #include "fs-util.h" #include "log.h" +#include "namespace-util.h" #include "path-util.h" #include "random-util.h" #include "strv.h" @@ -137,10 +138,7 @@ bool have_namespaces(void) { if (pid == 0) { /* child */ - if (unshare(CLONE_NEWNS) < 0) - _exit(EXIT_FAILURE); - - if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) + if (detach_mount_namespace() < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); diff --git a/src/test/test-udev.c b/src/test/test-udev.c index 208e7a0e96..c0b215dadc 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -17,6 +17,7 @@ #include "log.h" #include "main-func.h" #include "mkdir.h" +#include "namespace-util.h" #include "selinux-util.h" #include "signal-util.h" #include "string-util.h" @@ -36,15 +37,13 @@ static int fake_filesystems(void) { { "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true }, { "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true }, }; - unsigned i; + int r; - if (unshare(CLONE_NEWNS) < 0) - return log_error_errno(errno, "Failed to call unshare(): %m"); + r = detach_mount_namespace(); + if (r < 0) + return log_error_errno(r, "Failed to detach mount namespace: %m"); - if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) - return log_error_errno(errno, "Failed to mount / as private: %m"); - - for (i = 0; i < ELEMENTSOF(fakefss); i++) + for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error); if (!fakefss[i].ignore_mount_error)