[libvirt] [PATCH] qemu: Use correct permissions when determining the image chain

The code took into account only the global permissions. The domains now support per-vm DAC lables and per-image DAC labels. Use the most specific label available. --- src/qemu/qemu_domain.c | 35 +++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 8 ++++---- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_process.c | 2 +- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c947e2e..d45210b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2210,7 +2210,7 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver, if (!disk->src) continue; - if (qemuDomainDetermineDiskChain(driver, disk, false) >= 0 && + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) >= 0 && qemuDiskChainCheckBroken(disk) >= 0) continue; @@ -2319,13 +2319,41 @@ qemuDiskChainCheckBroken(virDomainDiskDefPtr disk) return 0; } +static void +qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg, + virDomainObjPtr vm, + virDomainDiskDefPtr disk, + uid_t *uid, gid_t *gid) +{ + virSecurityLabelDefPtr vmlabel; + virSecurityDeviceLabelDefPtr disklabel; + + if (cfg) { + if (uid) + *uid = cfg->user; + + if (gid) + *gid = cfg->group; + } + + if (vm && (vmlabel = virDomainDefGetSecurityLabelDef(vm->def, "dac"))) + virParseOwnershipIds(vmlabel->label, uid, gid); + + if ((disklabel = virDomainDiskDefGetSecurityLabelDef(disk, "dac"))) + virParseOwnershipIds(disklabel->label, uid, gid); +} + + int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, + virDomainObjPtr vm, virDomainDiskDefPtr disk, bool force) { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); int ret = 0; + uid_t uid; + gid_t gid; if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK || @@ -2340,8 +2368,11 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, goto cleanup; } } + + qemuDomainGetImageIds(cfg, vm, disk, &uid, &gid); + disk->backingChain = virStorageFileGetMetadata(disk->src, disk->format, - cfg->user, cfg->group, + uid, gid, cfg->allowDiskFormatProbing); if (!disk->backingChain) ret = -1; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 84624f9..3826d0b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -353,6 +353,7 @@ int qemuDomainCheckDiskPresence(virQEMUDriverPtr driver, int qemuDiskChainCheckBroken(virDomainDiskDefPtr disk); int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, + virDomainObjPtr vm, virDomainDiskDefPtr disk, bool force); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 944facb..94844df 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6499,7 +6499,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn, if (qemuTranslateDiskSourcePool(conn, disk) < 0) goto end; - if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) goto end; if (qemuSetupDiskCgroup(vm, disk) < 0) @@ -14632,7 +14632,7 @@ qemuDomainBlockPivot(virConnectPtr conn, disk->src = disk->mirror; disk->format = disk->mirrorFormat; disk->backingChain = NULL; - if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) { + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) { disk->src = oldsrc; disk->format = oldformat; disk->backingChain = oldchain; @@ -14983,7 +14983,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm, goto endjob; } - if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) goto endjob; if ((flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) && @@ -15190,7 +15190,7 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base, disk->dst); goto endjob; } - if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) goto endjob; if (!top) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 4a885d2..7066be6 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -719,7 +719,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, if (qemuSetUnprivSGIO(dev) < 0) goto end; - if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) + if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) goto end; if (qemuSetupDiskCgroup(vm, disk) < 0) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 8bcd98e..c1f60cd 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -997,7 +997,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL || type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) && status == VIR_DOMAIN_BLOCK_JOB_COMPLETED) - qemuDomainDetermineDiskChain(driver, disk, true); + qemuDomainDetermineDiskChain(driver, vm, disk, true); if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY && status == VIR_DOMAIN_BLOCK_JOB_READY) disk->mirroring = true; -- 1.8.5.3

On 02/07/2014 10:53 AM, Peter Krempa wrote:
The code took into account only the global permissions. The domains now support per-vm DAC lables and per-image DAC labels. Use the most
s/lables/labels/
specific label available. --- src/qemu/qemu_domain.c | 35 +++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 8 ++++---- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_process.c | 2 +- 5 files changed, 40 insertions(+), 8 deletions(-)
+static void +qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg, + virDomainObjPtr vm, + virDomainDiskDefPtr disk, + uid_t *uid, gid_t *gid) +{ + virSecurityLabelDefPtr vmlabel; + virSecurityDeviceLabelDefPtr disklabel;
Here, I'd add: if (uid) *uid = -1; if (gid) *gid = -1;
+ + if (cfg) { + if (uid) + *uid = cfg->user; + + if (gid) + *gid = cfg->group; + } + + if (vm && (vmlabel = virDomainDefGetSecurityLabelDef(vm->def, "dac"))) + virParseOwnershipIds(vmlabel->label, uid, gid); + + if ((disklabel = virDomainDiskDefGetSecurityLabelDef(disk, "dac"))) + virParseOwnershipIds(disklabel->label, uid, gid);
since all three of these more-specific overrides could all be missing, but ideally, you want to guarantee that we picked the best-possible uid/gid by the end of this method. ACK with that fixed - it means that all disks are now being opened by the same credentials as what we tell qemu to open with. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 02/07/14 21:47, Eric Blake wrote:
On 02/07/2014 10:53 AM, Peter Krempa wrote:
The code took into account only the global permissions. The domains now support per-vm DAC lables and per-image DAC labels. Use the most
s/lables/labels/
specific label available. --- src/qemu/qemu_domain.c | 35 +++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 8 ++++---- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_process.c | 2 +- 5 files changed, 40 insertions(+), 8 deletions(-)
+static void +qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg, + virDomainObjPtr vm, + virDomainDiskDefPtr disk, + uid_t *uid, gid_t *gid) +{ + virSecurityLabelDefPtr vmlabel; + virSecurityDeviceLabelDefPtr disklabel;
Here, I'd add:
if (uid) *uid = -1; if (gid) *gid = -1;
Right, I actually had that in one of the work versions but I've refactored it and forgot to initialize the variable.
+ + if (cfg) { + if (uid) + *uid = cfg->user; + + if (gid) + *gid = cfg->group; + } + + if (vm && (vmlabel = virDomainDefGetSecurityLabelDef(vm->def, "dac"))) + virParseOwnershipIds(vmlabel->label, uid, gid); + + if ((disklabel = virDomainDiskDefGetSecurityLabelDef(disk, "dac"))) + virParseOwnershipIds(disklabel->label, uid, gid);
since all three of these more-specific overrides could all be missing, but ideally, you want to guarantee that we picked the best-possible uid/gid by the end of this method.
ACK with that fixed - it means that all disks are now being opened by the same credentials as what we tell qemu to open with.
Fixed && pushed; Thanks. Peter
participants (2)
-
Eric Blake
-
Peter Krempa