Unverified Commit 352e79d4 by Stéphane Graber Committed by GitHub

Merge pull request #2025 from brauner/2017-12-12/fix_network_attach_and_detach

lxccontainer: only attach netns on netdev detach
parents 13700360 c7d76c09
...@@ -4250,22 +4250,27 @@ static bool do_lxcapi_may_control(struct lxc_container *c) ...@@ -4250,22 +4250,27 @@ static bool do_lxcapi_may_control(struct lxc_container *c)
WRAP_API(bool, lxcapi_may_control) WRAP_API(bool, lxcapi_may_control)
static bool do_add_remove_node(pid_t init_pid, const char *path, bool add, static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
struct stat *st) struct stat *st)
{ {
int ret;
char *tmp;
pid_t pid;
char chrootpath[MAXPATHLEN]; char chrootpath[MAXPATHLEN];
char *directory_path = NULL; char *directory_path = NULL;
pid_t pid;
int ret;
if ((pid = fork()) < 0) { pid = fork();
SYSERROR("failed to fork a child helper"); if (pid < 0) {
SYSERROR("Failed to fork()");
return false; return false;
} }
if (pid) { if (pid) {
if (wait_for_pid(pid) != 0) { ret = wait_for_pid(pid);
ERROR("Failed to create note in guest"); if (ret != 0) {
ERROR("Failed to create device node");
return false; return false;
} }
return true; return true;
} }
...@@ -4274,34 +4279,49 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add, ...@@ -4274,34 +4279,49 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
if (ret < 0 || ret >= MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return false; return false;
if (chroot(chrootpath) < 0) ret = chroot(chrootpath);
exit(1); if (ret < 0)
if (chdir("/") < 0) exit(EXIT_FAILURE);
exit(1);
ret = chdir("/");
if (ret < 0)
exit(EXIT_FAILURE);
/* remove path if it exists */ /* remove path if it exists */
if(faccessat(AT_FDCWD, path, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { ret = faccessat(AT_FDCWD, path, F_OK, AT_SYMLINK_NOFOLLOW);
if (unlink(path) < 0) { if(ret == 0) {
ERROR("unlink failed"); ret = unlink(path);
exit(1); if (ret < 0) {
ERROR("%s - Failed to remove \"%s\"", strerror(errno), path);
exit(EXIT_FAILURE);
} }
} }
if (!add) if (!add)
exit(0); exit(EXIT_SUCCESS);
/* create any missing directories */ /* create any missing directories */
directory_path = dirname(strdup(path)); tmp = strdup(path);
if (mkdir_p(directory_path, 0755) < 0 && errno != EEXIST) { if (!tmp)
ERROR("failed to create directory"); exit(EXIT_FAILURE);
exit(1);
directory_path = dirname(tmp);
ret = mkdir_p(directory_path, 0755);
if (ret < 0 && errno != EEXIST) {
ERROR("%s - Failed to create path \"%s\"", strerror(errno), directory_path);
free(tmp);
exit(EXIT_FAILURE);
} }
/* create the device node */ /* create the device node */
if (mknod(path, st->st_mode, st->st_rdev) < 0) { ret = mknod(path, st->st_mode, st->st_rdev);
ERROR("mknod failed"); free(tmp);
exit(1); if (ret < 0) {
ERROR("%s - Failed to create device node at \"%s\"", strerror(errno), path);
exit(EXIT_FAILURE);
} }
exit(0); exit(EXIT_SUCCESS);
} }
static bool add_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path, bool add) static bool add_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path, bool add)
...@@ -4377,10 +4397,13 @@ static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *sr ...@@ -4377,10 +4397,13 @@ static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *sr
WRAP_API_2(bool, lxcapi_remove_device_node, const char *, const char *) WRAP_API_2(bool, lxcapi_remove_device_node, const char *, const char *)
static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifname, static bool do_lxcapi_attach_interface(struct lxc_container *c,
const char *dst_ifname) const char *ifname,
const char *dst_ifname)
{ {
pid_t init_pid;
int ret = 0; int ret = 0;
if (am_unpriv()) { if (am_unpriv()) {
ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
return false; return false;
...@@ -4392,7 +4415,6 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifna ...@@ -4392,7 +4415,6 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifna
} }
ret = lxc_netdev_isup(ifname); ret = lxc_netdev_isup(ifname);
if (ret > 0) { if (ret > 0) {
/* netdev of ifname is up. */ /* netdev of ifname is up. */
ret = lxc_netdev_down(ifname); ret = lxc_netdev_down(ifname);
...@@ -4400,10 +4422,12 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifna ...@@ -4400,10 +4422,12 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifna
goto err; goto err;
} }
ret = lxc_netdev_move_by_name(ifname, do_lxcapi_init_pid(c), dst_ifname); init_pid = do_lxcapi_init_pid(c);
ret = lxc_netdev_move_by_name(ifname, init_pid, dst_ifname);
if (ret) if (ret)
goto err; goto err;
INFO("Moved network device \"%s\" to network namespace of %d", ifname, init_pid);
return true; return true;
err: err:
...@@ -4412,9 +4436,11 @@ err: ...@@ -4412,9 +4436,11 @@ err:
WRAP_API_2(bool, lxcapi_attach_interface, const char *, const char *) WRAP_API_2(bool, lxcapi_attach_interface, const char *, const char *)
static bool do_lxcapi_detach_interface(struct lxc_container *c, const char *ifname, static bool do_lxcapi_detach_interface(struct lxc_container *c,
const char *dst_ifname) const char *ifname,
const char *dst_ifname)
{ {
int ret;
pid_t pid, pid_outside; pid_t pid, pid_outside;
if (am_unpriv()) { if (am_unpriv()) {
...@@ -4430,40 +4456,52 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c, const char *ifna ...@@ -4430,40 +4456,52 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c, const char *ifna
pid_outside = getpid(); pid_outside = getpid();
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
ERROR("failed to fork task to get interfaces information"); ERROR("Failed to fork");
return false; return false;
} }
if (pid == 0) { /* child */ if (pid == 0) { /* child */
int ret = 0; pid_t init_pid;
if (!enter_net_ns(c)) {
ERROR("failed to enter namespace"); init_pid = do_lxcapi_init_pid(c);
exit(-1); if (!switch_to_ns(init_pid, "net")) {
ERROR("Failed to enter network namespace");
exit(EXIT_FAILURE);
} }
ret = lxc_netdev_isup(ifname); ret = lxc_netdev_isup(ifname);
if (ret < 0) if (ret < 0) {
exit(ret); ERROR("Failed to determine whether network device \"%s\" is up", ifname);
exit(EXIT_FAILURE);
}
/* netdev of ifname is up. */ /* netdev of ifname is up. */
if (ret) { if (ret) {
ret = lxc_netdev_down(ifname); ret = lxc_netdev_down(ifname);
if (ret) if (ret) {
exit(ret); ERROR("Failed to set network device \"%s\" down", ifname);
exit(EXIT_FAILURE);
}
} }
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 ifanme. */ if (ret < 0) {
if (ret == -EINVAL) { if (ret == -EINVAL)
ERROR("No network device named as %s.", ifname); ERROR("Network device \"%s\" not found", ifname);
else
ERROR("Failed to remove network device \"%s\"", ifname);
exit(EXIT_FAILURE);
} }
exit(ret);
exit(EXIT_SUCCESS);
} }
if (wait_for_pid(pid) != 0) ret = wait_for_pid(pid);
if (ret != 0)
return false; return false;
INFO("Moved network device \"%s\" to network namespace of %d", ifname, pid_outside);
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment