diff --git a/daemon/remote.c b/daemon/remote.c index 323f00c264..44609c72a9 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -57,6 +57,8 @@ #include "memory.h" #include "util.h" #include "stream.h" +#include "uuid.h" +#include "virtaudit.h" #include "libvirt/libvirt-qemu.h" #define VIR_FROM_THIS VIR_FROM_REMOTE @@ -1213,6 +1215,8 @@ 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) { @@ -1220,11 +1224,18 @@ remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainCreate (dom) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; } + virDomainFree(dom); return 0; } @@ -1239,6 +1250,8 @@ 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) { @@ -1246,7 +1259,15 @@ remoteDispatchDomainCreateWithFlags (struct qemud_server *server ATTRIBUTE_UNUSE return -1; } - if (virDomainCreateWithFlags (dom, args->flags) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -1267,13 +1288,20 @@ 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); @@ -1313,6 +1341,8 @@ 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) { @@ -1320,7 +1350,13 @@ remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainDestroy (dom) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -1805,6 +1841,8 @@ 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); @@ -1837,7 +1875,7 @@ remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED { int r; virDomainPtr dom; - char *dname; + char *dname, uuidstr[VIR_UUID_STRING_BUFLEN]; dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { @@ -1852,6 +1890,11 @@ 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); @@ -1871,18 +1914,27 @@ 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; @@ -1918,6 +1970,8 @@ 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; @@ -1943,8 +1997,11 @@ 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, @@ -1952,10 +2009,16 @@ 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); @@ -1987,6 +2050,8 @@ 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); @@ -2168,6 +2233,8 @@ remoteDispatchDomainReboot (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) { @@ -2193,8 +2260,15 @@ remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED, remote_domain_restore_args *args, void *ret ATTRIBUTE_UNUSED) { + int r; - if (virDomainRestore (conn, args->from) == -1) { + 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) { remoteDispatchConnError(rerr, conn); return -1; } @@ -2219,7 +2293,13 @@ remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainResume (dom) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2238,6 +2318,8 @@ 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) { @@ -2245,7 +2327,13 @@ remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainSave (dom, args->to) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2264,6 +2352,7 @@ 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) { @@ -2271,7 +2360,17 @@ remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainCoreDump (dom, args->to, args->flags) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2656,6 +2755,8 @@ 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) { @@ -2663,7 +2764,13 @@ remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainSuspend (dom) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; @@ -2775,6 +2882,8 @@ 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) { @@ -2782,7 +2891,13 @@ remoteDispatchDomainManagedSave (struct qemud_server *server ATTRIBUTE_UNUSED, return -1; } - if (virDomainManagedSave (dom, args->flags) == -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) { virDomainFree(dom); remoteDispatchConnError(rerr, conn); return -1; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a9e057f972..d1ab12854e 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 @@ -908,8 +909,15 @@ 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,