The hotplug code was not correctly invoking the security driver
in error paths. If a hotplug attempt failed, the device would
be left with VM permissions applied, rather than restored to the
original permissions. Also, a CDROM media that is ejected was
not restored to original permissions. Finally there was a bogus
call to set hostdev permissions in the hostdev unplug code
* qemu/qemu_driver.c: Fix security driver usage in hotplug/unplug
---
src/qemu/qemu_driver.c | 177 +++++++++++++++++++++++++++++++++---------------
1 files changed, 123 insertions(+), 54 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 22b6adc..5054bcf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5126,6 +5126,11 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
return -1;
}
+ if (driver->securityDriver &&
+ driver->securityDriver->domainSetSecurityImageLabel &&
+ driver->securityDriver->domainSetSecurityImageLabel(conn, vm, newdisk) <
0)
+ return -1;
+
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (newdisk->src) {
@@ -5144,14 +5149,27 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
- if (ret == 0) {
- VIR_FREE(origdisk->src);
- origdisk->src = newdisk->src;
- newdisk->src = NULL;
- origdisk->type = newdisk->type;
- }
+ if (ret < 0)
+ goto error;
+
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, origdisk)
< 0)
+ VIR_WARN("Unable to restore security label on ejected image %s",
origdisk->src);
+
+ VIR_FREE(origdisk->src);
+ origdisk->src = newdisk->src;
+ newdisk->src = NULL;
+ origdisk->type = newdisk->type;
return ret;
+
+error:
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, newdisk)
< 0)
+ VIR_WARN("Unable to restore security label on new media %s",
newdisk->src);
+ return -1;
}
@@ -5173,9 +5191,14 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
}
}
+ if (driver->securityDriver &&
+ driver->securityDriver->domainSetSecurityImageLabel &&
+ driver->securityDriver->domainSetSecurityImageLabel(conn, vm,
dev->data.disk) < 0)
+ return -1;
+
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
virReportOOMError(conn);
- return -1;
+ goto error;
}
qemuDomainObjEnterMonitorWithDriver(driver, vm);
@@ -5185,13 +5208,22 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
&guestAddr);
qemuDomainObjExitMonitorWithDriver(driver, vm);
- if (ret == 0) {
- dev->data.disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
- memcpy(&dev->data.disk->info.addr.pci, &guestAddr,
sizeof(guestAddr));
- virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
- }
+ if (ret < 0)
+ goto error;
- return ret;
+ dev->data.disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ memcpy(&dev->data.disk->info.addr.pci, &guestAddr, sizeof(guestAddr));
+ virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
+
+ return 0;
+
+error:
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm,
dev->data.disk) < 0)
+ VIR_WARN("Unable to restore security label on %s",
dev->data.disk->src);
+
+ return -1;
}
static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
@@ -5285,15 +5317,21 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
if (STREQ(vm->def->disks[i]->dst, dev->dst)) {
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("target %s already exists"), dev->dst);
- goto cleanup;
+ return -1;
}
}
+
+ if (driver->securityDriver &&
+ driver->securityDriver->domainSetSecurityImageLabel &&
+ driver->securityDriver->domainSetSecurityImageLabel(conn, vm, dev) < 0)
+ return -1;
+
/* This func allocates the bus/unit IDs so must be before
* we search for controller
*/
if (!(drivestr = qemuBuildDriveStr(dev, 0, qemuCmdFlags)))
- goto cleanup;
+ goto error;
/* We should have an adddress now, so make sure */
@@ -5301,24 +5339,24 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unexpected disk address type %s"),
virDomainDeviceAddressTypeToString(dev->info.type));
- goto cleanup;
+ goto error;
}
for (i = 0 ; i < dev->info.addr.drive.controller ; i++) {
cont = qemuDomainFindOrCreateSCSIDiskController(conn, driver, vm, i);
if (!cont)
- goto cleanup;
+ goto error;
}
if (cont->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("SCSI controller %d was missing its PCI address"),
cont->idx);
- goto cleanup;
+ goto error;
}
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
virReportOOMError(conn);
- goto cleanup;
+ goto error;
}
qemuDomainObjEnterMonitorWithDriver(driver, vm);
@@ -5326,20 +5364,28 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
drivestr,
&cont->info.addr.pci,
&driveAddr);
-
qemuDomainObjExitMonitorWithDriver(driver, vm);
- if (ret == 0) {
- /* XXX we should probably validate that the addr matches
- * our existing defined addr instead of overwriting */
- dev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
- memcpy(&dev->info.addr.drive, &driveAddr, sizeof(driveAddr));
- virDomainDiskInsertPreAlloced(vm->def, dev);
- }
+ if (ret < 0)
+ goto error;
-cleanup:
+ /* XXX we should probably validate that the addr matches
+ * our existing defined addr instead of overwriting */
+ dev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+ memcpy(&dev->info.addr.drive, &driveAddr, sizeof(driveAddr));
+ virDomainDiskInsertPreAlloced(vm->def, dev);
VIR_FREE(drivestr);
- return ret;
+
+ return 0;
+
+error:
+ VIR_FREE(drivestr);
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, dev) <
0)
+ VIR_WARN("Unable to restore security label on %s", dev->src);
+
+ return -1;
}
@@ -5359,27 +5405,43 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr
conn,
}
}
+ if (driver->securityDriver &&
+ driver->securityDriver->domainSetSecurityImageLabel &&
+ driver->securityDriver->domainSetSecurityImageLabel(conn, vm,
dev->data.disk) < 0)
+ return -1;
+
if (!dev->data.disk->src) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("disk source path is missing"));
- return -1;
+ goto error;
}
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
virReportOOMError(conn);
- return -1;
+ goto error;
}
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorAddUSBDisk(priv->mon, dev->data.disk->src);
qemuDomainObjExitMonitorWithDriver(driver, vm);
- if (ret == 0)
- virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
+ if (ret < 0)
+ goto error;
- return ret;
+ virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
+
+ return 0;
+
+error:
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm,
dev->data.disk) < 0)
+ VIR_WARN("Unable to restore security label on %s",
dev->data.disk->src);
+
+ return -1;
}
+
static int qemudDomainAttachNetDevice(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
@@ -5617,15 +5679,31 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
switch (hostdev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
- return qemudDomainAttachHostPciDevice(conn, driver, vm, dev);
+ if (qemudDomainAttachHostPciDevice(conn, driver, vm, dev) < 0)
+ goto error;
+ break;
+
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
- return qemudDomainAttachHostUsbDevice(conn, driver, vm, dev);
+ if (qemudDomainAttachHostUsbDevice(conn, driver, vm, dev) < 0)
+ goto error;
+ break;
+
default:
qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
_("hostdev subsys type '%s' not supported"),
virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
- return -1;
+ goto error;
}
+
+ return 0;
+
+error:
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityHostdevLabel &&
+ driver->securityDriver->domainRestoreSecurityHostdevLabel(conn, vm,
dev->data.hostdev) < 0)
+ VIR_WARN0("Unable to restore host device labelling on hotplug fail");
+
+ return -1;
}
static int qemudDomainAttachDevice(virDomainPtr dom,
@@ -5688,18 +5766,10 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- if (driver->securityDriver &&
- driver->securityDriver->domainSetSecurityImageLabel)
- driver->securityDriver->domainSetSecurityImageLabel(dom->conn,
vm, dev->data.disk);
-
ret = qemudDomainChangeEjectableMedia(dom->conn, driver, vm, dev);
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
- if (driver->securityDriver &&
- driver->securityDriver->domainSetSecurityImageLabel)
- driver->securityDriver->domainSetSecurityImageLabel(dom->conn,
vm, dev->data.disk);
-
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm,
dev);
} else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
@@ -5815,6 +5885,11 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
}
virDomainDiskDefFree(detach);
+ if (driver->securityDriver &&
+ driver->securityDriver->domainRestoreSecurityImageLabel &&
+ driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm,
dev->data.disk) < 0)
+ VIR_WARN("Unable to restore security label on %s",
dev->data.disk->src);
+
ret = 0;
cleanup:
@@ -6081,9 +6156,9 @@ static int qemudDomainDetachHostDevice(virConnectPtr conn,
}
if (driver->securityDriver &&
- driver->securityDriver->domainSetSecurityHostdevLabel &&
- driver->securityDriver->domainSetSecurityHostdevLabel(conn, vm,
dev->data.hostdev) < 0)
- VIR_WARN0("Failed to restore device labelling");
+ driver->securityDriver->domainRestoreSecurityHostdevLabel &&
+ driver->securityDriver->domainRestoreSecurityHostdevLabel(conn, vm,
dev->data.hostdev) < 0)
+ VIR_WARN0("Failed to restore host device labelling");
return ret;
}
@@ -6124,9 +6199,6 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
ret = qemudDomainDetachPciDiskDevice(dom->conn, driver, vm, dev);
- if (driver->securityDriver &&
- driver->securityDriver->domainRestoreSecurityImageLabel)
- driver->securityDriver->domainRestoreSecurityImageLabel(dom->conn,
vm, dev->data.disk);
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
ret = qemudDomainDetachNetDevice(dom->conn, driver, vm, dev);
} else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
@@ -6140,9 +6212,6 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
}
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
ret = qemudDomainDetachHostDevice(dom->conn, driver, vm, dev);
- if (driver->securityDriver &&
- driver->securityDriver->domainRestoreSecurityHostdevLabel)
- driver->securityDriver->domainRestoreSecurityHostdevLabel(dom->conn,
vm, dev->data.hostdev);
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("This type of device cannot be hot
unplugged"));
--
1.6.5.2