]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
audit: add qemu hooks for auditing cgroup events
authorEric Blake <eblake@redhat.com>
Wed, 16 Feb 2011 02:35:43 +0000 (19:35 -0700)
committerEric Blake <eblake@redhat.com>
Thu, 24 Feb 2011 20:32:15 +0000 (13:32 -0700)
* src/qemu/qemu_audit.h (qemuDomainCgroupAudit): New prototype.
* src/qemu/qemu_audit.c (qemuDomainCgroupAudit): Implement it.
* src/qemu/qemu_driver.c (qemudDomainSaveFlag): Add audit.
* src/qemu/qemu_cgroup.c (qemuSetupDiskPathAllow)
(qemuSetupChardevCgroup, qemuSetupHostUsbDeviceCgroup)
(qemuSetupCgroup, qemuTeardownDiskPathDeny): Likewise.

src/qemu/qemu_audit.c
src/qemu/qemu_audit.h
src/qemu/qemu_cgroup.c
src/qemu/qemu_driver.c

index f03f984b17b6790a29a8d67bd08486f63ea2a5b5..76dacf7639d6aa318f89fea73cdcebb6b266599e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * qemu_audit.c: QEMU audit management
  *
- * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2006-2011 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -102,6 +102,52 @@ void qemuDomainNetAudit(virDomainObjPtr vm,
 }
 
 
