mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-06 03:36:04 +00:00
Fix unprivileged networking
If we are unprivileged and have asked for a veth device, then create a pipe over which to pass the veth names. Network-related todos: 1. set mtu on the container side of veth device 2. set mtu in lxc-user-nic. Note that this probably requires an update to the /etc/lxc/lxc-usernet file :( Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com> Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
parent
4f1d50d114
commit
658979c5f9
@ -3114,13 +3114,23 @@ static int unpriv_assign_nic(struct lxc_netdev *netdev, pid_t pid)
|
||||
token = strtok_r(buffer, ":", &saveptr);
|
||||
if (!token)
|
||||
return -1;
|
||||
netdev->name = strdup(token);
|
||||
netdev->name = malloc(IFNAMSIZ+1);
|
||||
if (!netdev->name) {
|
||||
ERROR("Out of memory");
|
||||
return -1;
|
||||
}
|
||||
memset(netdev->name, 0, IFNAMSIZ+1);
|
||||
strncpy(netdev->name, token, IFNAMSIZ);
|
||||
|
||||
/* fill netdev->veth_attr.pair field */
|
||||
token = strtok_r(NULL, ":", &saveptr);
|
||||
if (!token)
|
||||
return -1;
|
||||
netdev->priv.veth_attr.pair = strdup(token);
|
||||
if (!netdev->priv.veth_attr.pair) {
|
||||
ERROR("Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3139,7 +3149,9 @@ int lxc_assign_network(struct lxc_list *network, pid_t pid)
|
||||
if (netdev->type == LXC_NET_VETH && !am_root) {
|
||||
if (unpriv_assign_nic(netdev, pid))
|
||||
return -1;
|
||||
// TODO fill in netdev->ifindex and name
|
||||
// lxc-user-nic has moved the nic to the new ns.
|
||||
// unpriv_assign_nic() fills in netdev->name.
|
||||
// netdev->ifindex will be filed in at setup_netdev.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -563,6 +563,52 @@ static int must_drop_cap_sys_boot(struct lxc_conf *conf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* netpipe is used in the unprivileged case to transfer the ifindexes
|
||||
* from parent to child
|
||||
*/
|
||||
static int netpipe = -1;
|
||||
|
||||
static inline int count_veths(struct lxc_list *network)
|
||||
{
|
||||
struct lxc_list *iterator;
|
||||
struct lxc_netdev *netdev;
|
||||
int count = 0;
|
||||
|
||||
lxc_list_for_each(iterator, network) {
|
||||
netdev = iterator->elem;
|
||||
if (netdev->type != LXC_NET_VETH)
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int read_unpriv_netifindex(struct lxc_list *network)
|
||||
{
|
||||
struct lxc_list *iterator;
|
||||
struct lxc_netdev *netdev;
|
||||
|
||||
if (netpipe == -1)
|
||||
return 0;
|
||||
lxc_list_for_each(iterator, network) {
|
||||
netdev = iterator->elem;
|
||||
if (netdev->type != LXC_NET_VETH)
|
||||
continue;
|
||||
if (!(netdev->name = malloc(IFNAMSIZ))) {
|
||||
ERROR("Out of memory");
|
||||
close(netpipe);
|
||||
return -1;
|
||||
}
|
||||
if (read(netpipe, netdev->name, IFNAMSIZ) != IFNAMSIZ) {
|
||||
close(netpipe);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
close(netpipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_start(void *data)
|
||||
{
|
||||
struct lxc_handler *handler = data;
|
||||
@ -597,6 +643,9 @@ static int do_start(void *data)
|
||||
if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
|
||||
return -1;
|
||||
|
||||
if (read_unpriv_netifindex(&handler->conf->network) < 0)
|
||||
goto out_warn_father;
|
||||
|
||||
/*
|
||||
* if we are in a new user namespace, become root there to have
|
||||
* privilege over our namespace
|
||||
@ -728,6 +777,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
const char *name = handler->name;
|
||||
int saved_ns_fd[LXC_NS_MAX];
|
||||
int preserve_mask = 0, i;
|
||||
int netpipepair[2], nveths;
|
||||
|
||||
for (i = 0; i < LXC_NS_MAX; i++)
|
||||
if (handler->conf->inherit_ns_fd[i] != -1)
|
||||
@ -816,6 +866,15 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
if (attach_ns(handler->conf->inherit_ns_fd) < 0)
|
||||
goto out_delete_net;
|
||||
|
||||
if (am_unpriv() && (nveths = count_veths(&handler->conf->network))) {
|
||||
if (pipe(netpipepair) < 0) {
|
||||
SYSERROR("Error creating pipe");
|
||||
goto out_delete_net;
|
||||
}
|
||||
/* store netpipe in the global var for do_start's use */
|
||||
netpipe = netpipepair[0];
|
||||
}
|
||||
|
||||
/* Create a process in a new set of namespaces */
|
||||
handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
|
||||
if (handler->pid < 0) {
|
||||
@ -857,6 +916,23 @@ static int lxc_spawn(struct lxc_handler *handler)
|
||||
}
|
||||
}
|
||||
|
||||
if (netpipe != -1) {
|
||||
struct lxc_list *iterator;
|
||||
struct lxc_netdev *netdev;
|
||||
|
||||
close(netpipe);
|
||||
lxc_list_for_each(iterator, &handler->conf->network) {
|
||||
netdev = iterator->elem;
|
||||
if (netdev->type != LXC_NET_VETH)
|
||||
continue;
|
||||
if (write(netpipepair[1], netdev->name, IFNAMSIZ) != IFNAMSIZ) {
|
||||
ERROR("Error writing veth name to container");
|
||||
goto out_delete_net;
|
||||
}
|
||||
}
|
||||
close(netpipepair[1]);
|
||||
}
|
||||
|
||||
/* map the container uids - the container became an invalid
|
||||
* userid the moment it was cloned with CLONE_NEWUSER - this
|
||||
* call doesn't change anything immediately, but allows the
|
||||
|
Loading…
Reference in New Issue
Block a user