[libvirt] [PATCHv2 3/5] audit: add qemu hooks for auditing cgroup events
Daniel P. Berrange
berrange at redhat.com
Thu Feb 24 10:08:34 UTC 2011
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 :|
More information about the libvir-list
mailing list