[libvirt] [PATCH 0/7]: Rewrite all the auditing hooks

This patch series reverts two previous commits which added auditing hooks to the daemon/remote.c dispatcher code. This is then replaced with hooks added directly to the QEMU driver code. This has the downside that auditing only works for the QEMU driver, but it is unavoidable because the dispatcher code has insufficient information to properly generate audit records. It also handles escaping of strings which contain user supplied arbitrary formatted data. It finishes up by adding auditing of disk/net resources.

Revert most of commit a8b5f9bd27d65c2ced064b9267ca31dee7ad9c86. The audit hooks will be re-added directly in the QEMU driver code in a future commit * daemon/remote.c: Remove all audit logging hooks * src/qemu/qemu_driver.c: Remove all audit logging hooks --- daemon/remote.c | 134 ++++-------------------------------------------- src/qemu/qemu_driver.c | 7 --- 2 files changed, 10 insertions(+), 131 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 50ccb3b..886d53d 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -59,7 +59,6 @@ #include "stream.h" #include "uuid.h" #include "network.h" -#include "virtaudit.h" #include "libvirt/libvirt-qemu.h" #define VIR_FROM_THIS VIR_FROM_REMOTE @@ -1216,8 +1215,6 @@ remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -1225,18 +1222,11 @@ remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainCreate(dom); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=start name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainCreate (dom) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; } - virDomainFree(dom); return 0; } @@ -1251,8 +1241,6 @@ remoteDispatchDomainCreateWithFlags (struct qemud_server *server ATTRIBUTE_UNUSE remote_domain_create_with_flags_ret *ret) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -1260,15 +1248,7 @@ remoteDispatchDomainCreateWithFlags (struct qemud_server *server ATTRIBUTE_UNUSE return -1; } - r = virDomainCreateWithFlags(dom, args->flags); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=%s name=%s uuid=%s", - (args->flags & VIR_DOMAIN_START_PAUSED) != - 0 ? "start-paused" : "start", dom->name, uuidstr); - - if (r == -1) { + if (virDomainCreateWithFlags (dom, args->flags) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -1289,20 +1269,13 @@ remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, remote_domain_create_xml_ret *ret) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; dom = virDomainCreateXML (conn, args->xml_desc, args->flags); if (dom == NULL) { - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 0, - "op=start name=? uuid=?"); remoteDispatchConnError(rerr, conn); return -1; } - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, "op=start name=%s uuid=%s", - dom->name, uuidstr); - make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1342,8 +1315,6 @@ remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -1351,13 +1322,7 @@ remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainDestroy(dom); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=stop name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainDestroy (dom) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -1842,8 +1807,6 @@ remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED r = virDomainMigratePrepare (conn, &cookie, &cookielen, uri_in, uri_out, args->flags, dname, args->resource); - /* This creates a VM, but we don't audit it until the migration succeeds - and the VM actually starts. */ if (r == -1) { VIR_FREE(uri_out); remoteDispatchConnError(rerr, conn); @@ -1876,7 +1839,7 @@ remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED { int r; virDomainPtr dom; - char *dname, uuidstr[VIR_UUID_STRING_BUFLEN]; + char *dname; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -1891,11 +1854,6 @@ remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED args->cookie.cookie_len, args->uri, args->flags, dname, args->resource); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=migrate-out name=%s uuid=%s", dom->name, uuidstr); - virDomainFree (dom); if (r == -1) { remoteDispatchConnError(rerr, conn); @@ -1915,27 +1873,18 @@ remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED, remote_domain_migrate_finish_ret *ret) { virDomainPtr ddom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; CHECK_CONN (client); - /* Note that we are not able to audit "op=migrate-in" here if - VIR_DRV_FEATURE_MIGRATION_DIRECT is used. */ ddom = virDomainMigrateFinish (conn, args->dname, args->cookie.cookie_val, args->cookie.cookie_len, args->uri, args->flags); if (ddom == NULL) { - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 0, - "op=migrate-in name=%s uuid=?", args->dname); remoteDispatchConnError(rerr, conn); return -1; } - virUUIDFormat(ddom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, - "op=migrate-in name=%s uuid=%s", ddom->name, uuidstr); - make_nonnull_domain (&ret->ddom, ddom); virDomainFree (ddom); return 0; @@ -1971,8 +1920,6 @@ remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSE uri_in, uri_out, args->flags, dname, args->resource, args->dom_xml); - /* This creates a VM, but we don't audit it until the migration succeeds - and the VM actually starts. */ if (r == -1) { remoteDispatchConnError(rerr, conn); return -1; @@ -1998,11 +1945,8 @@ remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED remote_domain_migrate_finish2_ret *ret) { virDomainPtr ddom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; CHECK_CONN (client); - /* Note that we are not able to audit "op=migrate-in" here if - VIR_DRV_FEATURE_MIGRATION_DIRECT is used. */ ddom = virDomainMigrateFinish2 (conn, args->dname, args->cookie.cookie_val, args->cookie.cookie_len, @@ -2010,16 +1954,10 @@ remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED args->flags, args->retcode); if (ddom == NULL) { - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 0, - "op=migrate-in name=%s uuid=?", args->dname); remoteDispatchConnError(rerr, conn); return -1; } - virUUIDFormat(ddom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, - "op=migrate-in name=%s uuid=%s", ddom->name, uuidstr); - make_nonnull_domain (&ret->ddom, ddom); virDomainFree (ddom); @@ -2051,8 +1989,6 @@ remoteDispatchDomainMigratePrepareTunnel(struct qemud_server *server ATTRIBUTE_U r = virDomainMigratePrepareTunnel(conn, stream->st, args->flags, dname, args->resource, args->dom_xml); - /* This creates a VM, but we don't audit it until the migration succeeds - and the VM actually starts. */ if (r == -1) { remoteFreeClientStream(client, stream); remoteDispatchConnError(rerr, conn); @@ -2259,15 +2195,8 @@ remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED, remote_domain_restore_args *args, void *ret ATTRIBUTE_UNUSED) { - int r; - - r = virDomainRestore(conn, args->from); - /* We don't have enough information! */ - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=start name=? uuid=? file=%s", args->from); - - if (r == -1) { + if (virDomainRestore (conn, args->from) == -1) { remoteDispatchConnError(rerr, conn); return -1; } @@ -2285,8 +2214,6 @@ remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -2294,13 +2221,7 @@ remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainResume(dom); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, - "op=resume name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainResume (dom) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2319,8 +2240,6 @@ remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -2328,13 +2247,7 @@ remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainSave(dom, args->to); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=stop name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainSave (dom, args->to) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2353,7 +2266,6 @@ remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -2361,17 +2273,7 @@ remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainCoreDump(dom, args->to, args->flags); - - if ((args->flags & VIR_DUMP_CRASH) != 0) { - char uuidstr[VIR_UUID_STRING_BUFLEN]; - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=stop name=%s uuid=%s", dom->name, uuidstr); - } - - if (r == -1) { + if (virDomainCoreDump (dom, args->to, args->flags) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2756,8 +2658,6 @@ remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -2765,13 +2665,7 @@ remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainSuspend(dom); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, - "op=suspend name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainSuspend (dom) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2883,8 +2777,6 @@ remoteDispatchDomainManagedSave (struct qemud_server *server ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - int r; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -2892,13 +2784,7 @@ remoteDispatchDomainManagedSave (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - r = virDomainManagedSave(dom, args->flags); - - virUUIDFormat(dom->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, r != -1, - "op=stop name=%s uuid=%s", dom->name, uuidstr); - - if (r == -1) { + if (virDomainManagedSave (dom, args->flags) == -1) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ae1d833..923c57d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -80,7 +80,6 @@ #include "domain_nwfilter.h" #include "hooks.h" #include "storage_file.h" -#include "virtaudit.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -909,15 +908,9 @@ qemuHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, int hasError) { struct qemud_driver *driver = qemu_driver; virDomainEventPtr event = NULL; - char uuidstr[VIR_UUID_STRING_BUFLEN]; VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name); - /* If the domain stops of its own will, we wouldn't audit it otherwise. */ - virUUIDFormat(vm->def->uuid, uuidstr); - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, 1, - "op=stopped name=%s uuid=%s", vm->def->name, uuidstr); - virDomainObjLock(vm); event = virDomainEventNewFromObj(vm, -- 1.7.2.3

