]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: ignore failure in creating /dev/net/tun when --private-network is unspecified
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 13 Nov 2024 04:36:11 +0000 (13:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Nov 2024 07:54:06 +0000 (16:54 +0900)
Follow-up for efedb6b0f3cff37950112fd37cb750c16d599bc7.
Closes #35116.

src/nspawn/nspawn.c

index 3f443daf237ebaafb3866853df551ed7570b4e9f..64f8ecdd7dbc51ab27a1380b574ea34daed9cfad 100644 (file)
@@ -2246,7 +2246,7 @@ static int bind_mount_devnode(const char *from, const char *to) {
         return 0;
 }
 
-static int copy_devnode_one(const char *dest, const char *node) {
+static int copy_devnode_one(const char *dest, const char *node, bool ignore_mknod_failure) {
         int r;
 
         assert(dest);
@@ -2290,13 +2290,23 @@ static int copy_devnode_one(const char *dest, const char *node) {
                 if (r == -EEXIST)
                         log_notice("%s/dev/ is pre-mounted and pre-populated. If a pre-mounted /dev/ is provided it needs to be an unpopulated file system.", dest);
                 /* If arg_uid_shift != 0, then we cannot fall back to use bind mount. */
-                if (arg_uid_shift != 0)
+                if (arg_uid_shift != 0) {
+                        if (ignore_mknod_failure) {
+                                log_debug_errno(r, "Failed to mknod(%s), ignoring: %m", to);
+                                return 0;
+                        }
                         return log_error_errno(r, "Failed to mknod(%s): %m", to);
+                }
 
                 /* Some systems abusively restrict mknod but allow bind mounts. */
-                if (bind_mount_devnode(from, to) < 0)
+                if (bind_mount_devnode(from, to) < 0) {
                         /* use the original error code. */
+                        if (ignore_mknod_failure) {
+                                log_debug_errno(r, "Both mknod() and bind mount %s failed, ignoring: %m", to);
+                                return 0;
+                        }
                         return log_error_errno(r, "Both mknod() and bind mount %s failed: %m", to);
+                }
         } else {
                 /* mknod() succeeds, chown() it if necessary. */
                 r = userns_lchown(to, 0, 0);
@@ -2336,18 +2346,21 @@ static int copy_devnodes(const char *dest, bool enable_fuse) {
         assert(dest);
 
         FOREACH_STRING(node, "null", "zero", "full", "random", "urandom", "tty") {
-                r = copy_devnode_one(dest, node);
+                r = copy_devnode_one(dest, node, /* ignore_mknod_failure = */ false);
                 if (r < 0)
                         return r;
         }
 
         if (enable_fuse) {
-                r = copy_devnode_one(dest, "fuse");
+                r = copy_devnode_one(dest, "fuse", /* ignore_mknod_failure = */ false);
                 if (r < 0)
                         return r;
         }
 
-        r = copy_devnode_one(dest, "net/tun");
+        /* We unconditionally try to create /dev/net/tun, but let's ignore failure if --private-network is
+         * unspecified. The failure can be triggered when e.g. DevicePolicy= is set, but DeviceAllow= does
+         * not contains the device node, and --private-users=pick is specified. */
+        r = copy_devnode_one(dest, "net/tun", /* ignore_mknod_failure = */ !arg_private_network);
         if (r < 0)
                 return r;