summaryrefslogtreecommitdiffstats
path: root/debian/patches/shared-mount-util-use-namespace_fork-utils.patch
blob: f870a3e3b931653eac932712cc8f9b038e5b2e41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
From: Luca Boccassi <luca.boccassi@microsoft.com>
Date: Thu, 13 Aug 2020 14:47:01 +0100
Subject: shared/mount-util: use namespace_fork utils

(cherry picked from commit 2338a175fdec3859eab03115ca82a0d58453f5d7)
---
 src/shared/mount-util.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 4cfbb55..368c5f0 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -17,6 +17,7 @@
 #include "mkdir.h"
 #include "mount-util.h"
 #include "mountpoint-util.h"
+#include "namespace-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
@@ -756,12 +757,13 @@ int bind_mount_in_namespace(
                 bool make_file_or_directory) {
 
         _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
+        _cleanup_close_ int self_mntns_fd = -1, mntns_fd = -1, root_fd = -1;
         char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
         bool mount_slave_created = false, mount_slave_mounted = false,
                 mount_tmp_created = false, mount_tmp_mounted = false,
                 mount_outside_created = false, mount_outside_mounted = false;
         _cleanup_free_ char *chased_src = NULL;
-        struct stat st;
+        struct stat st, self_mntns_st;
         pid_t child;
         int r;
 
@@ -771,6 +773,24 @@ int bind_mount_in_namespace(
         assert(src);
         assert(dest);
 
+        r = namespace_open(target, NULL, &mntns_fd, NULL, NULL, &root_fd);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to retrieve FDs of the target process' namespace: %m");
+
+        if (fstat(mntns_fd, &st) < 0)
+                return log_debug_errno(errno, "Failed to fstat mount namespace FD of target process: %m");
+
+        r = namespace_open(0, NULL, &self_mntns_fd, NULL, NULL, NULL);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to retrieve FDs of systemd's namespace: %m");
+
+        if (fstat(self_mntns_fd, &self_mntns_st) < 0)
+                return log_debug_errno(errno, "Failed to fstat mount namespace FD of systemd: %m");
+
+        /* We can't add new mounts at runtime if the process wasn't started in a namespace */
+        if (st.st_ino == self_mntns_st.st_ino && st.st_dev == self_mntns_st.st_dev)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to activate bind mount in target, not running in a mount namespace");
+
         /* One day, when bind mounting /proc/self/fd/n works across
          * namespace boundaries we should rework this logic to make
          * use of it... */
@@ -877,27 +897,15 @@ int bind_mount_in_namespace(
                 goto finish;
         }
 
-        r = safe_fork("(sd-bindmnt)", FORK_RESET_SIGNALS, &child);
+        r = namespace_fork("(sd-bindmnt)", "(sd-bindmnt-inner)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+                           -1, mntns_fd, -1, -1, root_fd, &child);
         if (r < 0)
                 goto finish;
         if (r == 0) {
-                const char *mount_inside, *q;
-                int mntfd;
+                const char *mount_inside;
 
                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
 
-                q = procfs_file_alloca(target, "ns/mnt");
-                mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
-                if (mntfd < 0) {
-                        r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
-                        goto child_fail;
-                }
-
-                if (setns(mntfd, CLONE_NEWNS) < 0) {
-                        r = log_error_errno(errno, "Failed to join namespace of leader: %m");
-                        goto child_fail;
-                }
-
                 if (make_file_or_directory) {
                         (void) mkdir_parents(dest, 0755);
                         (void) make_mount_point_inode_from_stat(&st, dest, 0700);