[libvirt] [PATCH 05/19] Add an SELinux access control driver

Daniel P. Berrange berrange at redhat.com
Thu May 9 13:26:08 UTC 2013


From: "Daniel P. Berrange" <berrange at redhat.com>

Introduce an access control driver that uses the SELinux
framework for validating API authorization. Each libvirt
object is represented as a new class in SELinux policy,
along with all permissions.

The actual policy is not included here, it has to be
part of the core SELinux policy dist, since you can't
define new object classes/permissions in external loadable
modules

As well as going to the audit system, all SELinux AVC
denials also get reported in libvirtd system logs

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 m4/virt-compile-warnings.m4         |   1 +
 m4/virt-selinux.m4                  |   2 +
 po/POTFILES.in                      |   1 +
 src/Makefile.am                     |   9 +
 src/access/viraccessdriverselinux.c | 565 ++++++++++++++++++++++++++++++++++++
 src/access/viraccessdriverselinux.h |  28 ++
 src/access/viraccessmanager.c       |   6 +
 src/internal.h                      |   4 +
 src/util/virlog.c                   |   3 +-
 src/util/virlog.h                   |   1 +
 10 files changed, 619 insertions(+), 1 deletion(-)
 create mode 100644 src/access/viraccessdriverselinux.c
 create mode 100644 src/access/viraccessdriverselinux.h

diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4
index e054913..05798d3 100644
--- a/m4/virt-compile-warnings.m4
+++ b/m4/virt-compile-warnings.m4
@@ -94,6 +94,7 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[
       dontwarn="$dontwarn -Wmissing-prototypes"
       dontwarn="$dontwarn -Wmissing-declarations"
       dontwarn="$dontwarn -Wcast-align"
+      dontwarn="$dontwarn -Wmissing-format-attribute"
     fi
 
     dnl Check whether strchr(s, char variable) causes a bogus compile
diff --git a/m4/virt-selinux.m4 b/m4/virt-selinux.m4
index abb0d12..f849858 100644
--- a/m4/virt-selinux.m4
+++ b/m4/virt-selinux.m4
@@ -43,6 +43,8 @@ AC_DEFUN([LIBVIRT_CHECK_SELINUX],[
     dnl We prefer to use <selinux/label.h> and selabel_open, but can fall
     dnl back to matchpathcon for the sake of RHEL 5's version of libselinux.
     AC_CHECK_HEADERS([selinux/label.h])
+
+    AC_CHECK_FUNCS([security_deny_unknown])
   fi
 ])
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 02713c1..5723a0f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,7 @@ daemon/stream.c
 gnulib/lib/gai_strerror.c
 gnulib/lib/regcomp.c
 src/access/viraccessdriverpolkit.c
+src/access/viraccessdriverselinux.c
 src/access/viraccessmanager.c
 src/conf/cpu_conf.c
 src/conf/device_conf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 3e6c3df..20ce083 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -782,6 +782,9 @@ ACCESS_DRIVER_SOURCES = \
 ACCESS_DRIVER_POLKIT_SOURCES = \
 		access/viraccessdriverpolkit.h access/viraccessdriverpolkit.c
 
+ACCESS_DRIVER_SELINUX_SOURCES = \
+		access/viraccessdriverselinux.h access/viraccessdriverselinux.c
+
 ACCESS_DRIVER_POLKIT_POLICY = \
 		access/org.libvirt.api.policy
 
@@ -1368,6 +1371,12 @@ libvirt_driver_access_la_LIBADD =
 
 EXTRA_DIST += access/genpolkit.pl
 
+if WITH_SELINUX
+libvirt_driver_access_la_SOURCES += $(ACCESS_DRIVER_SELINUX_SOURCES)
+else
+EXTRA_DIST += $(ACCESS_DRIVER_SELINUX_SOURCES)
+endif
+
 if WITH_POLKIT1
 libvirt_driver_access_la_SOURCES += $(ACCESS_DRIVER_POLKIT_SOURCES)
 
diff --git a/src/access/viraccessdriverselinux.c b/src/access/viraccessdriverselinux.c
new file mode 100644
index 0000000..235760d
--- /dev/null
+++ b/src/access/viraccessdriverselinux.c
@@ -0,0 +1,565 @@
+/*
+ * viraccessdriverselinux.c: selinuxed access control driver
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "viraccessdriverselinux.h"
+#include "viralloc.h"
+#include "vircommand.h"
+#include "virlog.h"
+#include "virthread.h"
+#include "virerror.h"
+#include "virutil.h"
+
+#include <selinux/selinux.h>
+#include <selinux/avc.h>
+#include <selinux/av_permissions.h>
+#include <selinux/flask.h>
+
+
+#define VIR_FROM_THIS VIR_FROM_ACCESS
+#define virAccessError(code, ...)                                       \
+    virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,                 \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
+typedef enum {
+    VIR_ACCESS_DRIVER_SELINUX_CLASS_CONNECT,
+    VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+
+    VIR_ACCESS_DRIVER_SELINUX_CLASS_LAST
+} virAccessDriverSELinuxClass;
+
+VIR_ENUM_DECL(virAccessDriverSELinuxClass)
+VIR_ENUM_IMPL(virAccessDriverSELinuxClass,
+              VIR_ACCESS_DRIVER_SELINUX_CLASS_LAST,
+              "vir_connect",
+              "vir_domain")
+
+static void virAccessDriverSELinuxAVCLog(const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(1, 2);
+static void virAccessDriverSELinuxAVCLogAudit(void *data, security_class_t class, char *buf, size_t bufleft);
+static void *virAccessDriverSELinuxAVCCreateThread(void (*run)(void));
+static void virAccessDriverSELinuxAVCStopThread(void *thread);
+static void *virAccessDriverSELinuxAVCAllocLock(void);
+static void virAccessDriverSELinuxAVCGetLock(void *lock);
+static void virAccessDriverSELinuxAVCReleaseLock(void *lock);
+static void virAccessDriverSELinuxAVCFreeLock(void *lock);
+
+
+/* AVC callback structures for use in avc_init.  */
+static const struct avc_memory_callback virAccessDriverSELinuxAVCMemCallbacks =
+{
+    .func_malloc = malloc,
+    .func_free = free,
+};
+
+VIR_WARNINGS_NO_MISSING_FORMAT
+static const struct avc_log_callback virAccessDriverSELinuxAVCLogCallbacks =
+{
+    .func_log = virAccessDriverSELinuxAVCLog,
+    .func_audit = virAccessDriverSELinuxAVCLogAudit,
+};
+VIR_WARNINGS_RESET
+
+static const struct avc_thread_callback virAccessDriverSELinuxAVCThreadCallbacks =
+{
+    .func_create_thread = virAccessDriverSELinuxAVCCreateThread,
+    .func_stop_thread = virAccessDriverSELinuxAVCStopThread,
+};
+static const struct avc_lock_callback virAccessDriverSELinuxAVCLockCallbacks =
+{
+    .func_alloc_lock = virAccessDriverSELinuxAVCAllocLock,
+    .func_get_lock = virAccessDriverSELinuxAVCGetLock,
+    .func_release_lock = virAccessDriverSELinuxAVCReleaseLock,
+    .func_free_lock = virAccessDriverSELinuxAVCFreeLock,
+};
+
+
+typedef struct _virAccessDriverSELinuxPrivate virAccessDriverSELinuxPrivate;
+typedef virAccessDriverSELinuxPrivate *virAccessDriverSELinuxPrivatePtr;
+
+struct _virAccessDriverSELinuxPrivate {
+    bool enabled;
+
+    /* Cache for AVCs */
+    struct avc_entry_ref aeref;
+
+    /* SID of the daemon */
+    security_id_t selfSid;
+};
+
+
+static int virAccessDriverSELinuxSetup(virAccessManagerPtr manager)
+{
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+    int r;
+    security_context_t localCon;
+    int ret = -1;
+
+    if ((r = is_selinux_enabled()) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to determine if SELinux is enabled"));
+        return -1;
+    }
+    priv->enabled = r != 0;
+    priv->selfSid = SECSID_WILD;
+
+    avc_entry_ref_init(&priv->aeref);
+
+    if (avc_init("avc",
+                 &virAccessDriverSELinuxAVCMemCallbacks,
+                 &virAccessDriverSELinuxAVCLogCallbacks,
+                 &virAccessDriverSELinuxAVCThreadCallbacks,
+                 &virAccessDriverSELinuxAVCLockCallbacks) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to initialize AVC system"));
+        goto cleanup;
+    }
+
+    if (getcon(&localCon) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to get context of daemon"));
+        goto cleanup;
+    }
+
+    if (avc_context_to_sid(localCon, &priv->selfSid) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to convert context %s to SID"),
+                             (char*)localCon);
+        goto cleanup;
+    }
+    VIR_FREE(localCon);
+
+    ret = 0;
+cleanup:
+    if (ret < 0)
+        priv->selfSid = SECSID_WILD;
+    freecon(localCon);
+    return ret;
+}
+
+
+static void virAccessDriverSELinuxCleanup(virAccessManagerPtr manager)
+{
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    priv->selfSid = SECSID_WILD;
+}
+
+
+static security_id_t
+virAccessDriverSELinuxGetClientSID(void)
+{
+    virIdentityPtr identity = virIdentityGetCurrent();
+    const char *seccon = NULL;
+    security_id_t sid = SECSID_WILD;
+
+    if (!identity) {
+        virAccessError(VIR_ERR_ACCESS_DENIED, "%s",
+                       _("SELinux denying due to lack of identity"));
+        return NULL;
+    }
+    if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_SELINUX_CONTEXT, &seccon) < 0)
+        goto cleanup;
+
+    if (!seccon) {
+        virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("No security context available"));
+        goto cleanup;
+    }
+
+    if (avc_context_to_sid((security_context_t)seccon, &sid) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to convert context %s to SID"),
+                             seccon);
+        sid = SECSID_WILD;
+        goto cleanup;
+    }
+
+cleanup:
+    virObjectUnref(identity);
+    return sid;
+}
+
+
+static security_class_t
+virAccessDriverSELinuxGetObjectClass(const char *klassname)
+{
+    security_class_t ret;
+
+    if ((ret = string_to_security_class(klassname)) == 0) {
+        virReportSystemError(errno,
+                             _("Unable to find security class '%s'"), klassname);
+        return 0;
+    }
+
+    return ret;
+}
+
+
+static access_vector_t
+virAccessDriverSELinuxGetObjectPerm(const char *permname,
+                                    const char *klassname,
+                                    security_class_t objectClass)
+{
+    access_vector_t ret;
+
+    if (objectClass == 0)
+        return 0;
+
+    if ((ret = string_to_av_perm(objectClass, permname)) == 0) {
+        virReportSystemError(errno,
+                             _("Unable to lookup permission '%s' for class '%s'"),
+                             permname, klassname);
+        return 0;
+    }
+
+    return ret;
+}
+
+static int
+virAccessDriverSELinuxCheck(virAccessManagerPtr manager,
+                            security_id_t objectSid,
+                            virAccessDriverSELinuxClass klass,
+                            const char *permname)
+{
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+    const char *klassname = virAccessDriverSELinuxClassTypeToString(klass);
+    security_id_t clientSid = virAccessDriverSELinuxGetClientSID();
+    security_class_t klassId = virAccessDriverSELinuxGetObjectClass(klassname);
+    access_vector_t perm = virAccessDriverSELinuxGetObjectPerm(permname, klassname, klassId);
+    int ret;
+
+    if (clientSid == SECSID_WILD ||
+        klassId == 0 ||
+        perm == 0) {
+#ifdef HAVE_SECURITY_DENY_UNKNOWN
+        if (security_deny_unknown() == 0) {
+            VIR_WARN("Allow access, because policy does not deny unknown objects");
+            ret = 1; /* Allow */
+        } else {
+            ret = 0; /* Deny */
+        }
+#else
+        ret = 0; /* Deny */
+#endif
+        goto cleanup;
+    }
+
+    if (avc_has_perm(clientSid, objectSid,
+                     klassId, perm,
+                     &priv->aeref, NULL) < 0) {
+        int save_errno = errno;
+        if (security_getenforce() == 0) {
+            char ebuf[1024];
+            VIR_WARN("Ignoring denial in non-enforcing mode: %s",
+                     virStrerror(save_errno, ebuf, sizeof(ebuf)));
+            ret = 1; /* Allow */
+            goto cleanup;
+        }
+        switch (save_errno) {
+        case EACCES:
+            ret = 0; /* Deny */
+            break;
+        case EINVAL:
+            ret = -1; /* Error */
+            virAccessError(VIR_ERR_ACCESS_DENIED, "%s",
+                           _("SELinux denying due to invalid security context"));
+            break;
+        default:
+            ret = -1; /* Error */
+            virReportSystemError(errno, "%s",
+                                 _("SELinux denying"));
+            break;
+        }
+        goto cleanup;
+    }
+
+    ret = 1;
+
+cleanup:
+    return ret;
+}
+
+
+static int
+virAccessDriverSELinuxCheckConnect(virAccessManagerPtr manager,
+                                   const char *driverName ATTRIBUTE_UNUSED,
+                                   virAccessPermConnect perm)
+{
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    /* There's no object to use for targetSid here, so we
+     * instead use the daemon's context as the targetSid */
+    return virAccessDriverSELinuxCheck(manager,
+                                       priv->selfSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_CONNECT,
+                                       virAccessPermConnectTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckDomain(virAccessManagerPtr manager,
+                                  const char *driverName ATTRIBUTE_UNUSED,
+                                  virDomainDefPtr domain ATTRIBUTE_UNUSED,
+                                  virAccessPermDomain perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermDomainTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckInterface(virAccessManagerPtr manager,
+                                     const char *driverName ATTRIBUTE_UNUSED,
+                                     virInterfaceDefPtr iface ATTRIBUTE_UNUSED,
+                                     virAccessPermInterface perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermInterfaceTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckNetwork(virAccessManagerPtr manager,
+                                   const char *driverName ATTRIBUTE_UNUSED,
+                                   virNetworkDefPtr network ATTRIBUTE_UNUSED,
+                                   virAccessPermNetwork perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermNetworkTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckNodeDevice(virAccessManagerPtr manager,
+                                      const char *driverName ATTRIBUTE_UNUSED,
+                                      virNodeDeviceDefPtr nodedev ATTRIBUTE_UNUSED,
+                                      virAccessPermNodeDevice perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermNodeDeviceTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckNWFilter(virAccessManagerPtr manager,
+                                    const char *driverName ATTRIBUTE_UNUSED,
+                                    virNWFilterDefPtr nwfilter ATTRIBUTE_UNUSED,
+                                    virAccessPermNWFilter perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermNWFilterTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckSecret(virAccessManagerPtr manager,
+                                  const char *driverName ATTRIBUTE_UNUSED,
+                                  virSecretDefPtr secret ATTRIBUTE_UNUSED,
+                                  virAccessPermSecret perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermSecretTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckStoragePool(virAccessManagerPtr manager,
+                                       const char *driverName ATTRIBUTE_UNUSED,
+                                       virStoragePoolDefPtr pool ATTRIBUTE_UNUSED,
+                                       virAccessPermStoragePool perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermStoragePoolTypeToString(perm));
+}
+
+
+static int
+virAccessDriverSELinuxCheckStorageVol(virAccessManagerPtr manager,
+                                      const char *driverName ATTRIBUTE_UNUSED,
+                                      virStoragePoolDefPtr pool ATTRIBUTE_UNUSED,
+                                      virStorageVolDefPtr vol ATTRIBUTE_UNUSED,
+                                      virAccessPermStorageVol perm)
+{
+    security_id_t objectSid;
+
+    virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+    objectSid = priv->selfSid; /* XXX take from def ? */
+
+    return virAccessDriverSELinuxCheck(manager,
+                                       objectSid,
+                                       VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN,
+                                       virAccessPermStorageVolTypeToString(perm));
+}
+
+
+static void virAccessDriverSELinuxAVCLog(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    virLogVMessage(VIR_LOG_FROM_ACCESS, VIR_LOG_WARN,
+                   __FILE__, __LINE__ ,__func__,
+                   NULL, fmt, ap);
+    va_end(ap);
+}
+
+
+static void virAccessDriverSELinuxAVCLogAudit(void *data ATTRIBUTE_UNUSED,
+                                              security_class_t class ATTRIBUTE_UNUSED,
+                                              char *buf ATTRIBUTE_UNUSED,
+                                              size_t bufleft ATTRIBUTE_UNUSED)
+{
+}
+
+
+static void *virAccessDriverSELinuxAVCCreateThread(void (*run)(void))
+{
+    virThreadPtr thread;
+
+    if (VIR_ALLOC(thread) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    if (virThreadCreate(thread, false, (virThreadFunc)run, NULL) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to create thread"));
+        VIR_FREE(thread);
+    }
+
+    return thread;
+}
+
+
+static void virAccessDriverSELinuxAVCStopThread(void *thread)
+{
+    virThreadCancel(thread);
+    VIR_FREE(thread);
+}
+
+
+static void *virAccessDriverSELinuxAVCAllocLock(void)
+{
+    virMutexPtr lock;
+    if (VIR_ALLOC(lock) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+    if (virMutexInit(lock) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to initialize mutex"));
+        VIR_FREE(lock);
+        return NULL;
+    }
+    return lock;
+}
+
+
+static void virAccessDriverSELinuxAVCGetLock(void *lock)
+{
+    virMutexLock(lock);
+}
+
+
+static void virAccessDriverSELinuxAVCReleaseLock(void *lock)
+{
+    virMutexUnlock(lock);
+}
+
+
+static void virAccessDriverSELinuxAVCFreeLock(void *lock)
+{
+    virMutexDestroy(lock);
+    VIR_FREE(lock);
+}
+
+
+virAccessDriver accessDriverSELinux = {
+    .privateDataLen = sizeof(virAccessDriverSELinuxPrivate),
+    .name = "selinux",
+    .setup = virAccessDriverSELinuxSetup,
+    .cleanup = virAccessDriverSELinuxCleanup,
+    .checkConnect = virAccessDriverSELinuxCheckConnect,
+    .checkDomain = virAccessDriverSELinuxCheckDomain,
+    .checkInterface = virAccessDriverSELinuxCheckInterface,
+    .checkNetwork = virAccessDriverSELinuxCheckNetwork,
+    .checkNodeDevice = virAccessDriverSELinuxCheckNodeDevice,
+    .checkNWFilter = virAccessDriverSELinuxCheckNWFilter,
+    .checkSecret = virAccessDriverSELinuxCheckSecret,
+    .checkStoragePool = virAccessDriverSELinuxCheckStoragePool,
+    .checkStorageVol = virAccessDriverSELinuxCheckStorageVol,
+};
diff --git a/src/access/viraccessdriverselinux.h b/src/access/viraccessdriverselinux.h
new file mode 100644
index 0000000..e2b26e2
--- /dev/null
+++ b/src/access/viraccessdriverselinux.h
@@ -0,0 +1,28 @@
+/*
+ * viraccessdriverselinux.h: selinuxed access control driver
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VIR_ACCESS_DRIVER_SELINUX_H__
+# define __VIR_ACCESS_DRIVER_SELINUX_H__
+
+# include "viraccessdriver.h"
+
+extern virAccessDriver accessDriverSELinux;
+
+#endif /* __VIR_ACCESS_DRIVER_SELINUX_H__ */
diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c
index f8c0cae..71c3470 100644
--- a/src/access/viraccessmanager.c
+++ b/src/access/viraccessmanager.c
@@ -26,6 +26,9 @@
 #if WITH_POLKIT1
 # include "viraccessdriverpolkit.h"
 #endif
+#if WITH_SELINUX
+# include "viraccessdriverselinux.h"
+#endif
 #include "viralloc.h"
 #include "virerror.h"
 #include "virobject.h"
@@ -114,6 +117,9 @@ static virAccessDriverPtr accessDrivers[] = {
 #if WITH_POLKIT1
     &accessDriverPolkit,
 #endif
+#if WITH_SELINUX
+    &accessDriverSELinux,
+#endif
 };
 
 
diff --git a/src/internal.h b/src/internal.h
index d819aa3..9b56fa2 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -219,11 +219,15 @@
 #  define VIR_WARNINGS_NO_CAST_ALIGN \
     _Pragma ("GCC diagnostic push") \
     _Pragma ("GCC diagnostic ignored \"-Wcast-align\"")
+#  define VIR_WARNINGS_NO_MISSING_FORMAT \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wmissing-format-attribute\"")
 
 #  define VIR_WARNINGS_RESET \
     _Pragma ("GCC diagnostic pop")
 # else
 #  define VIR_WARNINGS_NO_CAST_ALIGN
+#  define VIR_WARNINGS_NO_MISSING_FORMAT
 #  define VIR_WARNINGS_RESET
 # endif
 
diff --git a/src/util/virlog.c b/src/util/virlog.c
index 62ff838..152191c 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -66,7 +66,8 @@ VIR_ENUM_IMPL(virLogSource, VIR_LOG_FROM_LAST,
               "error",
               "audit",
               "trace",
-              "library");
+              "library",
+              "access");
 
 /*
  * A logging buffer to keep some history over logs
diff --git a/src/util/virlog.h b/src/util/virlog.h
index 6b83245..08d12c0 100644
--- a/src/util/virlog.h
+++ b/src/util/virlog.h
@@ -50,6 +50,7 @@ typedef enum {
     VIR_LOG_FROM_AUDIT,
     VIR_LOG_FROM_TRACE,
     VIR_LOG_FROM_LIBRARY,
+    VIR_LOG_FROM_ACCESS,
 
     VIR_LOG_FROM_LAST,
 } virLogSource;
-- 
1.8.1.4




More information about the libvir-list mailing list