If the user did not specify any uid mapping, map its own
user ID to ID 0 inside the container and the rest of the IDs
to the first found user's authorized range in /etc/sub[ug]id
https://issues.redhat.com/browse/RHEL-7386
https://gitlab.com/libvirt/libvirt/-/issues/535
Signed-off-by: Ján Tomko <jtomko(a)redhat.com>
---
src/qemu/qemu_virtiofs.c | 76 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 74 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c
index 4dacd37a1c..d539d0a192 100644
--- a/src/qemu/qemu_virtiofs.c
+++ b/src/qemu/qemu_virtiofs.c
@@ -369,12 +369,84 @@ qemuVirtioFSSetupCgroup(virDomainObj *vm,
return 0;
}
+static int
+qemuVirtioFSPrepareIdMap(virDomainFSDef *fs)
+{
+ g_autofree char *username = NULL;
+ g_autofree char *groupname = NULL;
+ virSubID *subuids = NULL;
+ virSubID *subgids = NULL;
+ uid_t euid = geteuid();
+ uid_t egid = getegid();
+ int subuidlen = 0;
+ int subgidlen = 0;
+ size_t i;
+
+ username = virGetUserName(euid);
+ groupname = virGetGroupName(egid);
+
+ fs->idmap.uidmap = g_new0(virDomainIdMapEntry, 2);
+ fs->idmap.gidmap = g_new0(virDomainIdMapEntry, 2);
+
+ if ((subuidlen = virGetSubIDs(&subuids, "/etc/subuid")) < 0)
+ return -1;
+
+ fs->idmap.uidmap[0].start = 0;
+ fs->idmap.uidmap[0].target = euid;
+ fs->idmap.uidmap[0].count = 1;
+ fs->idmap.nuidmap = 1;
+
+ for (i = 0; i < subuidlen; i++) {
+ if ((subuids[i].idstr && STREQ(subuids[i].idstr, username)) ||
+ subuids[i].id == euid) {
+ fs->idmap.uidmap[1].start = 1;
+ fs->idmap.uidmap[1].target = subuids[i].start;
+ fs->idmap.uidmap[1].count = subuids[i].range;
+ fs->idmap.nuidmap++;
+ break;
+ }
+ }
+
+ virSubIDsFree(&subuids, subuidlen);
+
+ if ((subgidlen = virGetSubIDs(&subgids, "/etc/subgid")) < 0)
+ return -1;
+
+ fs->idmap.gidmap[0].start = 0;
+ fs->idmap.gidmap[0].target = getegid();
+ fs->idmap.gidmap[0].count = 1;
+ fs->idmap.ngidmap = 1;
+
+ for (i = 0; i < subgidlen; i++) {
+ if ((subgids[i].idstr && STREQ(subgids[i].idstr, groupname)) ||
+ subgids[i].id == egid) {
+ fs->idmap.gidmap[1].start = 1;
+ fs->idmap.gidmap[1].target = subgids[i].start;
+ fs->idmap.gidmap[1].count = subgids[i].range;
+ fs->idmap.ngidmap++;
+ break;
+ }
+ }
+
+ virSubIDsFree(&subgids, subgidlen);
+
+ return 0;
+}
+
int
qemuVirtioFSPrepareDomain(virQEMUDriver *driver,
virDomainFSDef *fs)
{
- if (fs->binary || fs->sock)
+ if (fs->sock)
return 0;
- return qemuVhostUserFillDomainFS(driver, fs);
+ if (!fs->binary && qemuVhostUserFillDomainFS(driver, fs) < 0)
+ return -1;
+
+ if (!driver->privileged && !fs->idmap.uidmap) {
+ if (qemuVirtioFSPrepareIdMap(fs) < 0)
+ return -1;
+ }
+
+ return 0;
}
--
2.42.0