* src/qemu/qemu_audit.h (qemuDomainHostdevAudit): New prototype. * src/qemu/qemu_audit.c (qemuDomainHostdevAudit): New function. (qemuDomainStartAudit): Call as appropriate. * src/qemu/qemu_hotplug.c (qemuDomainAttachHostPciDevice) (qemuDomainAttachHostUsbDevice, qemuDomainDetachHostPciDevice) (qemuDomainDetachHostUsbDevice): Likewise. --- v2: new patch; covers the case of pci and usb host device passthrough, worth auditing since this can involve IOMMU mappings to have the guest manage the device I/O. src/qemu/qemu_audit.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_audit.h | 4 ++ src/qemu/qemu_hotplug.c | 28 +++++++----------- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/src/qemu/qemu_audit.c b/src/qemu/qemu_audit.c index 6ea31c9..26247a6 100644 --- a/src/qemu/qemu_audit.c +++ b/src/qemu/qemu_audit.c @@ -103,6 +103,75 @@ void qemuDomainNetAudit(virDomainObjPtr vm, /** + * qemuDomainHostdevAudit: + * @vm: domain making a change in pass-through host device + * @hostdev: device being attached or removed + * @reason: one of "start, "attach", or "detach" + * @success: true if the device passthrough operation succeeded + * + * Log an audit message about an attempted device passthrough change. + */ +void +qemuDomainHostdevAudit(virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev, + const char *reason, + bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *vmname; + char *address; + char *device; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + switch (hostdev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + if (virAsprintf(&address, "%.4x:%.2x:%.2x.%.1x", + hostdev->source.subsys.u.pci.domain, + hostdev->source.subsys.u.pci.bus, + hostdev->source.subsys.u.pci.slot, + hostdev->source.subsys.u.pci.function) < 0) { + VIR_WARN0("OOM while encoding audit message"); + goto cleanup; + } + break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: + if (virAsprintf(&address, "%.3d.%.3d", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device) < 0) { + VIR_WARN0("OOM while encoding audit message"); + goto cleanup; + } + break; + default: + VIR_WARN("Unexpected hostdev type while encoding audit message: %d", + hostdev->source.subsys.type); + goto cleanup; + } + + if (!(device = virAuditEncode("device", VIR_AUDIT_STR(address)))) { + VIR_WARN0("OOM while encoding audit message"); + goto cleanup; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success, + "resrc=dev reason=%s %s uuid=%s type=%s %s", + reason, vmname, uuidstr, + virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type), + device); + +cleanup: + VIR_FREE(vmname); + VIR_FREE(device); + VIR_FREE(address); +} + + +/** * qemuDomainCgroupAudit: * @vm: domain making the cgroups ACL change * @cgroup: cgroup that manages the devices @@ -238,6 +307,11 @@ void qemuDomainStartAudit(virDomainObjPtr vm, const char *reason, bool success) qemuDomainNetAudit(vm, NULL, net, "start", true); } + for (i = 0 ; i < vm->def->nhostdevs ; i++) { + virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i]; + qemuDomainHostdevAudit(vm, hostdev, "start", true); + } + qemuDomainMemoryAudit(vm, 0, vm->def->mem.cur_balloon, "start", true); qemuDomainVcpuAudit(vm, 0, vm->def->vcpus, "start", true); diff --git a/src/qemu/qemu_audit.h b/src/qemu/qemu_audit.h index cdbb957..2f901be 100644 --- a/src/qemu/qemu_audit.h +++ b/src/qemu/qemu_audit.h @@ -39,6 +39,10 @@ void qemuDomainNetAudit(virDomainObjPtr vm, virDomainNetDefPtr newDef, const char *reason, bool success); +void qemuDomainHostdevAudit(virDomainObjPtr vm, + virDomainHostdevDefPtr def, + const char *reason, + bool success); void qemuDomainCgroupAudit(virDomainObjPtr vm, virCgroupPtr group, const char *reason, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 8090b90..da07c29 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -842,6 +842,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr)); } + qemuDomainHostdevAudit(vm, hostdev, "attach", ret == 0); if (ret < 0) goto error; @@ -918,6 +919,7 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainHostdevAudit(vm, hostdev, "attach", ret == 0); if (ret < 0) goto error; @@ -1607,20 +1609,14 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - return -1; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - return -1; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci); } qemuDomainObjExitMonitorWithDriver(driver, vm); - - ret = 0; + qemuDomainHostdevAudit(vm, detach, "detach", ret == 0); + if (ret < 0) + return -1; pci = pciGetDevice(detach->source.subsys.u.pci.domain, detach->source.subsys.u.pci.bus, @@ -1715,13 +1711,11 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver, } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - return -1; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); qemuDomainObjExitMonitorWithDriver(driver, vm); - - ret = 0; + qemuDomainHostdevAudit(vm, detach, "detach", ret == 0); + if (ret < 0) + return -1; if (vm->def->nhostdevs > 1) { memmove(vm->def->hostdevs + i, -- 1.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list