]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Audit VM start/stop/suspend/resume
authorMiloslav Trmač <mitr@redhat.com>
Tue, 12 Oct 2010 11:22:03 +0000 (12:22 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 19 Oct 2010 16:31:31 +0000 (17:31 +0100)
Most operations are audited at the libvirtd level; auditing in
src/libvirt.c would result in two audit entries per operation (one in
the client, one in libvirtd).

The only exception is a domain stopping of its own will (e.g. because
the user clicks on "shutdown" inside the interface).  There can often be
no client connected at the time the domain stops, so libvirtd does not
have any virConnectPtr object on which to attach an event watch.  This
patch therefore adds auditing directly inside the qemu driver (other
drivers are not supported).

daemon/remote.c
src/qemu/qemu_driver.c

index 323f00c26407a078ec49745c59fdba540816fb91..44609c72a9fea7c7a2f078b8d3f823e1e3805f57 100644 (file)
@@ -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;
+
+    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 (virDomainRestore (conn, args->from) == -1) {
+    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;
index a9e057f9724ec3bc7ad502d075cd518799aa30d9..d1ab12854e7a3709efc54b1e4b04c44fffefe720 100644 (file)
@@ -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,