From: Yu Watanabe Date: Wed, 17 Jan 2024 00:28:31 +0000 (+0900) Subject: nspawn-network: split out move_back_network_interfaces() X-Git-Tag: v256-rc1~1103^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cdd9988e430007bba73bb3b57dddd9cf1ef05975;p=thirdparty%2Fsystemd.git nspawn-network: split out move_back_network_interfaces() No functional change, just refactoring and preparation for later commits. --- diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index 369d8742b60..de21c68a6db 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -11,13 +11,16 @@ #include "alloc-util.h" #include "ether-addr-util.h" +#include "fd-util.h" #include "hexdecoct.h" #include "lock-util.h" #include "missing_network.h" +#include "namespace-util.h" #include "netif-naming-scheme.h" #include "netlink-util.h" #include "nspawn-network.h" #include "parse-util.h" +#include "process-util.h" #include "siphash24.h" #include "socket-netlink.h" #include "socket-util.h" @@ -503,6 +506,58 @@ int test_network_interfaces_initialized(char **iface_pairs) { return 0; } +static int netns_child_begin(int netns_fd, int *ret_original_netns_fd) { + _cleanup_close_ int original_netns_fd = -EBADF; + int r; + + assert(netns_fd >= 0); + + if (ret_original_netns_fd) { + r = namespace_open(0, + /* ret_pidns_fd = */ NULL, + /* ret_mntns_fd = */ NULL, + &original_netns_fd, + /* ret_userns_fd = */ NULL, + /* ret_root_fd = */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to open original network namespace: %m"); + } + + r = namespace_enter(/* pidns_fd = */ -EBADF, + /* mntns_fd = */ -EBADF, + netns_fd, + /* userns_fd = */ -EBADF, + /* root_fd = */ -EBADF); + if (r < 0) + return log_error_errno(r, "Failed to enter child network namespace: %m"); + + if (ret_original_netns_fd) + *ret_original_netns_fd = TAKE_FD(original_netns_fd); + + return 0; +} + +static int netns_fork_and_wait(int netns_fd, int *ret_original_netns_fd) { + int r; + + assert(netns_fd >= 0); + + r = safe_fork("(sd-netns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL); + if (r < 0) + return log_error_errno(r, "Failed to fork process (sd-netns): %m"); + if (r == 0) { + if (netns_child_begin(netns_fd, ret_original_netns_fd) < 0) + _exit(EXIT_FAILURE); + + return 0; + } + + if (ret_original_netns_fd) + *ret_original_netns_fd = -EBADF; + + return 1; +} + int move_network_interfaces(int netns_fd, char **iface_pairs) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int r; @@ -544,6 +599,30 @@ int move_network_interfaces(int netns_fd, char **iface_pairs) { return 0; } +int move_back_network_interfaces(int child_netns_fd, char **interface_pairs) { + _cleanup_close_ int parent_netns_fd = -EBADF; + int r; + + 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) { + /* Reverse network interfaces pair list so that interfaces get their initial name back. + * This is about ensuring interfaces get their old name back when being moved back. */ + interface_pairs = strv_reverse(interface_pairs); + + r = move_network_interfaces(parent_netns_fd, interface_pairs); + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + return 0; +} + int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; unsigned idx = 0; diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h index a785f8ea42f..9729b6e37e7 100644 --- a/src/nspawn/nspawn-network.h +++ b/src/nspawn/nspawn-network.h @@ -19,6 +19,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **iface_pairs); int setup_ipvlan(const char *machine_name, pid_t pid, char **iface_pairs); int move_network_interfaces(int netns_fd, char **iface_pairs); +int move_back_network_interfaces(int child_netns_fd, char **interface_pairs); int veth_extra_parse(char ***l, const char *p); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5dd3ff5549e..445d85da6f0 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5377,46 +5377,9 @@ static int run_container( fd_kmsg_fifo = safe_close(fd_kmsg_fifo); if (arg_private_network) { - /* Move network interfaces back to the parent network namespace. We use `safe_fork` - * to avoid having to move the parent to the child network namespace. */ - r = safe_fork(NULL, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL); + r = move_back_network_interfaces(child_netns_fd, arg_network_interfaces); if (r < 0) return r; - - if (r == 0) { - _cleanup_close_ int parent_netns_fd = -EBADF; - - r = namespace_open(0, - /* ret_pidns_fd = */ NULL, - /* ret_mntns_fd = */ NULL, - &parent_netns_fd, - /* ret_userns_fd = */ NULL, - /* ret_root_fd = */ NULL); - if (r < 0) { - log_error_errno(r, "Failed to open parent network namespace: %m"); - _exit(EXIT_FAILURE); - } - - r = namespace_enter(/* pidns_fd = */ -EBADF, - /* mntns_fd = */ -EBADF, - child_netns_fd, - /* userns_fd = */ -EBADF, - /* root_fd = */ -EBADF); - if (r < 0) { - log_error_errno(r, "Failed to enter child network namespace: %m"); - _exit(EXIT_FAILURE); - } - - /* Reverse network interfaces pair list so that interfaces get their initial name back. - * This is about ensuring interfaces get their old name back when being moved back. */ - arg_network_interfaces = strv_reverse(arg_network_interfaces); - - r = move_network_interfaces(parent_netns_fd, arg_network_interfaces); - if (r < 0) - log_error_errno(r, "Failed to move network interfaces back to parent network namespace: %m"); - - _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); - } } r = wait_for_container(TAKE_PID(*pid), &container_status);