summaryrefslogtreecommitdiffstats
path: root/src/nspawn
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn')
-rw-r--r--src/nspawn/nspawn-network.c50
-rw-r--r--src/nspawn/nspawn-network.h1
-rw-r--r--src/nspawn/nspawn.c17
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);