nspawn: move network namespace creation to a separate step (#8430)
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 20 Mar 2018 17:07:17 +0000 (18:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Mar 2018 17:07:17 +0000 (18:07 +0100)
Fixes #8427.

Unsharing the namespace in a separate step changes the ownership of
/proc/net/ip_tables_names (and related files) from nobody:nobody to
root:root. See [1] and [2] for all the details.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f13f2aeed154da8e48f90b85e720f8ba39b1e881
[2] https://bugzilla.netfilter.org/show_bug.cgi?id=1064#c9

src/nspawn/nspawn.c

index 90f1c41..4b941ed 100644 (file)
@@ -2323,10 +2323,15 @@ static int inner_child(
                       arg_uid_shift,
                       arg_uid_range,
                       arg_selinux_apifs_context);
-
         if (r < 0)
                 return r;
 
+        if (!arg_network_namespace_path && arg_private_network) {
+                r = unshare(CLONE_NEWNET);
+                if (r < 0)
+                        return log_error_errno(errno, "Failed to unshare network namespace: %m");
+        }
+
         r = mount_sysfs(NULL, arg_mount_settings);
         if (r < 0)
                 return r;
@@ -2341,7 +2346,7 @@ static int inner_child(
         if (arg_use_cgns && cg_ns_supported()) {
                 r = unshare(CLONE_NEWCGROUP);
                 if (r < 0)
-                        return log_error_errno(errno, "Failed to unshare cgroup namespace");
+                        return log_error_errno(errno, "Failed to unshare cgroup namespace: %m");
                 r = mount_cgroups(
                                 "",
                                 arg_unified_cgroup_hierarchy,
@@ -2568,7 +2573,6 @@ static int outer_child(
         ssize_t l;
         int r;
         _cleanup_close_ int fd = -1;
-        bool create_netns;
 
         assert(barrier);
         assert(directory);
@@ -2811,11 +2815,8 @@ static int outer_child(
         if (fd < 0)
                 return fd;
 
-        create_netns = !arg_network_namespace_path && arg_private_network;
-
         pid = raw_clone(SIGCHLD|CLONE_NEWNS|
                         arg_clone_ns_flags |
-                        (create_netns ? CLONE_NEWNET : 0) |
                         (arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0));
         if (pid < 0)
                 return log_error_errno(errno, "Failed to fork inner child: %m");