+/**
+ * qemuDomainCgroupAudit:
+ * @vm: domain making the cgroups ACL change
+ * @cgroup: cgroup that manages the devices
+ * @reason: either "allow" or "deny"
+ * @item: one of "all", "path", or "major"
+ * @name: NULL for @item of "all", device path for @item of "path", and
+ * string describing major device type for @item of "major"
+ * @success: true if the cgroup operation succeeded
+ *
+ * Log an audit message about an attempted cgroup device ACL change.
+ */
+void qemuDomainCgroupAudit(virDomainObjPtr vm,
+                           virCgroupPtr cgroup ATTRIBUTE_UNUSED,
+                           const char *reason,
+                           const char *item,
+                           const char *name,
+                           bool success)
+{
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    char *vmname;
+    char *detail = NULL;
+
+    virUUIDFormat(vm->def->uuid, uuidstr);
+    if (!(vmname = virAuditEncode("vm", vm->def->name))) {
+        VIR_WARN0("OOM while encoding audit message");
+        return;
+    }
+    if (name &&
+        !(detail = virAuditEncode(STREQ(item, "path") ? "path" : "type",
+                                  name))) {
+        VIR_WARN0("OOM while encoding audit message");
+        goto cleanup;
+    }
+
+    VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
+              "resrc=cgroup reason=%s %s uuid=%s item=%s%s%s",
+              reason, vmname, uuidstr,
+              item, detail ? " " : "", detail ? detail : "");
+
+cleanup:
+    VIR_FREE(vmname);
+    VIR_FREE(detail);
+}
+
+
 static void qemuDomainLifecycleAudit(virDomainObjPtr vm,
                                      const char *op,
                                      const char *reason,
index 5b5a5d3ab4f5078f35d404631ae189f0e46908f3..da18eb45140dd4c41aa089f14e04b288c314ee86 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * qemu_audit.h: QEMU audit management
  *
- * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2006-2011 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
 # define __QEMU_AUDIT_H__
 
 # include "domain_conf.h"
+# include "cgroup.h"
 
 void qemuDomainStartAudit(virDomainObjPtr vm, const char *reason, bool success);
 void qemuDomainStopAudit(virDomainObjPtr vm, const char *reason);
@@ -38,6 +39,12 @@ void qemuDomainNetAudit(virDomainObjPtr vm,
                         virDomainNetDefPtr newDef,
                         const char *reason,
                         bool success);
+void qemuDomainCgroupAudit(virDomainObjPtr vm,
+                           virCgroupPtr group,
+                           const char *reason,
+                           const char *item,
+                           const char *name,
+                           bool success);
 void qemuDomainSecurityLabelAudit(virDomainObjPtr vm, bool success);
 
 #endif /* __QEMU_AUDIT_H__ */
index 49ec473a72812c17e07fc76ce2892092f4991f16..b39b5e13bd6fabee03c487ddd01f6b1d39af7870 100644 (file)
@@ -29,6 +29,7 @@
 #include "memory.h"
 #include "virterror_internal.h"
 #include "util.h"
+#include "qemu_audit.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -66,6 +67,9 @@ qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
     VIR_DEBUG("Process path %s for disk", path);
     /* XXX RO vs RW */
     rc = virCgroupAllowDevicePath(data->cgroup, path);
+    if (rc <= 0)
+        qemuDomainCgroupAudit(data->vm, data->cgroup, "allow", "path", path,
+                              rc == 0);
     if (rc < 0) {
         if (rc == -EACCES) { /* Get this for root squash NFS */
             VIR_DEBUG("Ignoring EACCES for %s", path);
@@ -106,6 +110,9 @@ qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
     VIR_DEBUG("Process path %s for disk", path);
     /* XXX RO vs RW */
     rc = virCgroupDenyDevicePath(data->cgroup, path);
+    if (rc <= 0)
+        qemuDomainCgroupAudit(data->vm, data->cgroup, "deny", "path", path,
+                              rc == 0);
     if (rc < 0) {
         if (rc == -EACCES) { /* Get this for root squash NFS */
             VIR_DEBUG("Ignoring EACCES for %s", path);
@@ -148,6 +155,9 @@ qemuSetupChardevCgroup(virDomainDefPtr def,
 
     VIR_DEBUG("Process path '%s' for disk", dev->source.data.file.path);
     rc = virCgroupAllowDevicePath(data->cgroup, dev->source.data.file.path);
+    if (rc < 0)
+        qemuDomainCgroupAudit(data->vm, data->cgroup, "allow", "path",
+                              dev->source.data.file.path, rc == 0);
     if (rc < 0) {
         virReportSystemError(-rc,
                              _("Unable to allow device %s for %s"),
@@ -168,6 +178,9 @@ int qemuSetupHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED,
 
     VIR_DEBUG("Process path '%s' for USB device", path);
     rc = virCgroupAllowDevicePath(data->cgroup, path);
+    if (rc <= 0)
+        qemuDomainCgroupAudit(data->vm, data->cgroup, "allow", "path", path,
+                              rc == 0);
     if (rc < 0) {
         virReportSystemError(-rc,
                              _("Unable to allow device %s"),
@@ -203,6 +216,7 @@ int qemuSetupCgroup(struct qemud_driver *driver,
     if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
         qemuCgroupData data = { vm, cgroup };
         rc = virCgroupDenyAllDevices(cgroup);
+        qemuDomainCgroupAudit(vm, cgroup, "deny", "all", NULL, rc == 0);
         if (rc != 0) {
             if (rc == -EPERM) {
                 VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
@@ -220,6 +234,7 @@ int qemuSetupCgroup(struct qemud_driver *driver,
         }
 
         rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
+        qemuDomainCgroupAudit(vm, cgroup, "allow", "major", "pty", rc == 0);
         if (rc != 0) {
             virReportSystemError(-rc, "%s",
                                  _("unable to allow /dev/pts/ devices"));
@@ -228,6 +243,8 @@ int qemuSetupCgroup(struct qemud_driver *driver,
 
         if (vm->def->nsounds) {
             rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
+            qemuDomainCgroupAudit(vm, cgroup, "allow", "major", "sound",
+                                  rc == 0);
             if (rc != 0) {
                 virReportSystemError(-rc, "%s",
                                      _("unable to allow /dev/snd/ devices"));
@@ -238,6 +255,8 @@ int qemuSetupCgroup(struct qemud_driver *driver,
         for (i = 0; deviceACL[i] != NULL ; i++) {
             rc = virCgroupAllowDevicePath(cgroup,
                                           deviceACL[i]);
+            qemuDomainCgroupAudit(vm, cgroup, "allow", "path",
+                                  deviceACL[i], rc == 0);
             if (rc < 0 &&
                 rc != -ENOENT) {
                 virReportSystemError(-rc,
index ebbc8ddbad1b24a3888a49303801d455defc865e..72e930cc5e10f5726d1af76d7ce8f9cb91def552 100644 (file)
@@ -1962,6 +1962,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
             goto endjob;
         }
         rc = virCgroupAllowDevicePath(cgroup, path);
+        if (rc <= 0)
+            qemuDomainCgroupAudit(vm, cgroup, "allow", "path", path, rc == 0);
         if (rc < 0) {
             virReportSystemError(-rc,
                                  _("Unable to allow device %s for %s"),
@@ -2011,6 +2013,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
 
     if (cgroup != NULL) {
         rc = virCgroupDenyDevicePath(cgroup, path);
+        if (rc <= 0)
+            qemuDomainCgroupAudit(vm, cgroup, "deny", "path", path, rc == 0);
         if (rc < 0)
             VIR_WARN("Unable to deny device %s for %s %d",
                      path, vm->def->name, rc);
@@ -2042,6 +2046,9 @@ endjob:
 
             if (cgroup != NULL) {
                 rc = virCgroupDenyDevicePath(cgroup, path);
+                if (rc <= 0)
+                    qemuDomainCgroupAudit(vm, cgroup, "deny", "path", path,
+                                          rc == 0);
                 if (rc < 0)
                     VIR_WARN("Unable to deny device %s for %s: %d",
                              path, vm->def->name, rc);