From d3c66b20cae5bcd13e0afcbabdb4b9385e8699ff Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 1 Sep 2017 16:44:46 +0200 Subject: [PATCH] network: stop recording saved physical net devices liblxc will now correctly log any network device names and ifindeces in their respective network namespaces. So there's no need to record physical network devices any more. This spares us heap allocations and memory we need to have lying around til the container is shutdown. Signed-off-by: Christian Brauner --- src/lxc/conf.c | 12 ------- src/lxc/conf.h | 2 -- src/lxc/confile_utils.c | 4 +++ src/lxc/network.c | 75 ++++++++++++++++++++++++----------------- src/lxc/network.h | 7 +--- src/lxc/start.c | 41 +++------------------- 6 files changed, 54 insertions(+), 87 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 268c73e4f..b1d35e98a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3511,17 +3511,6 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key) return 0; } -static void lxc_clear_saved_nics(struct lxc_conf *conf) -{ - int i; - - if (!conf->saved_nics) - return; - for (i=0; i < conf->num_savednics; i++) - free(conf->saved_nics[i].orig_name); - free(conf->saved_nics); -} - static inline void lxc_clear_aliens(struct lxc_conf *conf) { struct lxc_list *it,*next; @@ -3575,7 +3564,6 @@ void lxc_conf_free(struct lxc_conf *conf) lxc_clear_cgroups(conf, "lxc.cgroup"); lxc_clear_hooks(conf, "lxc.hook"); lxc_clear_mount_entries(conf); - lxc_clear_saved_nics(conf); lxc_clear_idmaps(conf); lxc_clear_groups(conf); lxc_clear_includes(conf); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 43e836fa6..3aaf51440 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -211,8 +211,6 @@ struct lxc_conf { struct lxc_list cgroup; struct lxc_list id_map; struct lxc_list network; - struct saved_nic *saved_nics; - int num_savednics; int auto_mounts; struct lxc_list mount_list; struct lxc_list caps; diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 8b7b3a5b4..dd3548e5b 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -278,6 +278,10 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) break; case LXC_NET_PHYS: TRACE("type: phys"); + if (netdev->priv.phys_attr.ifindex > 0) { + TRACE("host side ifindex for phys device: %d", + netdev->priv.phys_attr.ifindex); + } break; case LXC_NET_EMPTY: TRACE("type: empty"); diff --git a/src/lxc/network.c b/src/lxc/network.c index c965653df..f52a139b4 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -2277,7 +2277,7 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler) char netns_path[6 + LXC_NUMSTRLEN64 + 4 + LXC_NUMSTRLEN64 + 1]; bool deleted_all = true; - if (!am_unpriv()) + if (handler->root) return true; *netns_path = '\0'; @@ -2346,13 +2346,10 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler) int lxc_create_network_priv(struct lxc_handler *handler) { - bool am_root; struct lxc_list *iterator; struct lxc_list *network = &handler->conf->network; - /* We need to be root. */ - am_root = (getuid() == 0); - if (!am_root) + if (!handler->root) return 0; lxc_list_for_each(iterator, network) { @@ -2454,7 +2451,7 @@ bool lxc_delete_network_priv(struct lxc_handler *handler) struct lxc_list *network = &handler->conf->network; bool deleted_all = true; - if (am_unpriv()) + if (!handler->root) return true; lxc_list_for_each(iterator, network) { @@ -2471,12 +2468,12 @@ bool lxc_delete_network_priv(struct lxc_handler *handler) ret = lxc_netdev_rename_by_index(netdev->ifindex, netdev->link); if (ret < 0) WARN("Failed to rename interface with index %d " - "to its initial name \"%s\"", - netdev->ifindex, netdev->link); + "from \"%s\" to its initial name \"%s\"", + netdev->ifindex, netdev->name, netdev->link); else TRACE("Renamed interface with index %d to its " - "initial name \"%s\"", - netdev->ifindex, netdev->link); + "from \"%s\" to its initial name \"%s\"", + netdev->ifindex, netdev->name, netdev->link); continue; } @@ -2572,51 +2569,69 @@ int lxc_requests_empty_network(struct lxc_handler *handler) } /* try to move physical nics to the init netns */ -void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf) +int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler) { int ret; - int i, oldfd; + int oldfd; char ifname[IFNAMSIZ]; + struct lxc_list *iterator; + int netnsfd = handler->netnsfd; + struct lxc_conf *conf = handler->conf; - if (netnsfd < 0 || conf->num_savednics == 0) - return; + /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to + * the parent network namespace. We won't have this capability if we are + * unprivileged. + */ + if (!handler->root) + return 0; - INFO("Trying to restore network device names in original namespace for " - "%d network devices", conf->num_savednics); + TRACE("Moving physical network devices back to parent network namespace"); oldfd = lxc_preserve_ns(getpid(), "net"); if (oldfd < 0) { SYSERROR("Failed to preserve network namespace"); - return; + return -1; } - ret = setns(netnsfd, 0); + ret = setns(netnsfd, CLONE_NEWNET); if (ret < 0) { SYSERROR("Failed to enter network namespace"); close(oldfd); - return; + return -1; } - for (i = 0; i < conf->num_savednics; i++) { - struct saved_nic *s = &conf->saved_nics[i]; + lxc_list_for_each(iterator, &conf->network) { + struct lxc_netdev *netdev = iterator->elem; - /* retrieve the name of the interface */ - if (!if_indextoname(s->ifindex, ifname)) { + if (netdev->type != LXC_NET_PHYS) + continue; + + /* Retrieve the name of the interface in the container's network + * namespace. + */ + if (!if_indextoname(netdev->ifindex, ifname)) { WARN("No interface corresponding to ifindex %d", - s->ifindex); + netdev->ifindex); continue; } - if (lxc_netdev_move_by_name(ifname, 1, s->orig_name)) + + ret = lxc_netdev_move_by_name(ifname, 1, netdev->link); + if (ret < 0) WARN("Error moving network device \"%s\" back to " "network namespace", ifname); - free(s->orig_name); + else + TRACE("Moved network device \"%s\" back to network " + "namespace", ifname); } - conf->num_savednics = 0; - ret = setns(oldfd, 0); - if (ret < 0) - SYSERROR("Failed to enter network namespace"); + ret = setns(oldfd, CLONE_NEWNET); close(oldfd); + if (ret < 0) { + SYSERROR("Failed to enter network namespace"); + return -1; + } + + return 0; } static int setup_hw_addr(char *hwaddr, const char *ifname) diff --git a/src/lxc/network.h b/src/lxc/network.h index f80ea15cb..9badf14b8 100644 --- a/src/lxc/network.h +++ b/src/lxc/network.h @@ -175,11 +175,6 @@ struct lxc_netdev { char *downscript; }; -struct saved_nic { - int ifindex; - char *orig_name; -}; - /* Convert a string mac address to a socket structure. */ extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr); @@ -307,7 +302,7 @@ extern int lxc_find_gateway_addresses(struct lxc_handler *handler); extern int lxc_create_network_unpriv(const char *lxcpath, char *lxcname, struct lxc_list *network, pid_t pid); extern int lxc_requests_empty_network(struct lxc_handler *handler); -extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf); +extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler); extern int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf, struct lxc_list *network); diff --git a/src/lxc/start.c b/src/lxc/start.c index 616651187..116b1ebd8 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1162,36 +1162,6 @@ out_error: return -1; } -static int save_phys_nics(struct lxc_conf *conf) -{ - struct lxc_list *iterator; - int am_root = (getuid() == 0); - - if (!am_root) - return 0; - - lxc_list_for_each(iterator, &conf->network) { - struct lxc_netdev *netdev = iterator->elem; - - if (netdev->type != LXC_NET_PHYS) - continue; - conf->saved_nics = realloc(conf->saved_nics, - (conf->num_savednics+1)*sizeof(struct saved_nic)); - if (!conf->saved_nics) - return -1; - conf->saved_nics[conf->num_savednics].ifindex = netdev->ifindex; - conf->saved_nics[conf->num_savednics].orig_name = strdup(netdev->link); - if (!conf->saved_nics[conf->num_savednics].orig_name) - return -1; - INFO("Stored saved_nic #%d idx %d name %s.", conf->num_savednics, - conf->saved_nics[conf->num_savednics].ifindex, - conf->saved_nics[conf->num_savednics].orig_name); - conf->num_savednics++; - } - - return 0; -} - static int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler) { struct lxc_list *iterator, *network; @@ -1359,11 +1329,6 @@ static int lxc_spawn(struct lxc_handler *handler) return -1; } } - - if (save_phys_nics(handler->conf)) { - ERROR("Failed to save physical nic info."); - goto out_abort; - } } if (!cgroup_init(handler)) { @@ -1689,8 +1654,10 @@ int __lxc_start(const char *name, struct lxc_handler *handler, } } - DEBUG("Pushing physical nics back to host namespace"); - lxc_restore_phys_nics_to_netns(handler->netnsfd, handler->conf); + err = lxc_restore_phys_nics_to_netns(handler); + if (err < 0) + ERROR("Failed to move physical network devices back to parent " + "network namespace"); if (handler->pinfd >= 0) { close(handler->pinfd); -- 2.47.2