This reverts commit b8e2de8899594edcd78b3a7cb1b39b89bbed2891 The hooks will be re-added in the QEMU driver itself. * src/security/security_selinux.c: Remove audit hooks --- src/security/security_selinux.c | 22 ++++------------------ 1 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 0995d67..a9dd836 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -28,8 +28,6 @@ #include "pci.h" #include "hostusb.h" #include "storage_file.h" -#include "uuid.h" -#include "virtaudit.h" #define VIR_FROM_THIS VIR_FROM_SECURITY @@ -162,22 +160,20 @@ SELinuxGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, virDomainObjPtr vm) { int rc = -1; - char mcs[1024], uuidstr[VIR_UUID_STRING_BUFLEN]; + char mcs[1024]; char *scontext = NULL; int c1 = 0; int c2 = 0; - if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) { - rc = 0; - goto done; - } + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) + return 0; if (vm->def->seclabel.label || vm->def->seclabel.model || vm->def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); - goto done; + return rc; } do { @@ -221,16 +217,6 @@ err: VIR_FREE(vm->def->seclabel.model); done: VIR_FREE(scontext); - - virUUIDFormat(vm->def->uuid, uuidstr); - /* The derived socket context is not audited. */ -#define STR(X) ((X) != NULL ? (X) : "?") - VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_ID, rc == 0, - "name=%s uuid=%s process-context=%s image-context=%s", - vm->def->name, uuidstr, STR(vm->def->seclabel.label), - STR(vm->def->seclabel.imagelabel)); -#undef STR - return rc; } -- 1.7.2.3

