[libvirt] [PATCH 2/3] audit: split cgroup audit types to allow more information

Eric Blake eblake at redhat.com
Tue Mar 8 00:08:07 UTC 2011


Device names can be manipulated, so it is better to also log
the major/minor device number corresponding to the cgroup ACL
changes that libvirt made.  This required some refactoring
of the relatively new qemu cgroup audit code.

* src/qemu/qemu_audit.c (qemuDomainCgroupAudit): Drop a parameter.
(qemuDomainCgroupAuditMajor, qemuDomainCgroupAuditPath): New
functions, to allow listing device major/minor in audit.
* src/qemu/qemu_driver.c (qemudDomainSaveFlag): Adjust callers.
* src/qemu/qemu_cgroup.c (qemuSetupDiskPathAllow)
(qemuSetupChardevCgroup, qemuSetupHostUsbDeviceCgroup)
(qemuSetupCgroup, qemuTeardownDiskPathDeny): Likewise.
---
 src/qemu/qemu_audit.c  |  104 +++++++++++++++++++++++++++++++++++++++++-------
 src/qemu/qemu_audit.h  |   14 ++++++-
 src/qemu/qemu_cgroup.c |   29 +++++++------
 src/qemu/qemu_driver.c |    8 ++--
 4 files changed, 120 insertions(+), 35 deletions(-)

diff --git a/src/qemu/qemu_audit.c b/src/qemu/qemu_audit.c
index 0f954c0..0d85fa7 100644
--- a/src/qemu/qemu_audit.c
+++ b/src/qemu/qemu_audit.c
@@ -23,6 +23,9 @@

 #include <config.h>

+#include <sys/stat.h>
+#include <sys/types.h>
+
 #include "qemu_audit.h"
 #include "virtaudit.h"
 #include "uuid.h"
@@ -176,9 +179,10 @@ cleanup:
  * @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"
+ * @extra: additional details, in the form "all",
+ * "major category=xyz maj=nn", or "path path=xyz dev=nn:mm" (the
+ * latter two are generated by qemuDomainCgroupAuditMajor and
+ * qemuDomainCgroupAuditPath).
  * @success: true if the cgroup operation succeeded
  *
  * Log an audit message about an attempted cgroup device ACL change.
@@ -186,37 +190,107 @@ cleanup:
 void qemuDomainCgroupAudit(virDomainObjPtr vm,
                            virCgroupPtr cgroup ATTRIBUTE_UNUSED,
                            const char *reason,
-                           const char *item,
-                           const char *name,
+                           const char *extra,
                            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" : "category",
-                                  name))) {
+
+    VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
+              "resrc=cgroup reason=%s %s uuid=%s class=%s",
+              reason, vmname, uuidstr, extra);
+
+    VIR_FREE(vmname);
+}
+
+/**
+ * qemuDomainCgroupAuditMajor:
+ * @vm: domain making the cgroups ACL change
+ * @cgroup: cgroup that manages the devices
+ * @reason: either "allow" or "deny"
+ * @maj: the major number of the device category
+ * @name: a textual name for that device category, alphabetic only
+ * @success: true if the cgroup operation succeeded
+ *
+ * Log an audit message about an attempted cgroup device ACL change.
+ */
+void qemuDomainCgroupAuditMajor(virDomainObjPtr vm,
+                                virCgroupPtr cgroup,
+                                const char *reason,
+                                int maj,
+                                const char *name,
+                                bool success)
+{
+    char *extra;
+
+    if (virAsprintf(&extra, "major category=%s maj=%02X", name, maj) < 0) {
+        VIR_WARN0("OOM while encoding audit message");
+        return;
+    }
+
+    qemuDomainCgroupAudit(vm, cgroup, reason, extra, success);
+
+    VIR_FREE(extra);
+}
+
+/**
+ * qemuDomainCgroupAuditPath:
+ * @vm: domain making the cgroups ACL change
+ * @cgroup: cgroup that manages the devices
+ * @reason: either "allow" or "deny"
+ * @path: the device being adjusted
+ * @success: true if the cgroup operation succeeded
+ *
+ * Log an audit message about an attempted cgroup device ACL change to
+ * a specific device.
+ */
+void qemuDomainCgroupAuditPath(virDomainObjPtr vm,
+                               virCgroupPtr cgroup,
+                               const char *reason,
+                               const char *path,
+                               bool success)
+{
+    char *detail;
+    char *extra;
+    int rc;
+
+    if (!(detail = virAuditEncode("path", path))) {
+        VIR_WARN0("OOM while encoding audit message");
+        return;
+    }
+
+#if defined major && defined minor
+    struct stat sb;
+    if (stat(path, &sb) == 0 &&
+        (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))) {
+        int maj = major(sb.st_rdev);
+        int min = minor(sb.st_rdev);
+        rc = virAsprintf(&extra, "path path=%s rdev=%02X:%02X",
+                         path, maj, min);
+    } else
+#endif
+    {
+        rc = virAsprintf(&extra, "path path=%s rdev=?", path);
+    }
+
+    if (rc < 0) {
         VIR_WARN0("OOM while encoding audit message");
         goto cleanup;
     }

-    VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
-              "resrc=cgroup reason=%s %s uuid=%s class=%s%s%s",
-              reason, vmname, uuidstr,
-              item, detail ? " " : "", detail ? detail : "");
+    qemuDomainCgroupAudit(vm, cgroup, reason, extra, success);

 cleanup:
-    VIR_FREE(vmname);
+    VIR_FREE(extra);
     VIR_FREE(detail);
 }

