process-util: add a new FORK_MOUNTNS_SLAVE flag for safe_fork()
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Mar 2018 19:52:46 +0000 (20:52 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 24 May 2018 15:01:57 +0000 (17:01 +0200)
We already have a flag for creating a new mount namespace for the child.
Let's add an extension to that: a new FORK_MOUNTNFS_SLAVE flag. When
used in combination will mark all mounts in the child namespace as
MS_SLAVE so that the child can freely mount or unmount stuff but it
won't leak into the parent.

src/basic/process-util.c
src/basic/process-util.h
src/shared/dissect-image.c

index ce56ce0..65abaaf 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/mount.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
@@ -1344,6 +1345,16 @@ int safe_fork_full(
                 }
         }
 
+        if ((flags & (FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE)) == (FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE)) {
+
+                /* Optionally, make sure we never propagate mounts to the host. */
+
+                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
+                        log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
+                        _exit(EXIT_FAILURE);
+                }
+        }
+
         if (flags & FORK_CLOSE_ALL_FDS) {
                 /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
                 log_close();
index 0cec7c4..ba6fea6 100644 (file)
@@ -163,6 +163,7 @@ typedef enum ForkFlags {
         FORK_LOG           = 1U << 5,
         FORK_WAIT          = 1U << 6,
         FORK_NEW_MOUNTNS   = 1U << 7,
+        FORK_MOUNTNS_SLAVE = 1U << 8,
 } ForkFlags;
 
 int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
index f63c2a0..608e4b5 100644 (file)
@@ -1278,14 +1278,10 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         if (r < 0)
                 goto finish;
 
-        r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS, &child);
+        r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
         if (r < 0)
                 goto finish;
         if (r == 0) {
-                /* Make sure we never propagate to the host */
-                if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
-                        _exit(EXIT_FAILURE);
-
                 r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to mount dissected image: %m");