Add a helper API for ecscaping the value in audit log messages * src/util/virtaudit.h, src/util/virtaudit.c, src/libvirt_private.syms: Add virAuditEncode --- src/libvirt_private.syms | 1 + src/util/virtaudit.c | 12 ++++++++++++ src/util/virtaudit.h | 4 ++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1a71e79..7ceb016 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -794,6 +794,7 @@ virUUIDParse; # virtaudit.h virAuditClose; +virAuditEncode; virAuditLog; virAuditOpen; virAuditSend; diff --git a/src/util/virtaudit.c b/src/util/virtaudit.c index 3226961..d568660 100644 --- a/src/util/virtaudit.c +++ b/src/util/virtaudit.c @@ -136,3 +136,15 @@ void virAuditClose(void) close(auditfd); #endif } + +char *virAuditEncode(const char *key, const char *value) +{ +#if HAVE_AUDIT + return audit_encode_nv_string(key, value, 0); +#else + char *str; + if (virAsprintf(&str, "%s=%s", key, value) < 0) + return NULL; + return str; +#endif +} diff --git a/src/util/virtaudit.h b/src/util/virtaudit.h index f0d9cd7..37046f2 100644 --- a/src/util/virtaudit.h +++ b/src/util/virtaudit.h @@ -41,6 +41,8 @@ void virAuditSend(const char *file, const char *func, size_t linenr, enum virAuditRecordType type, bool success, const char *fmt, ...); +char *virAuditEncode(const char *key, const char *value); + void virAuditClose(void); # define VIR_AUDIT(type, success, ...) \ @@ -51,5 +53,7 @@ void virAuditClose(void); virAuditSend(__FILE__, __func__, __LINE__, \ clienttty, clientaddr, type, success, __VA_ARGS__); +# define VIR_AUDIT_STR(str) \ + ((str) ? (str) : "?") #endif /* __LIBVIRT_AUDIT_H__ */ -- 1.7.2.3

* src/util/virtaudit.h: Add printf format attribute annotation --- src/util/virtaudit.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/util/virtaudit.h b/src/util/virtaudit.h index 37046f2..6c4deeb 100644 --- a/src/util/virtaudit.h +++ b/src/util/virtaudit.h @@ -39,7 +39,8 @@ void virAuditLog(int enabled); void virAuditSend(const char *file, const char *func, size_t linenr, const char *clienttty, const char *clientaddr, enum virAuditRecordType type, bool success, - const char *fmt, ...); + const char *fmt, ...) + ATTRIBUTE_FMT_PRINTF(8, 9); char *virAuditEncode(const char *key, const char *value); -- 1.7.2.3