-
 /**
  * qemuDomainResourceAudit:
  * @vm: domain making an integer resource change
diff --git a/src/qemu/qemu_audit.h b/src/qemu/qemu_audit.h
index 247edde..500eb98 100644
--- a/src/qemu/qemu_audit.h
+++ b/src/qemu/qemu_audit.h
@@ -46,9 +46,19 @@ void qemuDomainHostdevAudit(virDomainObjPtr vm,
 void qemuDomainCgroupAudit(virDomainObjPtr vm,
                            virCgroupPtr group,
                            const char *reason,
-                           const char *item,
-                           const char *name,
+                           const char *extra,
                            bool success);
+void qemuDomainCgroupAuditMajor(virDomainObjPtr vm,
+                                virCgroupPtr group,
+                                const char *reason,
+                                int maj,
+                                const char *name,
+                                bool success);
+void qemuDomainCgroupAuditPath(virDomainObjPtr vm,
+                               virCgroupPtr group,
+                               const char *reason,
+                               const char *path,
+                               bool success);
 void qemuDomainMemoryAudit(virDomainObjPtr vm,
                            unsigned long long oldmem,
                            unsigned long long newmem,
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index e71d3fa..b911005 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -68,8 +68,8 @@ qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
     /* XXX RO vs RW */
     rc = virCgroupAllowDevicePath(data->cgroup, path);
     if (rc <= 0)
-        qemuDomainCgroupAudit(data->vm, data->cgroup, "allow", "path", path,
-                              rc == 0);
+        qemuDomainCgroupAuditPath(data->vm, data->cgroup, "allow", path,
+                                  rc == 0);
     if (rc < 0) {
         if (rc == -EACCES) { /* Get this for root squash NFS */
             VIR_DEBUG("Ignoring EACCES for %s", path);
@@ -111,8 +111,8 @@ qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
     /* XXX RO vs RW */
     rc = virCgroupDenyDevicePath(data->cgroup, path);
     if (rc <= 0)
-        qemuDomainCgroupAudit(data->vm, data->cgroup, "deny", "path", path,
-                              rc == 0);
+        qemuDomainCgroupAuditPath(data->vm, data->cgroup, "deny", path,
+                                  rc == 0);
     if (rc < 0) {
         if (rc == -EACCES) { /* Get this for root squash NFS */
             VIR_DEBUG("Ignoring EACCES for %s", path);
@@ -156,8 +156,8 @@ 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);
+        qemuDomainCgroupAuditPath(data->vm, data->cgroup, "allow",
+                                  dev->source.data.file.path, rc == 0);
     if (rc < 0) {
         virReportSystemError(-rc,
                              _("Unable to allow device %s for %s"),
@@ -179,8 +179,8 @@ 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);
+        qemuDomainCgroupAuditPath(data->vm, data->cgroup, "allow", path,
+                                  rc == 0);
     if (rc < 0) {
         virReportSystemError(-rc,
                              _("Unable to allow device %s"),
@@ -216,7 +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);
+        qemuDomainCgroupAudit(vm, cgroup, "deny", "all", rc == 0);
         if (rc != 0) {
             if (rc == -EPERM) {
                 VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
@@ -234,7 +234,8 @@ int qemuSetupCgroup(struct qemud_driver *driver,
         }

         rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
-        qemuDomainCgroupAudit(vm, cgroup, "allow", "major", "pty", rc == 0);
+        qemuDomainCgroupAuditMajor(vm, cgroup, "allow", DEVICE_PTY_MAJOR,
+                                   "pty", rc == 0);
         if (rc != 0) {
             virReportSystemError(-rc, "%s",
                                  _("unable to allow /dev/pts/ devices"));
@@ -247,8 +248,8 @@ int qemuSetupCgroup(struct qemud_driver *driver,
                driver->vncAllowHostAudio) ||
               (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL)))) {
             rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
-            qemuDomainCgroupAudit(vm, cgroup, "allow", "major", "sound",
-                                  rc == 0);
+            qemuDomainCgroupAuditMajor(vm, cgroup, "allow", DEVICE_SND_MAJOR,
+                                       "sound", rc == 0);
             if (rc != 0) {
                 virReportSystemError(-rc, "%s",
                                      _("unable to allow /dev/snd/ devices"));
@@ -259,8 +260,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);
+            qemuDomainCgroupAuditPath(vm, cgroup, "allow",
+                                      deviceACL[i], rc == 0);
             if (rc < 0 &&
                 rc != -ENOENT) {
                 virReportSystemError(-rc,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0f7cbad..cb5d7ef 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1965,7 +1965,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
         }
         rc = virCgroupAllowDevicePath(cgroup, path);
         if (rc <= 0)
-            qemuDomainCgroupAudit(vm, cgroup, "allow", "path", path, rc == 0);
+            qemuDomainCgroupAuditPath(vm, cgroup, "allow", path, rc == 0);
         if (rc < 0) {
             virReportSystemError(-rc,
                                  _("Unable to allow device %s for %s"),
@@ -2016,7 +2016,7 @@ 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);
+            qemuDomainCgroupAuditPath(vm, cgroup, "deny", path, rc == 0);
         if (rc < 0)
             VIR_WARN("Unable to deny device %s for %s %d",
                      path, vm->def->name, rc);
@@ -2049,8 +2049,8 @@ endjob:
             if (cgroup != NULL) {
                 rc = virCgroupDenyDevicePath(cgroup, path);
                 if (rc <= 0)
-                    qemuDomainCgroupAudit(vm, cgroup, "deny", "path", path,
-                                          rc == 0);
+                    qemuDomainCgroupAuditPath(vm, cgroup, "deny", path,
+                                              rc == 0);
                 if (rc < 0)
                     VIR_WARN("Unable to deny device %s for %s: %d",
                              path, vm->def->name, rc);
-- 
1.7.4




More information about the libvir-list mailing list