Skip to content

Commit

Permalink
network: delete ovs for unprivileged networks
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Aug 28, 2017
1 parent 7a58251 commit a055595
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 15 deletions.
134 changes: 120 additions & 14 deletions src/lxc/conf.c
Expand Up @@ -3207,26 +3207,44 @@ bool lxc_delete_network(struct lxc_handler *handler)
* namespace is destroyed but in case we did not move the
* interface to the network namespace, we have to destroy it.
*/
ret = lxc_netdev_delete_by_index(netdev->ifindex);
if (-ret == ENODEV) {
INFO("Interface \"%s\" with index %d already deleted "
"or existing in different network namespace",
netdev->name ? netdev->name : "(null)", netdev->ifindex);
} else if (ret < 0) {
deleted_all = false;
WARN("Failed to remove interface \"%s\" with index %d: "
"%s", netdev->name ? netdev->name : "(null)",
netdev->ifindex, strerror(-ret));
continue;
if (!am_unpriv()) {
ret = lxc_netdev_delete_by_index(netdev->ifindex);
if (-ret == ENODEV) {
INFO("Interface \"%s\" with index %d already "
"deleted or existing in different network "
"namespace",
netdev->name ? netdev->name : "(null)",
netdev->ifindex);
} else if (ret < 0) {
deleted_all = false;
WARN("Failed to remove interface \"%s\" with "
"index %d: %s",
netdev->name ? netdev->name : "(null)",
netdev->ifindex, strerror(-ret));
continue;
}
INFO("Removed interface \"%s\" with index %d",
netdev->name ? netdev->name : "(null)",
netdev->ifindex);
}
INFO("Removed interface \"%s\" with index %d",
netdev->name ? netdev->name : "(null)", netdev->ifindex);

if (netdev->type != LXC_NET_VETH)
continue;

if (am_unpriv())
if (am_unpriv()) {
if (is_ovs_bridge(netdev->link)) {
ret = lxc_unpriv_delete_nic(handler->lxcpath,
handler->name, "ovs",
netdev, getpid());
if (ret < 0)
WARN("Failed to remove port \"%s\" "
"from openvswitch bridge \"%s\"",
netdev->priv.veth_attr.pair,
netdev->link);
}

continue;
}

/* Explicitly delete host veth device to prevent lingering
* devices. We had issues in LXD around this.
Expand Down Expand Up @@ -5124,3 +5142,91 @@ struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings)

return result;
}

int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname, char *type,
struct lxc_netdev *netdev, pid_t pid)
{
pid_t child;
int bytes, pipefd[2];
char netdev_link[IFNAMSIZ + 1];
char buffer[MAX_BUFFER_SIZE] = {0};

if (netdev->type != LXC_NET_VETH) {
ERROR("nic type %d not support for unprivileged use",
netdev->type);
return -1;
}

if (pipe(pipefd) < 0) {
SYSERROR("pipe failed");
return -1;
}

child = fork();
if (child < 0) {
SYSERROR("fork");
close(pipefd[0]);
close(pipefd[1]);
return -1;
}

if (child == 0) { /* child */
/* Call lxc-user-nic pid type bridge. */
int ret;
char pidstr[LXC_NUMSTRLEN64];

close(pipefd[0]); /* Close the read-end of the pipe. */

/* Redirect stdout to write-end of the pipe. */
ret = dup2(pipefd[1], STDOUT_FILENO);
if (ret >= 0)
ret = dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]); /* Close the write-end of the pipe. */
if (ret < 0) {
SYSERROR("Failed to dup2() to redirect stdout to pipe file descriptor.");
exit(EXIT_FAILURE);
}

if (netdev->link)
strncpy(netdev_link, netdev->link, IFNAMSIZ);
else
strncpy(netdev_link, "none", IFNAMSIZ);

ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid);
if (ret < 0 || ret >= LXC_NUMSTRLEN64)
exit(EXIT_FAILURE);
pidstr[LXC_NUMSTRLEN64 - 1] = '\0';

INFO("Execing lxc-user-nic delete %s %s %s ovs %s %s", lxcpath,
lxcname, pidstr, netdev_link, netdev->priv.veth_attr.pair);
execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "delete", lxcpath,
lxcname, pidstr, "ovs", netdev_link,
netdev->priv.veth_attr.pair, (char *)NULL);
SYSERROR("Failed to exec lxc-user-nic.");
exit(EXIT_FAILURE);
}

/* close the write-end of the pipe */
close(pipefd[1]);

bytes = read(pipefd[0], &buffer, MAX_BUFFER_SIZE);
if (bytes < 0) {
SYSERROR("Failed to read from pipe file descriptor.");
close(pipefd[0]);
return -1;
}
buffer[bytes - 1] = '\0';

if (wait_for_pid(child) != 0) {
ERROR("lxc-user-nic failed to delete requested network: %s",
buffer[0] != '\0' ? buffer : "(null)");
close(pipefd[0]);
return -1;
}
TRACE("Received output \"%s\" from lxc-user-nic", buffer);

/* close the read-end of the pipe */
close(pipefd[0]);

return 0;
}
2 changes: 2 additions & 0 deletions src/lxc/conf.h
Expand Up @@ -500,5 +500,7 @@ extern FILE *make_anonymous_mount_file(struct lxc_list *mount);
extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
extern unsigned long add_required_remount_flags(const char *s, const char *d,
unsigned long flags);
extern int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname, char *type,
struct lxc_netdev *netdev, pid_t pid);

#endif /* __LXC_CONF_H */
22 changes: 21 additions & 1 deletion src/lxc/lxc_user_nic.c
Expand Up @@ -836,9 +836,10 @@ static char *lxc_secure_rename_in_ns(int pid, char *oldname, char *newname,
name = "eth%d";

ret = lxc_netdev_rename_by_name(oldname, name);
name = NULL;
if (ret < 0) {
usernic_error("Error %d renaming netdev %s to %s in container\n",
ret, oldname, name);
ret, oldname, newname ? newname : "eth%d");
goto do_full_cleanup;
}

Expand Down Expand Up @@ -1007,6 +1008,25 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}

if (!strcmp(args.cmd, "delete")) {
close(fd);

if (strcmp(args.type, "ovs")) {
usernic_error("%s", "Deletion of non ovs type network "
"devics not implemented\n");
exit(EXIT_FAILURE);
}

ret = lxc_ovs_delete_port(args.link, args.veth_name);
if (ret < 0) {
usernic_error("Failed to remove port \"%s\" from "
"openvswitch bridge \"%s\"",
args.veth_name, args.link);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

n = get_alloted(me, args.type, args.link, &alloted);
if (n > 0)
nicname = get_nic_if_avail(fd, alloted, pid, args.type,
Expand Down

0 comments on commit a055595

Please sign in to comment.