Add audit hooks to report all start and stop events on QEMU guest domains. * src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 923c57d..980d9d4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -80,6 +80,7 @@ #include "domain_nwfilter.h" #include "hooks.h" #include "storage_file.h" +#include "virtaudit.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -165,6 +166,9 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, virDomainObjPtr vm, int migrated); +static void qemuDomainStartAudit(virDomainObjPtr vm, const char *reason, bool success); +static void qemuDomainStopAudit(virDomainObjPtr vm, const char *reason); + static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemuDetectVcpuPIDs(struct qemud_driver *driver, @@ -920,6 +924,8 @@ qemuHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); qemudShutdownVMDaemon(driver, vm, 0); + qemuDomainStopAudit(vm, hasError ? "failed" : "shutdown"); + if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); else @@ -3662,6 +3668,36 @@ static int qemuDomainSnapshotSetActive(virDomainObjPtr vm, static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm, char *snapshotDir); +static void qemuDomainLifecycleAudit(virDomainObjPtr vm, + const char *op, + const char *reason, + bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *vmname; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, success, + "op=%s reason=%s %s uuid=%s", op, reason, vmname, uuidstr); + + VIR_FREE(vmname); +} + +static void qemuDomainStartAudit(virDomainObjPtr vm, const char *reason, bool success) +{ + qemuDomainLifecycleAudit(vm, "start", reason, success); +} + +static void qemuDomainStopAudit(virDomainObjPtr vm, const char *reason) +{ + qemuDomainLifecycleAudit(vm, "stop", reason, true); +} + static int qemudStartVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm, @@ -4598,6 +4634,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, if (qemudStartVMDaemon(conn, driver, vm, NULL, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1, NULL) < 0) { + qemuDomainStartAudit(vm, "booted", false); if (qemuDomainObjEndJob(vm) > 0) virDomainRemoveInactive(&driver->domains, vm); @@ -4608,6 +4645,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_BOOTED); + qemuDomainStartAudit(vm, "booted", true); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -4835,6 +4873,8 @@ static int qemudDomainDestroy(virDomainPtr dom) { event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_DESTROYED); + qemuDomainStopAudit(vm, "destroyed"); + if (!vm->persistent) { if (qemuDomainObjEndJob(vm) > 0) virDomainRemoveInactive(&driver->domains, @@ -5536,6 +5576,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, /* Shut it down */ qemudShutdownVMDaemon(driver, vm, 0); + qemuDomainStopAudit(vm, "saved"); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_SAVED); @@ -5849,6 +5890,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, endjob: if ((ret == 0) && (flags & VIR_DUMP_CRASH)) { qemudShutdownVMDaemon(driver, vm, 0); + qemuDomainStopAudit(vm, "crashed"); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_CRASHED); @@ -6719,12 +6761,15 @@ qemudDomainSaveImageStartVM(virConnectPtr conn, } } - if (ret < 0) + if (ret < 0) { + qemuDomainStartAudit(vm, "restored", false); goto out; + } event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_RESTORED); + qemuDomainStartAudit(vm, "restored", true); if (event) qemuDomainEventQueue(driver, event); @@ -7151,7 +7196,8 @@ static int qemudDomainObjStart(virConnectPtr conn, } ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1, NULL); - if (ret != -1) { + qemuDomainStartAudit(vm, "booted", ret >= 0); + if (ret >= 0) { virDomainEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, @@ -10900,6 +10946,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, -1, NULL); VIR_FREE(migrateFrom); if (internalret < 0) { + qemuDomainStartAudit(vm, "migrated", false); /* Note that we don't set an error here because qemudStartVMDaemon * should have already done that. */ @@ -10912,6 +10959,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, qemust = qemuStreamMigOpen(st, unixfile); if (qemust == NULL) { + qemuDomainStartAudit(vm, "migrated", false); qemudShutdownVMDaemon(driver, vm, 0); if (!vm->persistent) { if (qemuDomainObjEndJob(vm) > 0) @@ -10927,6 +10975,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, st->driver = &qemuStreamMigDrv; st->privateData = qemust; + qemuDomainStartAudit(vm, "migrated", true); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); @@ -11142,6 +11191,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port); if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, true, -1, NULL) < 0) { + qemuDomainStartAudit(vm, "migrated", false); /* Note that we don't set an error here because qemudStartVMDaemon * should have already done that. */ @@ -11153,6 +11203,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, goto endjob; } + qemuDomainStartAudit(vm, "migrated", true); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); @@ -11710,6 +11761,7 @@ qemudDomainMigratePerform (virDomainPtr dom, /* Clean up the source domain. */ qemudShutdownVMDaemon(driver, vm, 1); + qemuDomainStopAudit(vm, "migrated"); resume = 0; event = virDomainEventNewFromObj(vm, @@ -11879,6 +11931,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, } } else { qemudShutdownVMDaemon(driver, vm, 1); + qemuDomainStopAudit(vm, "failed"); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FAILED); @@ -12708,6 +12761,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL, false, -1, NULL); + qemuDomainStartAudit(vm, "from-snapshot", rc >= 0); if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0) goto endjob; if (rc < 0) @@ -12747,6 +12801,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, if (virDomainObjIsActive(vm)) { qemudShutdownVMDaemon(driver, vm, 0); + qemuDomainStopAudit(vm, "from-snapshot"); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT); -- 1.7.2.3

