diff options
Diffstat (limited to 'src/nspawn')
-rw-r--r-- | src/nspawn/nspawn-network.c | 50 | ||||
-rw-r--r-- | src/nspawn/nspawn-network.h | 1 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 17 |
3 files changed, 62 insertions, 6 deletions
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index ec5d396..f46995b 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -821,6 +821,56 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs) { return 0; } +static int remove_macvlan_impl(char **interface_pairs) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + + assert(interface_pairs); + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + STRV_FOREACH_PAIR(a, b, interface_pairs) { + _cleanup_free_ char *n = NULL; + + n = strdup(*b); + if (!n) + return log_oom(); + + (void) net_shorten_ifname(n, /* check_naming_scheme= */ true); + + r = remove_one_link(rtnl, n); + if (r < 0) + log_warning_errno(r, "Failed to remove macvlan interface %s, ignoring: %m", n); + } + + return 0; +} + +int remove_macvlan(int child_netns_fd, char **interface_pairs) { + _cleanup_close_ int parent_netns_fd = -EBADF; + int r; + + /* In some cases the kernel might pin the macvlan links on the container even after the namespace + * died. Hence, let's better remove them explicitly too. See issue #680. */ + + assert(child_netns_fd >= 0); + + if (strv_isempty(interface_pairs)) + return 0; + + r = netns_fork_and_wait(child_netns_fd, &parent_netns_fd); + if (r < 0) + return r; + if (r == 0) { + r = remove_macvlan_impl(interface_pairs); + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + return 0; +} + int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int r; diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h index 840fe15..ed08c98 100644 --- a/src/nspawn/nspawn-network.h +++ b/src/nspawn/nspawn-network.h @@ -17,6 +17,7 @@ int setup_bridge(const char *veth_name, const char *bridge_name, bool create); int remove_bridge(const char *bridge_name); int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs); +int remove_macvlan(int child_netns_fd, char **interface_pairs); int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs); int move_network_interfaces(int netns_fd, char **iface_pairs); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5842d3b..c6ce36b 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2207,7 +2207,7 @@ static int copy_devnodes(const char *dest) { /* Explicitly warn the user when /dev is already populated. */ if (errno == 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 (errno != EPERM) + if (!ERRNO_IS_PRIVILEGE(errno) || arg_uid_shift != 0) return log_error_errno(errno, "mknod(%s) failed: %m", to); /* Some systems abusively restrict mknod but allow bind mounts. */ @@ -2217,12 +2217,12 @@ static int copy_devnodes(const char *dest) { r = mount_nofollow_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); if (r < 0) return log_error_errno(r, "Both mknod and bind mount (%s) failed: %m", to); + } else { + r = userns_lchown(to, 0, 0); + if (r < 0) + return log_error_errno(r, "chown() of device node %s failed: %m", to); } - r = userns_lchown(to, 0, 0); - if (r < 0) - return log_error_errno(r, "chown() of device node %s failed: %m", to); - dn = path_join("/dev", S_ISCHR(st.st_mode) ? "char" : "block"); if (!dn) return log_oom(); @@ -5567,7 +5567,8 @@ static int run_container( } else if (!isempty(arg_background)) (void) pty_forward_set_background_color(forward, arg_background); - set_window_title(forward); + if (shall_set_terminal_title()) + set_window_title(forward); break; default: @@ -5606,6 +5607,10 @@ static int run_container( r = move_back_network_interfaces(child_netns_fd, arg_network_interfaces); if (r < 0) return r; + + r = remove_macvlan(child_netns_fd, arg_network_macvlan); + if (r < 0) + return r; } r = wait_for_container(TAKE_PID(*pid), &container_status); |