mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-13 00:46:03 -06:00
Audit VM start/stop/suspend/resume
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).
This commit is contained in:
parent
8f680ad3b8
commit
a8b5f9bd27
135
daemon/remote.c
135
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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user