lxccontainer: do_lxcapi_detach_interface to support detaching wlan devices

Signed-off-by: Thomas Parrott <thomas.parrott@canonical.com>
This commit is contained in:
Thomas Parrott 2019-07-26 16:14:18 +01:00
parent f9f15a7a76
commit e4103cf63f
5 changed files with 31 additions and 4 deletions

View File

@ -213,7 +213,7 @@ static int lxc_attach_to_ns(pid_t pid, struct lxc_proc_context_info *ctx)
return 0; return 0;
} }
static int lxc_attach_remount_sys_proc(void) int lxc_attach_remount_sys_proc(void)
{ {
int ret; int ret;

View File

@ -45,4 +45,6 @@ extern int lxc_attach(struct lxc_container *container,
lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_exec_t exec_function, void *exec_payload,
lxc_attach_options_t *options, pid_t *attached_process); lxc_attach_options_t *options, pid_t *attached_process);
extern int lxc_attach_remount_sys_proc(void);
#endif /* __LXC_ATTACH_H */ #endif /* __LXC_ATTACH_H */

View File

@ -4793,6 +4793,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
{ {
int ret; int ret;
pid_t pid, pid_outside; pid_t pid, pid_outside;
__do_free char *physname = NULL;
/* /*
* TODO - if this is a physical device, then we need am_host_unpriv. * TODO - if this is a physical device, then we need am_host_unpriv.
@ -4828,6 +4829,19 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
/* create new mount namespace for use with remounting /sys and is_wlan() below. */
ret = unshare(CLONE_NEWNS);
if (ret < 0) {
ERROR("Failed to unshare mount namespace");
_exit(EXIT_FAILURE);
}
/* set / recursively as private so that mount propagation doesn't affect us. */
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
ERROR("Failed to recursively set / as private in mount namespace");
_exit(EXIT_FAILURE);
}
ret = lxc_netdev_isup(ifname); ret = lxc_netdev_isup(ifname);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to determine whether network device \"%s\" is up", ifname); ERROR("Failed to determine whether network device \"%s\" is up", ifname);
@ -4843,7 +4857,14 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
} }
} }
/* remount /sys so is_wlan() can check if this device is a wlan device. */
lxc_attach_remount_sys_proc();
physname = is_wlan(ifname);
if (physname)
ret = lxc_netdev_move_wlan(physname, ifname, pid_outside, dst_ifname);
else
ret = lxc_netdev_move_by_name(ifname, pid_outside, dst_ifname); ret = lxc_netdev_move_by_name(ifname, pid_outside, dst_ifname);
/* -EINVAL means there is no netdev named as ifname. */ /* -EINVAL means there is no netdev named as ifname. */
if (ret < 0) { if (ret < 0) {
if (ret == -EINVAL) if (ret == -EINVAL)

View File

@ -1172,7 +1172,7 @@ out:
* will be passed to lxc_netdev_move_wlan() which will free it when done. * will be passed to lxc_netdev_move_wlan() which will free it when done.
*/ */
#define PHYSNAME "/sys/class/net/%s/phy80211/name" #define PHYSNAME "/sys/class/net/%s/phy80211/name"
static char *is_wlan(const char *ifname) char *is_wlan(const char *ifname)
{ {
__do_free char *path = NULL; __do_free char *path = NULL;
int i, ret; int i, ret;
@ -1245,7 +1245,7 @@ static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
_exit(lxc_netdev_rename_by_name(old, new)); _exit(lxc_netdev_rename_by_name(old, new));
} }
static int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid, int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
const char *newname) const char *newname)
{ {
__do_free char *cmd = NULL; __do_free char *cmd = NULL;

View File

@ -293,4 +293,8 @@ extern int lxc_netns_set_nsid(int netns_fd);
extern int lxc_netns_get_nsid(__s32 fd); extern int lxc_netns_get_nsid(__s32 fd);
extern int lxc_create_network(struct lxc_handler *handler); extern int lxc_create_network(struct lxc_handler *handler);
extern char *is_wlan(const char *ifname);
extern int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
const char *newname);
#endif /* __LXC_NETWORK_H */ #endif /* __LXC_NETWORK_H */