From: Yu Watanabe Date: Wed, 17 Jan 2024 00:48:12 +0000 (+0900) Subject: nspawn-network: split out move_network_interface_one() X-Git-Tag: v256-rc1~1103^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38475cac6f7c3d74b3c0a4468d9a61ae76a127ad;p=thirdparty%2Fsystemd.git nspawn-network: split out move_network_interface_one() This also changes to use sd_device to get some attributes. So, on moving interfaces back to the parent, we need to populate sysfs associated to the client netns. That may look redundant and complicated, but it makes later change easier, and hopefully faster. --- diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index de21c68a6db..27ae07eba49 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -4,17 +4,21 @@ #include #include #include +#include #include "sd-device.h" #include "sd-id128.h" #include "sd-netlink.h" #include "alloc-util.h" +#include "device-util.h" #include "ether-addr-util.h" #include "fd-util.h" #include "hexdecoct.h" #include "lock-util.h" #include "missing_network.h" +#include "mkdir.h" +#include "mount-util.h" #include "namespace-util.h" #include "netif-naming-scheme.h" #include "netlink-util.h" @@ -531,6 +535,22 @@ static int netns_child_begin(int netns_fd, int *ret_original_netns_fd) { if (r < 0) return log_error_errno(r, "Failed to enter child network namespace: %m"); + r = umount_recursive("/sys/", /* flags = */ 0); + if (r < 0) + log_debug_errno(r, "Failed to unmount directories below /sys/, ignoring: %m"); + + (void) mkdir_p("/sys/", 0755); + + /* Populate new sysfs instance associated with the client netns, to make sd_device usable. */ + r = mount_nofollow_verbose(LOG_ERR, "sysfs", "/sys/", "sysfs", + MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, /* opts = */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to mount sysfs on /sys/: %m"); + + /* udev_avaliable() might be called previously and the result may be cached. + * Now, we (re-)mount sysfs. Hence, we need to reset the cache. */ + reset_cached_udev_availability(); + if (ret_original_netns_fd) *ret_original_netns_fd = TAKE_FD(original_netns_fd); @@ -542,7 +562,7 @@ static int netns_fork_and_wait(int netns_fd, int *ret_original_netns_fd) { assert(netns_fd >= 0); - r = safe_fork("(sd-netns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL); + r = safe_fork("(sd-netns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL); if (r < 0) return log_error_errno(r, "Failed to fork process (sd-netns): %m"); if (r == 0) { @@ -558,42 +578,71 @@ static int netns_fork_and_wait(int netns_fd, int *ret_original_netns_fd) { return 1; } -int move_network_interfaces(int netns_fd, char **iface_pairs) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; +static int move_network_interface_one(sd_netlink **rtnl, int netns_fd, sd_device *dev, const char *name) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; - if (strv_isempty(iface_pairs)) - return 0; + assert(rtnl); + assert(netns_fd >= 0); + assert(dev); + assert(name); - r = sd_netlink_open(&rtnl); + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to rtnetlink: %m"); + } + + int ifindex; + r = sd_device_get_ifindex(dev, &ifindex); if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); + return log_device_error_errno(dev, r, "Failed to get ifindex: %m"); - STRV_FOREACH_PAIR(i, b, iface_pairs) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - int ifi; + r = sd_rtnl_message_new_link(*rtnl, &m, RTM_SETLINK, ifindex); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to allocate netlink message: %m"); - ifi = rtnl_resolve_interface_or_warn(&rtnl, *i); - if (ifi < 0) - return ifi; + r = sd_netlink_message_append_u32(m, IFLA_NET_NS_FD, netns_fd); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to append namespace fd to netlink message: %m"); - r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, ifi); - if (r < 0) - return log_error_errno(r, "Failed to allocate netlink message: %m"); + const char *sysname; + r = sd_device_get_sysname(dev, &sysname); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get sysname: %m"); - r = sd_netlink_message_append_u32(m, IFLA_NET_NS_FD, netns_fd); + if (!streq(name, sysname)) { + r = sd_netlink_message_append_string(m, IFLA_IFNAME, name); if (r < 0) - return log_error_errno(r, "Failed to append namespace fd to netlink message: %m"); + return log_device_error_errno(dev, r, "Failed to add netlink interface name: %m"); + } + + r = sd_netlink_call(*rtnl, m, 0, NULL); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to move interface to namespace: %m"); - if (!streq(*b, *i)) { - r = sd_netlink_message_append_string(m, IFLA_IFNAME, *b); - if (r < 0) - return log_error_errno(r, "Failed to add netlink interface name: %m"); - } + return 0; +} - r = sd_netlink_call(rtnl, m, 0, NULL); +int move_network_interfaces(int netns_fd, char **iface_pairs) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + + assert(netns_fd >= 0); + + if (strv_isempty(iface_pairs)) + return 0; + + STRV_FOREACH_PAIR(from, to, iface_pairs) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + r = sd_device_new_from_ifname(&dev, *from); if (r < 0) - return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i); + return log_error_errno(r, "Unknown interface name %s: %m", *from); + + r = move_network_interface_one(&rtnl, netns_fd, dev, *to); + if (r < 0) + return r; } return 0;