You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
3.4 KiB
94 lines
3.4 KiB
From 91ad9b94bcd964adfbaa8d84d8f39304d39835d0 Mon Sep 17 00:00:00 2001
|
|
From: Christian Brauner <christian.brauner@ubuntu.com>
|
|
Date: Thu, 6 May 2021 18:16:45 +0200
|
|
Subject: [PATCH] conf: handle kernels with CAP_SETFCAP
|
|
|
|
LXC is being very clever and sometimes maps the caller's uid into the
|
|
child userns. This means that the caller can technically write fscaps
|
|
that are valid in the ancestor userns (which can be a security issue in
|
|
some scenarios) so newer kernels require CAP_SETFCAP to do this. Until
|
|
newuidmap/newgidmap are updated to account for this simply write the
|
|
mapping directly in this case.
|
|
|
|
Cc: stable-4.0
|
|
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
|
|
---
|
|
src/lxc/conf.c | 25 ++++++++++++++++++++-----
|
|
1 file changed, 20 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
|
|
index 72e21b5300..f388946970 100644
|
|
--- a/src/lxc/conf.c
|
|
+++ b/src/lxc/conf.c
|
|
@@ -2978,6 +2978,9 @@ static int lxc_map_ids_exec_wrapper(void *args)
|
|
return -1;
|
|
}
|
|
|
|
+static struct id_map *find_mapped_hostid_entry(const struct lxc_list *idmap,
|
|
+ unsigned id, enum idtype idtype);
|
|
+
|
|
int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
|
{
|
|
int fill, left;
|
|
@@ -2991,12 +2994,22 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
|
char mapbuf[STRLITERALLEN("new@idmap") + STRLITERALLEN(" ") +
|
|
INTTYPE_TO_STRLEN(pid_t) + STRLITERALLEN(" ") +
|
|
LXC_IDMAPLEN] = {0};
|
|
- bool had_entry = false, use_shadow = false;
|
|
+ bool had_entry = false, maps_host_root = false, use_shadow = false;
|
|
int hostuid, hostgid;
|
|
|
|
hostuid = geteuid();
|
|
hostgid = getegid();
|
|
|
|
+ /*
|
|
+ * Check whether caller wants to map host root.
|
|
+ * Due to a security fix newer kernels require CAP_SETFCAP when mapping
|
|
+ * host root into the child userns as you would be able to write fscaps
|
|
+ * that would be valid in the ancestor userns. Mapping host root should
|
|
+ * rarely be the case but LXC is being clever in a bunch of cases.
|
|
+ */
|
|
+ if (find_mapped_hostid_entry(idmap, 0, ID_TYPE_UID))
|
|
+ maps_host_root = true;
|
|
+
|
|
/* If new{g,u}idmap exists, that is, if shadow is handing out subuid
|
|
* ranges, then insist that root also reserve ranges in subuid. This
|
|
* will protected it by preventing another user from being handed the
|
|
@@ -3014,7 +3027,9 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
|
|
else if (!gidmap)
|
|
WARN("newgidmap is lacking necessary privileges");
|
|
|
|
- if (uidmap > 0 && gidmap > 0) {
|
|
+ if (maps_host_root) {
|
|
+ INFO("Caller maps host root. Writing mapping directly");
|
|
+ } else if (uidmap > 0 && gidmap > 0) {
|
|
DEBUG("Functional newuidmap and newgidmap binary found");
|
|
use_shadow = true;
|
|
} else {
|
|
@@ -4229,14 +4244,14 @@ static struct id_map *mapped_nsid_add(const struct lxc_conf *conf, unsigned id,
|
|
return retmap;
|
|
}
|
|
|
|
-static struct id_map *find_mapped_hostid_entry(const struct lxc_conf *conf,
|
|
+static struct id_map *find_mapped_hostid_entry(const struct lxc_list *idmap,
|
|
unsigned id, enum idtype idtype)
|
|
{
|
|
struct id_map *map;
|
|
struct lxc_list *it;
|
|
struct id_map *retmap = NULL;
|
|
|
|
- lxc_list_for_each (it, &conf->id_map) {
|
|
+ lxc_list_for_each (it, idmap) {
|
|
map = it->elem;
|
|
if (map->idtype != idtype)
|
|
continue;
|
|
@@ -4265,7 +4280,7 @@ static struct id_map *mapped_hostid_add(const struct lxc_conf *conf, uid_t id,
|
|
return NULL;
|
|
|
|
/* Reuse existing mapping. */
|
|
- tmp = find_mapped_hostid_entry(conf, id, type);
|
|
+ tmp = find_mapped_hostid_entry(&conf->id_map, id, type);
|
|
if (tmp) {
|
|
memcpy(entry, tmp, sizeof(*entry));
|
|
} else {
|