mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-08 12:18:51 +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);
|
token = strtok_r(buffer, ":", &saveptr);
|
||||||
if (!token)
|
if (!token)
|
||||||
return -1;
|
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 */
|
/* fill netdev->veth_attr.pair field */
|
||||||
token = strtok_r(NULL, ":", &saveptr);
|
token = strtok_r(NULL, ":", &saveptr);
|
||||||
if (!token)
|
if (!token)
|
||||||
return -1;
|
return -1;
|
||||||
netdev->priv.veth_attr.pair = strdup(token);
|
netdev->priv.veth_attr.pair = strdup(token);
|
||||||
|
if (!netdev->priv.veth_attr.pair) {
|
||||||
|
ERROR("Out of memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
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 (netdev->type == LXC_NET_VETH && !am_root) {
|
||||||
if (unpriv_assign_nic(netdev, pid))
|
if (unpriv_assign_nic(netdev, pid))
|
||||||
return -1;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,6 +563,52 @@ static int must_drop_cap_sys_boot(struct lxc_conf *conf)
|
|||||||
return 0;
|
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)
|
static int do_start(void *data)
|
||||||
{
|
{
|
||||||
struct lxc_handler *handler = 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))
|
if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
|
||||||
return -1;
|
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
|
* if we are in a new user namespace, become root there to have
|
||||||
* privilege over our namespace
|
* privilege over our namespace
|
||||||
@ -728,6 +777,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
const char *name = handler->name;
|
const char *name = handler->name;
|
||||||
int saved_ns_fd[LXC_NS_MAX];
|
int saved_ns_fd[LXC_NS_MAX];
|
||||||
int preserve_mask = 0, i;
|
int preserve_mask = 0, i;
|
||||||
|
int netpipepair[2], nveths;
|
||||||
|
|
||||||
for (i = 0; i < LXC_NS_MAX; i++)
|
for (i = 0; i < LXC_NS_MAX; i++)
|
||||||
if (handler->conf->inherit_ns_fd[i] != -1)
|
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)
|
if (attach_ns(handler->conf->inherit_ns_fd) < 0)
|
||||||
goto out_delete_net;
|
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 */
|
/* Create a process in a new set of namespaces */
|
||||||
handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
|
handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
|
||||||
if (handler->pid < 0) {
|
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
|
/* map the container uids - the container became an invalid
|
||||||
* userid the moment it was cloned with CLONE_NEWUSER - this
|
* userid the moment it was cloned with CLONE_NEWUSER - this
|
||||||
* call doesn't change anything immediately, but allows the
|
* call doesn't change anything immediately, but allows the
|
||||||
|
Loading…
Reference in New Issue
Block a user