On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time. beside that generic issue, patch looks fine, ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Oct 27, 2010 at 04:33:03PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs
One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time.
Quite possibly, but I believe audit people would describe this scenario as a feature, rather than a bug :-) Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Oct 27, 2010 at 03:39:02PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:33:03PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs
One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time.
Quite possibly, but I believe audit people would describe this scenario as a feature, rather than a bug :-)
Grumpf ... :-( I'm fine with allowing code which can monitor/affect normal operation behaviour but it must be off by default then. There is no default set in daemon/libvirtd.conf for audit_level, I would like to see an assumed value of 0 then, is that the case ? Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Oct 27, 2010 at 04:46:30PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 03:39:02PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:33:03PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs
One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time.
Quite possibly, but I believe audit people would describe this scenario as a feature, rather than a bug :-)
Grumpf ... :-( I'm fine with allowing code which can monitor/affect normal operation behaviour but it must be off by default then. There is no default set in daemon/libvirtd.conf for audit_level, I would like to see an assumed value of 0 then, is that the case ?
The default is that libvirt auditing will be enabled, if auditing is enabled on the OS. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Oct 27, 2010 at 03:48:59PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:46:30PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 03:39:02PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:33:03PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs
One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time.
Quite possibly, but I believe audit people would describe this scenario as a feature, rather than a bug :-)
Grumpf ... :-( I'm fine with allowing code which can monitor/affect normal operation behaviour but it must be off by default then. There is no default set in daemon/libvirtd.conf for audit_level, I would like to see an assumed value of 0 then, is that the case ?
The default is that libvirt auditing will be enabled, if auditing is enabled on the OS.
Grumpf :-( , another randomization of the default behaviour of the library ... now each time we will have a bug reported, we will have to wonder if there isn't some audit rules doing some trick. At least it should now change the behaviour, it can just slow or stop operations on that domain, right ? Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Oct 27, 2010 at 04:55:10PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 03:48:59PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:46:30PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 03:39:02PM +0100, Daniel P. Berrange wrote:
On Wed, Oct 27, 2010 at 04:33:03PM +0200, Daniel Veillard wrote:
On Wed, Oct 27, 2010 at 12:36:15PM +0100, Daniel P. Berrange wrote:
Add audit hooks to report all start and stop events on QEMU guest domains.
* src/qemu/qemu_driver.c: Audit start/stop events --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 2 deletions(-)
patch 1-4 trivial ACKs
One of the differences if we lock down in the driver (beside the redundancy that will be needed) is that we end up writing to the audit system deep in the driver with all the locks needed for operation. Is there a risk of being blocked while writing to the audit system ? This could potentially be a problem because all operations on the domain would be stopped during that time.
Quite possibly, but I believe audit people would describe this scenario as a feature, rather than a bug :-)
Grumpf ... :-( I'm fine with allowing code which can monitor/affect normal operation behaviour but it must be off by default then. There is no default set in daemon/libvirtd.conf for audit_level, I would like to see an assumed value of 0 then, is that the case ?
The default is that libvirt auditing will be enabled, if auditing is enabled on the OS.
Grumpf :-( , another randomization of the default behaviour of the library ... now each time we will have a bug reported, we will have to wonder if there isn't some audit rules doing some trick. At least it should now change the behaviour, it can just slow or stop operations on that domain,
I really don't think there's anything worth worrying about here. Auditing is only going to block in scenarios where you're already doomed, like 100% disk full on /var/log Daniel. -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Add auditing of the allocated security label in the QEMU driver VM startup code * src/qemu/qemu_driver.c: Audit security label --- src/qemu/qemu_driver.c | 32 ++++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 980d9d4..8db5e7a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3698,6 +3698,27 @@ static void qemuDomainStopAudit(virDomainObjPtr vm, const char *reason) qemuDomainLifecycleAudit(vm, "stop", reason, true); } +static void qemuDomainSecurityLabelAudit(virDomainObjPtr vm, bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *vmname; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_ID, success, + "%s uuid=%s vm-ctx=%s img-ctx=%s", + vmname, uuidstr, + VIR_AUDIT_STR(vm->def->seclabel.label), + VIR_AUDIT_STR(vm->def->seclabel.imagelabel)); + + VIR_FREE(vmname); +} + + static int qemudStartVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm, @@ -3752,10 +3773,13 @@ static int qemudStartVMDaemon(virConnectPtr conn, then generate a security label for isolation */ DEBUG0("Generating domain security label (if required)"); if (driver->securityDriver && - driver->securityDriver->domainGenSecurityLabel && - driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, - vm) < 0) - goto cleanup; + driver->securityDriver->domainGenSecurityLabel) { + ret = driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, + vm); + qemuDomainSecurityLabelAudit(vm, ret >= 0); + if (ret < 0) + goto cleanup; + } DEBUG0("Generating setting domain security labels (if required)"); if (driver->securityDriver && -- 1.7.2.3

On Wed, Oct 27, 2010 at 12:36:16PM +0100, Daniel P. Berrange wrote:
Add auditing of the allocated security label in the QEMU driver VM startup code
* src/qemu/qemu_driver.c: Audit security label --- src/qemu/qemu_driver.c | 32 ++++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 980d9d4..8db5e7a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3698,6 +3698,27 @@ static void qemuDomainStopAudit(virDomainObjPtr vm, const char *reason) qemuDomainLifecycleAudit(vm, "stop", reason, true); }
+static void qemuDomainSecurityLabelAudit(virDomainObjPtr vm, bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *vmname; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_ID, success, + "%s uuid=%s vm-ctx=%s img-ctx=%s", + vmname, uuidstr, + VIR_AUDIT_STR(vm->def->seclabel.label), + VIR_AUDIT_STR(vm->def->seclabel.imagelabel)); + + VIR_FREE(vmname); +} + + static int qemudStartVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm, @@ -3752,10 +3773,13 @@ static int qemudStartVMDaemon(virConnectPtr conn, then generate a security label for isolation */ DEBUG0("Generating domain security label (if required)"); if (driver->securityDriver && - driver->securityDriver->domainGenSecurityLabel && - driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, - vm) < 0) - goto cleanup; + driver->securityDriver->domainGenSecurityLabel) { + ret = driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, + vm); + qemuDomainSecurityLabelAudit(vm, ret >= 0); + if (ret < 0) + goto cleanup; + }
DEBUG0("Generating setting domain security labels (if required)"); if (driver->securityDriver &&
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Add auditing of all initial disk/net assignments to QEMU guests at startup. Add auditing for all hotplug & unplug events and disk media changes. * src/qemu/qemu_driver.c: Add disk/net resource auditing --- src/qemu/qemu_driver.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 111 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8db5e7a..b119ca1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3668,6 +3668,79 @@ static int qemuDomainSnapshotSetActive(virDomainObjPtr vm, static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm, char *snapshotDir); +static void qemuDomainDiskAudit(virDomainObjPtr vm, + virDomainDiskDefPtr oldDef, + virDomainDiskDefPtr newDef, + const char *reason, + bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *vmname; + char *oldsrc = NULL; + char *newsrc = NULL; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + if (!(oldsrc = virAuditEncode("old-disk", + oldDef && oldDef->src ? + oldDef->src : "?"))) { + VIR_WARN0("OOM while encoding audit message"); + goto cleanup; + } + if (!(newsrc = virAuditEncode("new-disk", + newDef && newDef->src ? + newDef->src : "?"))) { + VIR_WARN0("OOM while encoding audit message"); + goto cleanup; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success, + "resrc=disk reason=%s %s uuid=%s %s %s", + reason, vmname, uuidstr, + oldsrc, newsrc); + +cleanup: + VIR_FREE(vmname); + VIR_FREE(oldsrc); + VIR_FREE(newsrc); +} + + +static void qemuDomainNetAudit(virDomainObjPtr vm, + virDomainNetDefPtr oldDef, + virDomainNetDefPtr newDef, + const char *reason, + bool success) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char newMacstr[VIR_MAC_STRING_BUFLEN]; + char oldMacstr[VIR_MAC_STRING_BUFLEN]; + char *vmname; + + virUUIDFormat(vm->def->uuid, uuidstr); + if (oldDef) + virFormatMacAddr(oldDef->mac, oldMacstr); + if (newDef) + virFormatMacAddr(newDef->mac, newMacstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { + VIR_WARN0("OOM while encoding audit message"); + return; + } + + VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success, + "resrc=net reason=%s %s uuid=%s old-net='%s' new-net='%s'", + reason, vmname, uuidstr, + oldDef ? oldMacstr : "?", + newDef ? newMacstr : "?"); + + VIR_FREE(vmname); +} + + static void qemuDomainLifecycleAudit(virDomainObjPtr vm, const char *op, const char *reason, @@ -3677,6 +3750,7 @@ static void qemuDomainLifecycleAudit(virDomainObjPtr vm, char *vmname; virUUIDFormat(vm->def->uuid, uuidstr); + if (!(vmname = virAuditEncode("vm", vm->def->name))) { VIR_WARN0("OOM while encoding audit message"); return; @@ -3690,6 +3764,19 @@ static void qemuDomainLifecycleAudit(virDomainObjPtr vm, static void qemuDomainStartAudit(virDomainObjPtr vm, const char *reason, bool success) { + int i; + + for (i = 0 ; i < vm->def->ndisks ; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + if (disk->src) /* Skips CDROM without media initially inserted */ + qemuDomainDiskAudit(vm, NULL, disk, "start", true); + } + + for (i = 0 ; i < vm->def->nnets ; i++) { + virDomainNetDefPtr net = vm->def->nets[i]; + qemuDomainNetAudit(vm, NULL, net, "start", true); + } + qemuDomainLifecycleAudit(vm, "start", reason, success); } @@ -7565,6 +7652,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, origdisk, disk, "update", ret >= 0); + if (ret < 0) goto error; @@ -7664,6 +7753,8 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, NULL, disk, "attach", ret >= 0); + if (ret < 0) goto error; @@ -7899,6 +7990,8 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, NULL, disk, "attach", ret >= 0); + if (ret < 0) goto error; @@ -7984,6 +8077,8 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, NULL, disk, "attach", ret >= 0); + if (ret < 0) goto error; @@ -8118,11 +8213,13 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { if (qemuMonitorAddNetdev(priv->mon, netstr) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, NULL, net, "attach", false); goto try_tapfd_close; } } else { if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, NULL, net, "attach", false); goto try_tapfd_close; } } @@ -8150,12 +8247,14 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, NULL, net, "attach", false); goto try_remove; } } else { if (qemuMonitorAddPCINetwork(priv->mon, nicstr, &guestAddr) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, NULL, net, "attach", false); goto try_remove; } net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -8163,6 +8262,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, NULL, net, "attach", true); + ret = 0; vm->def->nets[vm->def->nnets++] = net; @@ -8860,6 +8961,8 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, detach, NULL, "detach", ret >= 0); + if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src); @@ -8928,6 +9031,8 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainDiskAudit(vm, detach, NULL, "detach", ret >= 0); + virDomainDiskRemove(vm->def, i); virDomainDiskDefFree(detach); @@ -9081,12 +9186,14 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver, if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { qemuDomainObjExitMonitor(vm); + qemuDomainNetAudit(vm, detach, NULL, "detach", false); goto cleanup; } } else { if (qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, detach, NULL, "detach", false); goto cleanup; } } @@ -9095,16 +9202,20 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver, (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, detach, NULL, "detach", false); goto cleanup; } } else { if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, detach, NULL, "detach", false); goto cleanup; } } qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainNetAudit(vm, detach, NULL, "detach", true); + if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) VIR_WARN0("Unable to release PCI address on NIC"); -- 1.7.2.3

On Wed, Oct 27, 2010 at 12:36:17PM +0100, Daniel P. Berrange wrote:
Add auditing of all initial disk/net assignments to QEMU guests at startup. Add auditing for all hotplug & unplug events and disk media changes.
* src/qemu/qemu_driver.c: Add disk/net resource auditing --- src/qemu/qemu_driver.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8db5e7a..b119ca1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3668,6 +3668,79 @@ static int qemuDomainSnapshotSetActive(virDomainObjPtr vm, static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm, char *snapshotDir);
ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard