On Wed, Feb 23, 2011 at 05:03:01PM -0700, Eric Blake wrote: > * 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. > --- > > v2: updated to avoid audit messages about regular files, which never > affect cgroup ACLs > > src/qemu/qemu_audit.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- > src/qemu/qemu_audit.h | 9 ++++++++- > src/qemu/qemu_cgroup.c | 19 +++++++++++++++++++ > src/qemu/qemu_driver.c | 7 +++++++ > 4 files changed, 81 insertions(+), 2 deletions(-) > > diff --git a/src/qemu/qemu_audit.c b/src/qemu/qemu_audit.c > index f03f984..c76d49e 100644 > --- a/src/qemu/qemu_audit.c > +++ b/src/qemu/qemu_audit.c > @@ -1,7 +1,7 @@ > /* > * qemu_audit.c: QEMU audit management > * > - * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc. > + * Copyright (C) 2006-2007, 2009-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", "file", or "major" I'd be inclined to rename 'file' to 'path', because to me 'file' implies a plain file, while we're actually dealing with block devices. > + * @name: NULL for @item of "all", path for @item of "file", 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, "file") ? "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, > diff --git a/src/qemu/qemu_audit.h b/src/qemu/qemu_audit.h > index 5b5a5d3..40f4591 100644 > --- a/src/qemu/qemu_audit.h > +++ b/src/qemu/qemu_audit.h > @@ -1,7 +1,7 @@ > /* > * qemu_audit.h: QEMU audit management > * > - * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc. > + * Copyright (C) 2006-2007, 2009-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__ */ > diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c > index 49ec473..5d4f35e 100644 > --- a/src/qemu/qemu_cgroup.c > +++ b/src/qemu/qemu_cgroup.c > @@ -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", "file", 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", "file", 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", "file", > + 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", "file", 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", "file", > + 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 1916ed6..c2ddd34 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -1963,6 +1963,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, > goto endjob; > } > rc = virCgroupAllowDevicePath(cgroup, path); > + if (rc <= 0) > + qemuDomainCgroupAudit(vm, cgroup, "allow", "file", path, rc == 0); > if (rc < 0) { > virReportSystemError(-rc, > _("Unable to allow device %s for %s"), > @@ -2012,6 +2014,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, > > if (cgroup != NULL) { > rc = virCgroupDenyDevicePath(cgroup, path); > + if (rc <= 0) > + qemuDomainCgroupAudit(vm, cgroup, "deny", "file", path, rc == 0); > if (rc < 0) > VIR_WARN("Unable to deny device %s for %s %d", > path, vm->def->name, rc); > @@ -2043,6 +2047,9 @@ endjob: > > if (cgroup != NULL) { > rc = virCgroupDenyDevicePath(cgroup, path); > + if (rc <= 0) > + qemuDomainCgroupAudit(vm, cgroup, "deny", "file", path, > + rc == 0); > if (rc < 0) > VIR_WARN("Unable to deny device %s for %s: %d", > path, vm->def->name, rc); ACK if s/file/path/ Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list