[libvirt] [PATCH 1/8] Refactor the security drivers to simplify usage

Daniel P. Berrange berrange at redhat.com
Mon Nov 22 18:09:20 UTC 2010


The current security driver usage requires horrible code like

    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityHostdevLabel &&
        driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
                                                              vm, hostdev) < 0)

This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply

  if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
                                        vm, hostdev) < 0)

The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.

The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.

* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
  use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c,  src/qemu/qemu_security_dac.h
  src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
  Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
  src/security/security_dac.c, src/security/security_dac.h: Generic
  versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
  src/security/security_driver.c, src/security/security_driver.h,
  src/security/security_selinux.c, src/security/security_selinux.h:
  Update to take virSecurityManagerPtr object as the first param
  in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
  implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
  New internal API for invoking security drivers
---
 src/Makefile.am                  |   12 +-
 src/libvirt_private.syms         |   33 ++-
 src/qemu/qemu_conf.h             |    6 +-
 src/qemu/qemu_driver.c           |  250 +++++---------
 src/qemu/qemu_security_dac.c     |  590 -------------------------------
 src/qemu/qemu_security_dac.h     |   22 --
 src/qemu/qemu_security_stacked.c |  418 ----------------------
 src/qemu/qemu_security_stacked.h |   22 --
 src/security/security_apparmor.c |  152 ++++++---
 src/security/security_apparmor.h |    2 +
 src/security/security_dac.c      |  712 ++++++++++++++++++++++++++++++++++++++
 src/security/security_dac.h      |   27 ++
 src/security/security_driver.c   |  116 ++-----
 src/security/security_driver.h   |   95 +++---
 src/security/security_manager.c  |  291 ++++++++++++++++
 src/security/security_manager.h  |   74 ++++
 src/security/security_nop.c      |  168 +++++++++
 src/security/security_nop.h      |   17 +
 src/security/security_selinux.c  |  145 +++++---
 src/security/security_selinux.h  |    2 +-
 src/security/security_stack.c    |  383 ++++++++++++++++++++
 src/security/security_stack.h    |   24 ++
 22 files changed, 2079 insertions(+), 1482 deletions(-)
 delete mode 100644 src/qemu/qemu_security_dac.c
 delete mode 100644 src/qemu/qemu_security_dac.h
 delete mode 100644 src/qemu/qemu_security_stacked.c
 delete mode 100644 src/qemu/qemu_security_stacked.h
 create mode 100644 src/security/security_dac.c
 create mode 100644 src/security/security_dac.h
 create mode 100644 src/security/security_manager.c
 create mode 100644 src/security/security_manager.h
 create mode 100644 src/security/security_nop.c
 create mode 100644 src/security/security_nop.h
 create mode 100644 src/security/security_stack.c
 create mode 100644 src/security/security_stack.h

diff --git a/src/Makefile.am b/src/Makefile.am
index a9a1986..66af9cf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -273,11 +273,7 @@ QEMU_DRIVER_SOURCES =						\
 		qemu/qemu_monitor_json.h			\
 		qemu/qemu_driver.c qemu/qemu_driver.h		\
 		qemu/qemu_bridge_filter.c			\
-		qemu/qemu_bridge_filter.h			\
-		qemu/qemu_security_stacked.h			\
-		qemu/qemu_security_stacked.c			\
-		qemu/qemu_security_dac.h			\
-		qemu/qemu_security_dac.c
+		qemu/qemu_bridge_filter.h
 
 XENAPI_DRIVER_SOURCES =								\
 		xenapi/xenapi_driver.c xenapi/xenapi_driver.h	\
@@ -376,7 +372,11 @@ NWFILTER_DRIVER_SOURCES =					\
 
 # Security framework and drivers for various models
 SECURITY_DRIVER_SOURCES =					\
-		security/security_driver.h security/security_driver.c
+		security/security_driver.h security/security_driver.c \
+		security/security_nop.h security/security_nop.c \
+		security/security_stack.h security/security_stack.c \
+		security/security_dac.h security/security_dac.c \
+		security/security_manager.h security/security_manager.c
 
 SECURITY_DRIVER_SELINUX_SOURCES =				\
 		security/security_selinux.h security/security_selinux.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8bf1028..3af0210 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -646,13 +646,32 @@ virSecretDefParseFile;
 virSecretDefParseString;
 
 
-# security.h
-virSecurityDriverGetDOI;
-virSecurityDriverGetModel;
-virSecurityDriverInit;
-virSecurityDriverSetDOI;
-virSecurityDriverStartup;
-virSecurityDriverVerify;
+# security_driver.h
+virSecurityDriverLookup;
+
+
+# security_manager.h
+virSecurityManagerClearSocketLabel;
+virSecurityManagerGenLabel;
+virSecurityManagerGetDOI;
+virSecurityManagerGetModel;
+virSecurityManagerGetProcessLabel;
+virSecurityManagerNew;
+virSecurityManagerNewStack;
+virSecurityManagerNewDAC;
+virSecurityManagerReleaseLabel;
+virSecurityManagerReserveLabel;
+virSecurityManagerRestoreImageLabel;
+virSecurityManagerRestoreAllLabel;
+virSecurityManagerRestoreHostdevLabel;
+virSecurityManagerRestoreSavedStateLabel;
+virSecurityManagerSetAllLabel;
+virSecurityManagerSetImageLabel;
+virSecurityManagerSetHostdevLabel;
+virSecurityManagerSetProcessLabel;
+virSecurityManagerSetSavedStateLabel;
+virSecurityManagerSetSocketLabel;
+virSecurityManagerVerify;
 
 
 # storage_conf.h
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 790ce98..ba3c7b1 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -34,7 +34,7 @@
 # include "domain_conf.h"
 # include "domain_event.h"
 # include "threads.h"
-# include "security/security_driver.h"
+# include "security/security_manager.h"
 # include "cgroup.h"
 # include "pci.h"
 # include "cpu_conf.h"
@@ -166,9 +166,7 @@ struct qemud_driver {
     int domainEventDispatching;
 
     char *securityDriverName;
-    virSecurityDriverPtr securityDriver;
-    virSecurityDriverPtr securityPrimaryDriver;
-    virSecurityDriverPtr securitySecondaryDriver;
+    virSecurityManagerPtr securityManager;
 
     char *saveImageFormat;
     char *dumpImageFormat;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ed1ea6b..2b901b8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -70,8 +70,6 @@
 #include "pci.h"
 #include "hostusb.h"
 #include "processinfo.h"
-#include "qemu_security_stacked.h"
-#include "qemu_security_dac.h"
 #include "cgroup.h"
 #include "libvirt_internal.h"
 #include "xml.h"
@@ -1395,10 +1393,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm)
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecuritySocketLabel &&
-        driver->securityDriver->domainSetSecuritySocketLabel
-          (driver->securityDriver,vm) < 0) {
+    if (virSecurityManagerSetSocketLabel(driver->securityManager, vm) < 0) {
         VIR_ERROR(_("Failed to set security context for monitor for %s"),
                   vm->def->name);
         goto error;
@@ -1416,10 +1411,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm)
     if (priv->mon == NULL)
         virDomainObjUnref(vm);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainClearSecuritySocketLabel &&
-        driver->securityDriver->domainClearSecuritySocketLabel
-          (driver->securityDriver,vm) < 0) {
+    if (virSecurityManagerClearSocketLabel(driver->securityManager, vm) < 0) {
         VIR_ERROR(_("Failed to clear security context for monitor for %s"),
                   vm->def->name);
         goto error;
@@ -1488,10 +1480,7 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq
             goto error;
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainReserveSecurityLabel &&
-        driver->securityDriver->domainReserveSecurityLabel(driver->securityDriver,
-                                                           obj) < 0)
+    if (virSecurityManagerReserveLabel(driver->securityManager, obj) < 0)
         goto error;
 
     if (qemudVMFiltersInstantiate(conn, obj->def))
@@ -1531,30 +1520,24 @@ qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver)
 static int
 qemudSecurityInit(struct qemud_driver *qemud_drv)
 {
-    int ret;
-    virSecurityDriverPtr security_drv;
-
-    qemuSecurityStackedSetDriver(qemud_drv);
-    qemuSecurityDACSetDriver(qemud_drv);
-
-    ret = virSecurityDriverStartup(&security_drv,
-                                   qemud_drv->securityDriverName,
-                                   qemud_drv->allowDiskFormatProbing);
-    if (ret == -1) {
-        VIR_ERROR0(_("Failed to start security driver"));
+    virSecurityManagerPtr mgr = virSecurityManagerNew(qemud_drv->securityDriverName,
+                                                      qemud_drv->allowDiskFormatProbing);
+    if (!mgr)
         return -1;
-    }
 
-    /* No primary security driver wanted to be enabled: just setup
-     * the DAC driver on its own */
-    if (ret == -2) {
-        qemud_drv->securityDriver = &qemuDACSecurityDriver;
-        VIR_INFO0(_("No security driver available"));
+    if (qemud_drv->privileged) {
+        virSecurityManagerPtr dac = virSecurityManagerNewDAC(qemud_drv->user,
+                                                             qemud_drv->group,
+                                                             qemud_drv->allowDiskFormatProbing,
+                                                             qemud_drv->dynamicOwnership);
+        if (!dac)
+            return -1;
+
+        if (!(qemud_drv->securityManager = virSecurityManagerNewStack(mgr,
+                                                                      dac)))
+            return -1;
     } else {
-        qemud_drv->securityPrimaryDriver = security_drv;
-        qemud_drv->securitySecondaryDriver = &qemuDACSecurityDriver;
-        qemud_drv->securityDriver = &qemuStackedSecurityDriver;
-        VIR_INFO("Initialized security driver %s", security_drv->name);
+        qemud_drv->securityManager = mgr;
     }
 
     return 0;
@@ -1600,20 +1583,22 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
     caps->ns.href = qemuDomainDefNamespaceHref;
 
     /* Security driver data */
-    if (driver->securityPrimaryDriver) {
-        const char *doi, *model;
+    const char *doi, *model;
 
-        doi = virSecurityDriverGetDOI(driver->securityPrimaryDriver);
-        model = virSecurityDriverGetModel(driver->securityPrimaryDriver);
+    doi = virSecurityManagerGetDOI(driver->securityManager);
+    model = virSecurityManagerGetModel(driver->securityManager);
+    if (STREQ(model, "none")) {
+        model = "";
+        doi = "";
+    }
 
-        if (!(caps->host.secModel.model = strdup(model)))
-            goto no_memory;
-        if (!(caps->host.secModel.doi = strdup(doi)))
-            goto no_memory;
+    if (!(caps->host.secModel.model = strdup(model)))
+        goto no_memory;
+    if (!(caps->host.secModel.doi = strdup(doi)))
+        goto no_memory;
 
-        VIR_DEBUG("Initialized caps for security driver \"%s\" with "
-                  "DOI \"%s\"", model, doi);
-    }
+    VIR_DEBUG("Initialized caps for security driver \"%s\" with "
+              "DOI \"%s\"", model, doi);
 
     return caps;
 
@@ -3681,9 +3666,7 @@ static int qemudSecurityHook(void *data) {
     if (qemudInitCpuAffinity(h->vm) < 0)
         return -1;
 
-    if (h->driver->securityDriver &&
-        h->driver->securityDriver->domainSetSecurityProcessLabel &&
-        h->driver->securityDriver->domainSetSecurityProcessLabel(h->driver->securityDriver, h->vm) < 0)
+    if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0)
         return -1;
 
     return 0;
@@ -3912,22 +3895,17 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     /* If you are using a SecurityDriver with dynamic labelling,
        then generate a security label for isolation */
     DEBUG0("Generating domain security label (if required)");
-    if (driver->securityDriver &&
-        driver->securityDriver->domainGenSecurityLabel) {
-        ret = driver->securityDriver->domainGenSecurityLabel(driver->securityDriver,
-                                                             vm);
-        qemuDomainSecurityLabelAudit(vm, ret >= 0);
-        if (ret < 0)
-            goto cleanup;
+    if (virSecurityManagerGenLabel(driver->securityManager,
+                                   vm) < 0) {
+        qemuDomainSecurityLabelAudit(vm, false);
+        goto cleanup;
     }
+    qemuDomainSecurityLabelAudit(vm, true);
 
     DEBUG0("Generating setting domain security labels (if required)");
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityAllLabel &&
-        driver->securityDriver->domainSetSecurityAllLabel(driver->securityDriver,
-                                                          vm, stdin_path) < 0) {
+    if (virSecurityManagerSetAllLabel(driver->securityManager,
+                                      vm, stdin_path) < 0)
         goto cleanup;
-    }
 
     /* Ensure no historical cgroup for this VM is lying around bogus
      * settings */
@@ -4342,14 +4320,10 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
     }
 
     /* Reset Security Labels */
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityAllLabel)
-        driver->securityDriver->domainRestoreSecurityAllLabel(driver->securityDriver,
-                                                              vm, migrated);
-    if (driver->securityDriver &&
-        driver->securityDriver->domainReleaseSecurityLabel)
-        driver->securityDriver->domainReleaseSecurityLabel(driver->securityDriver,
-                                                           vm);
+    virSecurityManagerRestoreAllLabel(driver->securityManager,
+                                      vm, migrated);
+    virSecurityManagerReleaseLabel(driver->securityManager,
+                                   vm);
 
     /* Clear out dynamically assigned labels */
     if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
@@ -4830,7 +4804,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto cleanup;
 
-    if (virSecurityDriverVerify(def) < 0)
+    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
         goto cleanup;
 
     if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
@@ -5743,10 +5717,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
     }
 
     if ((!bypassSecurityDriver) &&
-        driver->securityDriver &&
-        driver->securityDriver->domainSetSavedStateLabel &&
-        driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver,
-                                                         vm, path) == -1)
+        virSecurityManagerSetSavedStateLabel(driver->securityManager,
+                                             vm, path) < 0)
         goto endjob;
 
     if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
@@ -5779,10 +5751,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
         goto endjob;
 
     if ((!bypassSecurityDriver) &&
-        driver->securityDriver &&
-        driver->securityDriver->domainRestoreSavedStateLabel &&
-        driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver,
-                                                             vm, path) == -1)
+        virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
+                                                 vm, path) < 0)
         VIR_WARN("failed to restore save state label on %s", path);
 
     if (cgroup != NULL) {
@@ -5828,10 +5798,8 @@ endjob:
             }
 
             if ((!bypassSecurityDriver) &&
-                driver->securityDriver &&
-                driver->securityDriver->domainRestoreSavedStateLabel &&
-                driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver,
-                                                                     vm, path) == -1)
+                virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
+                                                         vm, path) < 0)
                 VIR_WARN("failed to restore save state label on %s", path);
         }
 
@@ -6096,10 +6064,8 @@ static int qemudDomainCoreDump(virDomainPtr dom,
         goto endjob;
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSavedStateLabel &&
-        driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver,
-                                                         vm, path) == -1)
+    if (virSecurityManagerSetSavedStateLabel(driver->securityManager,
+                                             vm, path) < 0)
         goto endjob;
 
     /* Migrate will always stop the VM, so the resume condition is
@@ -6156,11 +6122,9 @@ static int qemudDomainCoreDump(virDomainPtr dom,
 
     paused = 1;
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSavedStateLabel &&
-        driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver,
-                                                             vm, path) == -1)
-        goto endjob;
+    if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
+                                                 vm, path) < 0)
+        VIR_WARN("Failed to restore security label on %s", path);
 
 endjob:
     if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
@@ -6643,10 +6607,8 @@ static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr sec
      *   QEMU monitor hasn't seen SIGHUP/ERR on poll().
      */
     if (virDomainObjIsActive(vm)) {
-        if (driver->securityDriver &&
-            driver->securityDriver->domainGetSecurityProcessLabel &&
-            driver->securityDriver->domainGetSecurityProcessLabel(driver->securityDriver,
-                                                                  vm, seclabel) < 0) {
+        if (virSecurityManagerGetProcessLabel(driver->securityManager,
+                                              vm, seclabel) < 0) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR,
                             "%s", _("Failed to get security label"));
             goto cleanup;
@@ -6670,11 +6632,6 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn,
     int ret = 0;
 
     qemuDriverLock(driver);
-    if (!driver->securityPrimaryDriver) {
-        memset(secmodel, 0, sizeof (*secmodel));
-        goto cleanup;
-    }
-
     p = driver->caps->host.secModel.model;
     if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -7067,10 +7024,8 @@ qemudDomainSaveImageStartVM(virConnectPtr conn,
     ret = 0;
 
 out:
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSavedStateLabel &&
-        driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver,
-                                                             vm, path) == -1)
+    if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
+                                                 vm, path) < 0)
         VIR_WARN("failed to restore save state label on %s", path);
 
     return ret;
@@ -7646,7 +7601,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto cleanup;
 
-    if (virSecurityDriverVerify(def) < 0)
+    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
         goto cleanup;
 
     if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
@@ -7786,10 +7741,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
         return -1;
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityImageLabel &&
-        driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver,
-                                                            vm, disk) < 0)
+    if (virSecurityManagerSetImageLabel(driver->securityManager,
+                                        vm, disk) < 0)
         return -1;
 
     if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags)))
@@ -7818,10 +7771,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, origdisk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, origdisk) < 0)
         VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);
 
     VIR_FREE(origdisk->src);
@@ -7837,11 +7788,10 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
 
 error:
     VIR_FREE(driveAlias);
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, disk) < 0)
         VIR_WARN("Unable to restore security label on new media %s", disk->src);
+
     return -1;
 }
 
@@ -7865,10 +7815,8 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
         }
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityImageLabel &&
-        driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver,
-                                                            vm, disk) < 0)
+    if (virSecurityManagerSetImageLabel(driver->securityManager,
+                                        vm, disk) < 0)
         return -1;
 
     if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
@@ -7935,10 +7883,8 @@ error:
         qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
         VIR_WARN("Unable to release PCI address on %s", disk->src);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, disk) < 0)
         VIR_WARN("Unable to restore security label on %s", disk->src);
 
     return -1;
@@ -8078,10 +8024,8 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
     }
 
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityImageLabel &&
-        driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver,
-                                                            vm, disk) < 0)
+    if (virSecurityManagerSetImageLabel(driver->securityManager,
+                                        vm, disk) < 0)
         return -1;
 
     /* We should have an address already, so make sure */
@@ -8167,10 +8111,8 @@ error:
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, disk) < 0)
         VIR_WARN("Unable to restore security label on %s", disk->src);
 
     return -1;
@@ -8195,10 +8137,8 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
         }
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityImageLabel &&
-        driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver,
-                                                            vm, disk) < 0)
+    if (virSecurityManagerSetImageLabel(driver->securityManager,
+                                        vm, disk) < 0)
         return -1;
 
     if (!disk->src) {
@@ -8254,10 +8194,8 @@ error:
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, disk) < 0)
         VIR_WARN("Unable to restore security label on %s", disk->src);
 
     return -1;
@@ -8681,10 +8619,8 @@ static int qemudDomainAttachHostDevice(struct qemud_driver *driver,
     }
 
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainSetSecurityHostdevLabel &&
-        driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
-                                                              vm, hostdev) < 0)
+    if (virSecurityManagerSetHostdevLabel(driver->securityManager,
+                                          vm, hostdev) < 0)
         return -1;
 
     switch (hostdev->source.subsys.type) {
@@ -8710,10 +8646,8 @@ static int qemudDomainAttachHostDevice(struct qemud_driver *driver,
     return 0;
 
 error:
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
-        driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver,
-                                                                  vm, hostdev) < 0)
+    if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
+                                              vm, hostdev) < 0)
         VIR_WARN0("Unable to restore host device labelling on hotplug fail");
 
     return -1;
@@ -9150,10 +9084,8 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
 
     virDomainDiskDefFree(detach);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, dev->data.disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, dev->data.disk) < 0)
         VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
 
     if (cgroup != NULL) {
@@ -9216,10 +9148,8 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
 
     virDomainDiskDefFree(detach);
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityImageLabel &&
-        driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver,
-                                                                vm, dev->data.disk) < 0)
+    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                            vm, dev->data.disk) < 0)
         VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
 
     if (cgroup != NULL) {
@@ -9652,10 +9582,8 @@ static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
         return -1;
     }
 
-    if (driver->securityDriver &&
-        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
-        driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver,
-                                                                  vm, dev->data.hostdev) < 0)
+    if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
+                                              vm, dev->data.hostdev) < 0)
         VIR_WARN0("Failed to restore host device labelling");
 
     return ret;
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
deleted file mode 100644
index 55dc0c6..0000000
--- a/src/qemu/qemu_security_dac.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * QEMU POSIX DAC security driver
- */
-#include <config.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "qemu_security_dac.h"
-#include "qemu_conf.h"
-#include "datatypes.h"
-#include "virterror_internal.h"
-#include "util.h"
-#include "memory.h"
-#include "logging.h"
-#include "pci.h"
-#include "hostusb.h"
-#include "storage_file.h"
-
-#define VIR_FROM_THIS VIR_FROM_QEMU
-
-static struct qemud_driver *driver;
-
-void qemuSecurityDACSetDriver(struct qemud_driver *newdriver)
-{
-    driver = newdriver;
-}
-
-
-static int
-qemuSecurityDACSetOwnership(const char *path, int uid, int gid)
-{
-    VIR_INFO("Setting DAC user and group on '%s' to '%d:%d'", path, uid, gid);
-
-    if (chown(path, uid, gid) < 0) {
-        struct stat sb;
-        int chown_errno = errno;
-
-        if (stat(path, &sb) >= 0) {
-            if (sb.st_uid == uid &&
-                sb.st_gid == gid) {
-                /* It's alright, there's nothing to change anyway. */
-                return 0;
-            }
-        }
-
-        if (chown_errno == EOPNOTSUPP) {
-            VIR_INFO("Setting user and group to '%d:%d' on '%s' not supported by filesystem",
-                     uid, gid, path);
-        } else if (chown_errno == EPERM) {
-            VIR_INFO("Setting user and group to '%d:%d' on '%s' not permitted",
-                     uid, gid, path);
-        } else if (chown_errno == EROFS) {
-            VIR_INFO("Setting user and group to '%d:%d' on '%s' not possible on readonly filesystem",
-                     uid, gid, path);
-        } else {
-            virReportSystemError(chown_errno,
-                                 _("unable to set user and group to '%d:%d' on '%s'"),
-                                 uid, gid, path);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static int
-qemuSecurityDACRestoreSecurityFileLabel(const char *path)
-{
-    struct stat buf;
-    int rc = -1;
-    char *newpath = NULL;
-
-    VIR_INFO("Restoring DAC user and group on '%s'", path);
-
-    if (virFileResolveLink(path, &newpath) < 0) {
-        virReportSystemError(errno,
-                             _("cannot resolve symlink %s"), path);
-        goto err;
-    }
-
-    if (stat(newpath, &buf) != 0)
-        goto err;
-
-    /* XXX record previous ownership */
-    rc = qemuSecurityDACSetOwnership(newpath, 0, 0);
-
-err:
-    VIR_FREE(newpath);
-    return rc;
-}
-
-
-static int
-qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
-                                    const char *path,
-                                    size_t depth ATTRIBUTE_UNUSED,
-                                    void *opaque ATTRIBUTE_UNUSED)
-{
-    return qemuSecurityDACSetOwnership(path, driver->user, driver->group);
-}
-
-
-static int
-qemuSecurityDACSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                     virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                                     virDomainDiskDefPtr disk)
-
-{
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    return virDomainDiskDefForeachPath(disk,
-                                       driver->allowDiskFormatProbing,
-                                       false,
-                                       qemuSecurityDACSetSecurityFileLabel,
-                                       NULL);
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                            virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                                            virDomainDiskDefPtr disk,
-                                            int migrated)
-{
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    /* Don't restore labels on readoly/shared disks, because
-     * other VMs may still be accessing these
-     * Alternatively we could iterate over all running
-     * domains and try to figure out if it is in use, but
-     * this would not work for clustered filesystems, since
-     * we can't see running VMs using the file on other nodes
-     * Safest bet is thus to skip the restore step.
-     */
-    if (disk->readonly || disk->shared)
-        return 0;
-
-    if (!disk->src)
-        return 0;
-
-    /* If we have a shared FS & doing migrated, we must not
-     * change ownership, because that kills access on the
-     * destination host which is sub-optimal for the guest
-     * VM's I/O attempts :-)
-     */
-    if (migrated) {
-        int rc = virStorageFileIsSharedFS(disk->src);
-        if (rc < 0)
-            return -1;
-        if (rc == 1) {
-            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
-                      disk->src);
-            return 0;
-        }
-    }
-
-    return qemuSecurityDACRestoreSecurityFileLabel(disk->src);
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityImageLabel(virSecurityDriverPtr drv,
-                                         virDomainObjPtr vm,
-                                         virDomainDiskDefPtr disk)
-{
-    return qemuSecurityDACRestoreSecurityImageLabelInt(drv, vm, disk, 0);
-}
-
-
-static int
-qemuSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
-                                   const char *file,
-                                   void *opaque ATTRIBUTE_UNUSED)
-{
-    return qemuSecurityDACSetOwnership(file, driver->user, driver->group);
-}
-
-
-static int
-qemuSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
-                                   const char *file,
-                                   void *opaque ATTRIBUTE_UNUSED)
-{
-    return qemuSecurityDACSetOwnership(file, driver->user, driver->group);
-}
-
-
-static int
-qemuSecurityDACSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                       virDomainObjPtr vm,
-                                       virDomainHostdevDefPtr dev)
-
-{
-    int ret = -1;
-
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
-        return 0;
-
-    switch (dev->source.subsys.type) {
-    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
-
-        if (!usb)
-            goto done;
-
-        ret = usbDeviceFileIterate(usb, qemuSecurityDACSetSecurityUSBLabel, vm);
-        usbFreeDevice(usb);
-        break;
-    }
-
-    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
-        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
-                                      dev->source.subsys.u.pci.bus,
-                                      dev->source.subsys.u.pci.slot,
-                                      dev->source.subsys.u.pci.function);
-
-        if (!pci)
-            goto done;
-
-        ret = pciDeviceFileIterate(pci, qemuSecurityDACSetSecurityPCILabel, vm);
-        pciFreeDevice(pci);
-
-        break;
-    }
-
-    default:
-        ret = 0;
-        break;
-    }
-
-done:
-    return ret;
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
-                                       const char *file,
-                                       void *opaque ATTRIBUTE_UNUSED)
-{
-    return qemuSecurityDACRestoreSecurityFileLabel(file);
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
-                                       const char *file,
-                                       void *opaque ATTRIBUTE_UNUSED)
-{
-    return qemuSecurityDACRestoreSecurityFileLabel(file);
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                           virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                                           virDomainHostdevDefPtr dev)
-
-{
-    int ret = -1;
-
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
-        return 0;
-
-    switch (dev->source.subsys.type) {
-    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
-        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
-                                      dev->source.subsys.u.usb.device);
-
-        if (!usb)
-            goto done;
-
-        ret = usbDeviceFileIterate(usb, qemuSecurityDACRestoreSecurityUSBLabel, NULL);
-        usbFreeDevice(usb);
-
-        break;
-    }
-
-    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
-        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
-                                      dev->source.subsys.u.pci.bus,
-                                      dev->source.subsys.u.pci.slot,
-                                      dev->source.subsys.u.pci.function);
-
-        if (!pci)
-            goto done;
-
-        ret = pciDeviceFileIterate(pci, qemuSecurityDACRestoreSecurityPCILabel, NULL);
-        pciFreeDevice(pci);
-
-        break;
-    }
-
-    default:
-        ret = 0;
-        break;
-    }
-
-done:
-    return ret;
-}
-
-
-static int
-qemuSecurityDACSetChardevLabel(virDomainObjPtr vm,
-                               virDomainChrDefPtr dev)
-
-{
-    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
-    char *in = NULL, *out = NULL;
-    int ret = -1;
-
-    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
-        return 0;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-        ret = qemuSecurityDACSetOwnership(dev->data.file.path, driver->user, driver->group);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
-            (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
-            virReportOOMError();
-            goto done;
-        }
-        if ((qemuSecurityDACSetOwnership(in, driver->user, driver->group) < 0) ||
-            (qemuSecurityDACSetOwnership(out, driver->user, driver->group) < 0))
-            goto done;
-        ret = 0;
-        break;
-
-    default:
-        ret = 0;
-        break;
-    }
-
-done:
-    VIR_FREE(in);
-    VIR_FREE(out);
-    return ret;
-}
-
-static int
-qemuSecurityDACRestoreChardevLabel(virDomainObjPtr vm,
-                                   virDomainChrDefPtr dev)
-
-{
-    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
-    char *in = NULL, *out = NULL;
-    int ret = -1;
-
-    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
-        return 0;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-        ret = qemuSecurityDACRestoreSecurityFileLabel(dev->data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
-            (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
-            virReportOOMError();
-            goto done;
-        }
-        if ((qemuSecurityDACRestoreSecurityFileLabel(out) < 0) ||
-            (qemuSecurityDACRestoreSecurityFileLabel(in) < 0))
-            goto done;
-        ret = 0;
-        break;
-
-    default:
-        ret = 0;
-        break;
-    }
-
-done:
-    VIR_FREE(in);
-    VIR_FREE(out);
-    return ret;
-}
-
-
-static int
-qemuSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
-                                      virDomainChrDefPtr dev,
-                                      void *opaque)
-{
-    virDomainObjPtr vm = opaque;
-
-    return qemuSecurityDACRestoreChardevLabel(vm, dev);
-}
-
-
-static int
-qemuSecurityDACRestoreSecurityAllLabel(virSecurityDriverPtr drv,
-                                       virDomainObjPtr vm,
-                                       int migrated)
-{
-    int i;
-    int rc = 0;
-
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    VIR_DEBUG("Restoring security label on %s migrated=%d",
-              vm->def->name, migrated);
-
-    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
-        if (qemuSecurityDACRestoreSecurityHostdevLabel(drv,
-                                                       vm,
-                                                       vm->def->hostdevs[i]) < 0)
-            rc = -1;
-    }
-    for (i = 0 ; i < vm->def->ndisks ; i++) {
-        if (qemuSecurityDACRestoreSecurityImageLabelInt(drv,
-                                                        vm,
-                                                        vm->def->disks[i],
-                                                        migrated) < 0)
-            rc = -1;
-    }
-
-    if (virDomainChrDefForeach(vm->def,
-                               false,
-                               qemuSecurityDACRestoreChardevCallback,
-                               vm) < 0)
-        rc = -1;
-
-    if (vm->def->os.kernel &&
-        qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
-        rc = -1;
-
-    if (vm->def->os.initrd &&
-        qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
-                                      virDomainChrDefPtr dev,
-                                      void *opaque)
-{
-    virDomainObjPtr vm = opaque;
-
-    return qemuSecurityDACSetChardevLabel(vm, dev);
-}
-
-
-static int
-qemuSecurityDACSetSecurityAllLabel(virSecurityDriverPtr drv,
-                                   virDomainObjPtr vm,
-                                   const char *stdin_path ATTRIBUTE_UNUSED)
-{
-    int i;
-
-    if (!driver->privileged || !driver->dynamicOwnership)
-        return 0;
-
-    for (i = 0 ; i < vm->def->ndisks ; i++) {
-        /* XXX fixme - we need to recursively label the entriy tree :-( */
-        if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR)
-            continue;
-        if (qemuSecurityDACSetSecurityImageLabel(drv,
-                                                 vm,
-                                                 vm->def->disks[i]) < 0)
-            return -1;
-    }
-    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
-        if (qemuSecurityDACSetSecurityHostdevLabel(drv,
-                                                   vm,
-                                                   vm->def->hostdevs[i]) < 0)
-            return -1;
-    }
-
-    if (virDomainChrDefForeach(vm->def,
-                               true,
-                               qemuSecurityDACSetChardevCallback,
-                               vm) < 0)
-        return -1;
-
-    if (vm->def->os.kernel &&
-        qemuSecurityDACSetOwnership(vm->def->os.kernel,
-                                    driver->user,
-                                    driver->group) < 0)
-        return -1;
-
-    if (vm->def->os.initrd &&
-        qemuSecurityDACSetOwnership(vm->def->os.initrd,
-                                    driver->user,
-                                    driver->group) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-qemuSecurityDACSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                  virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                                  const char *savefile)
-{
-    if (!driver->privileged)
-        return 0;
-
-    return qemuSecurityDACSetOwnership(savefile, driver->user, driver->group);
-}
-
-
-static int
-qemuSecurityDACRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                      virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                                      const char *savefile)
-{
-    if (!driver->privileged)
-        return 0;
-
-    return qemuSecurityDACRestoreSecurityFileLabel(savefile);
-}
-
-
-static int
-qemuSecurityDACSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
-{
-    DEBUG("Dropping privileges of VM to %d:%d", driver->user, driver->group);
-
-    if (!driver->privileged)
-        return 0;
-
-    if (driver->group) {
-        if (setregid(driver->group, driver->group) < 0) {
-            virReportSystemError(errno,
-                                 _("cannot change to '%d' group"),
-                                 driver->group);
-            return -1;
-        }
-    }
-    if (driver->user) {
-        if (setreuid(driver->user, driver->user) < 0) {
-            virReportSystemError(errno,
-                                 _("cannot change to '%d' user"),
-                                 driver->user);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-
-virSecurityDriver qemuDACSecurityDriver = {
-    .name                       = "qemuDAC",
-
-    .domainSetSecurityProcessLabel = qemuSecurityDACSetProcessLabel,
-
-    .domainSetSecurityImageLabel = qemuSecurityDACSetSecurityImageLabel,
-    .domainRestoreSecurityImageLabel = qemuSecurityDACRestoreSecurityImageLabel,
-
-    .domainSetSecurityAllLabel     = qemuSecurityDACSetSecurityAllLabel,
-    .domainRestoreSecurityAllLabel = qemuSecurityDACRestoreSecurityAllLabel,
-
-    .domainSetSecurityHostdevLabel = qemuSecurityDACSetSecurityHostdevLabel,
-    .domainRestoreSecurityHostdevLabel = qemuSecurityDACRestoreSecurityHostdevLabel,
-
-    .domainSetSavedStateLabel = qemuSecurityDACSetSavedStateLabel,
-    .domainRestoreSavedStateLabel = qemuSecurityDACRestoreSavedStateLabel,
-};
diff --git a/src/qemu/qemu_security_dac.h b/src/qemu/qemu_security_dac.h
deleted file mode 100644
index a742f7a..0000000
--- a/src/qemu/qemu_security_dac.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * QEMU POSIX DAC security driver
- */
-
-#include "security/security_driver.h"
-#include "qemu_conf.h"
-
-#ifndef __QEMU_SECURITY_DAC
-# define __QEMU_SECURITY_DAC
-
-extern virSecurityDriver qemuDACSecurityDriver;
-
-void qemuSecurityDACSetDriver(struct qemud_driver *driver);
-
-#endif /* __QEMU_SECURITY_DAC */
diff --git a/src/qemu/qemu_security_stacked.c b/src/qemu/qemu_security_stacked.c
deleted file mode 100644
index 432d095..0000000
--- a/src/qemu/qemu_security_stacked.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * QEMU stacked security driver
- */
-
-#include <config.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "qemu_security_stacked.h"
-
-#include "qemu_conf.h"
-#include "datatypes.h"
-#include "virterror_internal.h"
-#include "util.h"
-#include "memory.h"
-#include "logging.h"
-#include "pci.h"
-#include "hostusb.h"
-#include "storage_file.h"
-
-#define VIR_FROM_THIS VIR_FROM_QEMU
-
-
-static struct qemud_driver *driver;
-
-void qemuSecurityStackedSetDriver(struct qemud_driver *newdriver)
-{
-    driver = newdriver;
-}
-
-
-static int
-qemuSecurityStackedVerify(virDomainDefPtr def)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSecurityVerify &&
-        driver->securitySecondaryDriver->domainSecurityVerify(def) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSecurityVerify &&
-        driver->securityPrimaryDriver->domainSecurityVerify(def) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedGenLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                            virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainGenSecurityLabel &&
-        driver->securitySecondaryDriver->domainGenSecurityLabel(driver->securitySecondaryDriver,
-                                                                vm) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainGenSecurityLabel &&
-        driver->securityPrimaryDriver->domainGenSecurityLabel(driver->securityPrimaryDriver,
-                                                              vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedReleaseLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainReleaseSecurityLabel &&
-        driver->securitySecondaryDriver->domainReleaseSecurityLabel(driver->securitySecondaryDriver,
-                                                                    vm) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainReleaseSecurityLabel &&
-        driver->securityPrimaryDriver->domainReleaseSecurityLabel(driver->securityPrimaryDriver,
-                                                                  vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedReserveLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainReserveSecurityLabel &&
-        driver->securitySecondaryDriver->domainReserveSecurityLabel(driver->securitySecondaryDriver,
-                                                                    vm) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainReserveSecurityLabel &&
-        driver->securityPrimaryDriver->domainReserveSecurityLabel(driver->securityPrimaryDriver,
-                                                                  vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                         virDomainObjPtr vm,
-                                         virDomainDiskDefPtr disk)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSecurityImageLabel &&
-        driver->securitySecondaryDriver->domainSetSecurityImageLabel(driver->securitySecondaryDriver,
-                                                                     vm, disk) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSecurityImageLabel &&
-        driver->securityPrimaryDriver->domainSetSecurityImageLabel(driver->securityPrimaryDriver,
-                                                                   vm, disk) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedRestoreSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                             virDomainObjPtr vm,
-                                             virDomainDiskDefPtr disk)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainRestoreSecurityImageLabel &&
-        driver->securitySecondaryDriver->domainRestoreSecurityImageLabel(driver->securitySecondaryDriver,
-                                                                         vm, disk) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainRestoreSecurityImageLabel &&
-        driver->securityPrimaryDriver->domainRestoreSecurityImageLabel(driver->securityPrimaryDriver,
-                                                                       vm, disk) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                           virDomainObjPtr vm,
-                                           virDomainHostdevDefPtr dev)
-
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSecurityHostdevLabel &&
-        driver->securitySecondaryDriver->domainSetSecurityHostdevLabel(driver->securitySecondaryDriver,
-                                                                       vm, dev) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSecurityHostdevLabel &&
-        driver->securityPrimaryDriver->domainSetSecurityHostdevLabel(driver->securityPrimaryDriver,
-                                                                     vm, dev) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                               virDomainObjPtr vm,
-                                               virDomainHostdevDefPtr dev)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel &&
-        driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel(driver->securitySecondaryDriver,
-                                                                           vm, dev) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel &&
-        driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel(driver->securityPrimaryDriver,
-                                                                         vm, dev) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                       virDomainObjPtr vm,
-                                       const char *stdin_path)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSecurityAllLabel &&
-        driver->securitySecondaryDriver->domainSetSecurityAllLabel(driver->securitySecondaryDriver,
-                                                                   vm, stdin_path) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSecurityAllLabel &&
-        driver->securityPrimaryDriver->domainSetSecurityAllLabel(driver->securityPrimaryDriver,
-                                                                 vm, stdin_path) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                           virDomainObjPtr vm,
-                                           int migrated)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainRestoreSecurityAllLabel &&
-        driver->securitySecondaryDriver->domainRestoreSecurityAllLabel(driver->securitySecondaryDriver,
-                                                                       vm, migrated) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainRestoreSecurityAllLabel &&
-        driver->securityPrimaryDriver->domainRestoreSecurityAllLabel(driver->securityPrimaryDriver,
-                                                                     vm, migrated) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                      virDomainObjPtr vm,
-                                      const char *savefile)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSavedStateLabel &&
-        driver->securitySecondaryDriver->domainSetSavedStateLabel(driver->securitySecondaryDriver,
-                                                                  vm, savefile) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSavedStateLabel &&
-        driver->securityPrimaryDriver->domainSetSavedStateLabel(driver->securityPrimaryDriver,
-                                                                vm, savefile) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                          virDomainObjPtr vm,
-                                          const char *savefile)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainRestoreSavedStateLabel &&
-        driver->securitySecondaryDriver->domainRestoreSavedStateLabel(driver->securitySecondaryDriver,
-                                                                      vm, savefile) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainRestoreSavedStateLabel &&
-        driver->securityPrimaryDriver->domainRestoreSavedStateLabel(driver->securityPrimaryDriver,
-                                                                    vm, savefile) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                   virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSecurityProcessLabel &&
-        driver->securitySecondaryDriver->domainSetSecurityProcessLabel(driver->securitySecondaryDriver,
-                                                                       vm) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSecurityProcessLabel &&
-        driver->securityPrimaryDriver->domainSetSecurityProcessLabel(driver->securityPrimaryDriver,
-                                                                     vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-static int
-qemuSecurityStackedGetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                   virDomainObjPtr vm,
-                                   virSecurityLabelPtr seclabel)
-{
-    int rc = 0;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainGetSecurityProcessLabel &&
-        driver->securityPrimaryDriver->domainGetSecurityProcessLabel(driver->securityPrimaryDriver,
-                                                                     vm,
-                                                                     seclabel) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedSetSocketLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                  virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainSetSecuritySocketLabel &&
-        driver->securityPrimaryDriver->domainSetSecuritySocketLabel(driver->securityPrimaryDriver,
-                                                                    vm) < 0)
-        rc = -1;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainSetSecuritySocketLabel &&
-        driver->securitySecondaryDriver->domainSetSecuritySocketLabel(driver->securitySecondaryDriver,
-                                                                      vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-static int
-qemuSecurityStackedClearSocketLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
-                                    virDomainObjPtr vm)
-{
-    int rc = 0;
-
-    if (driver->securitySecondaryDriver &&
-        driver->securitySecondaryDriver->domainClearSecuritySocketLabel &&
-        driver->securitySecondaryDriver->domainClearSecuritySocketLabel(driver->securitySecondaryDriver,
-                                                                        vm) < 0)
-        rc = -1;
-
-    if (driver->securityPrimaryDriver &&
-        driver->securityPrimaryDriver->domainClearSecuritySocketLabel &&
-        driver->securityPrimaryDriver->domainClearSecuritySocketLabel(driver->securityPrimaryDriver,
-                                                                      vm) < 0)
-        rc = -1;
-
-    return rc;
-}
-
-
-virSecurityDriver qemuStackedSecurityDriver = {
-    .name                       = "qemuStacked",
-    .domainSecurityVerify = qemuSecurityStackedVerify,
-
-    .domainGenSecurityLabel = qemuSecurityStackedGenLabel,
-    .domainReleaseSecurityLabel = qemuSecurityStackedReleaseLabel,
-    .domainReserveSecurityLabel = qemuSecurityStackedReserveLabel,
-
-    .domainGetSecurityProcessLabel = qemuSecurityStackedGetProcessLabel,
-    .domainSetSecurityProcessLabel = qemuSecurityStackedSetProcessLabel,
-
-    .domainSetSecurityImageLabel = qemuSecurityStackedSetSecurityImageLabel,
-    .domainRestoreSecurityImageLabel = qemuSecurityStackedRestoreSecurityImageLabel,
-
-    .domainSetSecurityAllLabel     = qemuSecurityStackedSetSecurityAllLabel,
-    .domainRestoreSecurityAllLabel = qemuSecurityStackedRestoreSecurityAllLabel,
-
-    .domainSetSecurityHostdevLabel = qemuSecurityStackedSetSecurityHostdevLabel,
-    .domainRestoreSecurityHostdevLabel = qemuSecurityStackedRestoreSecurityHostdevLabel,
-
-    .domainSetSavedStateLabel = qemuSecurityStackedSetSavedStateLabel,
-    .domainRestoreSavedStateLabel = qemuSecurityStackedRestoreSavedStateLabel,
-
-    .domainClearSecuritySocketLabel = qemuSecurityStackedClearSocketLabel,
-    .domainSetSecuritySocketLabel = qemuSecurityStackedSetSocketLabel,
-};
diff --git a/src/qemu/qemu_security_stacked.h b/src/qemu/qemu_security_stacked.h
deleted file mode 100644
index 07f76d5..0000000
--- a/src/qemu/qemu_security_stacked.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * QEMU stacked security driver
- */
-
-#include "security/security_driver.h"
-#include "qemu_conf.h"
-
-#ifndef __QEMU_SECURITY_STACKED
-# define __QEMU_SECURITY_STACKED
-
-extern virSecurityDriver qemuStackedSecurityDriver;
-
-void qemuSecurityStackedSetDriver(struct qemud_driver *driver);
-
-#endif /* __QEMU_SECURITY_DAC */
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index b43c4ac..37cd928 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -1,4 +1,3 @@
-
 /*
  * AppArmor security driver for libvirt
  * Copyright (C) 2009-2010 Canonical Ltd.
@@ -28,7 +27,6 @@
 
 #include "internal.h"
 
-#include "security_driver.h"
 #include "security_apparmor.h"
 #include "util.h"
 #include "memory.h"
@@ -47,7 +45,7 @@
 
 /* Data structure to pass to *FileIterate so we have everything we need */
 struct SDPDOP {
-    virSecurityDriverPtr drv;
+    virSecurityManagerPtr mgr;
     virDomainObjPtr vm;
 };
 
@@ -158,7 +156,7 @@ profile_status_file(const char *str)
  * load (add) a profile. Will create one if necessary
  */
 static int
-load_profile(virSecurityDriverPtr drv,
+load_profile(virSecurityManagerPtr mgr,
              const char *profile,
              virDomainObjPtr vm,
              const char *fn,
@@ -169,7 +167,7 @@ load_profile(virSecurityDriverPtr drv,
     char *xml = NULL;
     int pipefd[2];
     pid_t child;
-    const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv)
+    const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr)
         ? "1" : "0";
 
     if (pipe(pipefd) < -1) {
@@ -300,7 +298,7 @@ cleanup:
  * NULL.
  */
 static int
-reload_profile(virSecurityDriverPtr drv,
+reload_profile(virSecurityManagerPtr mgr,
                virDomainObjPtr vm,
                const char *fn,
                bool append)
@@ -317,7 +315,7 @@ reload_profile(virSecurityDriverPtr drv,
 
     /* Update the profile only if it is loaded */
     if (profile_loaded(secdef->imagelabel) >= 0) {
-        if (load_profile(drv, secdef->imagelabel, vm, fn, append) < 0) {
+        if (load_profile(mgr, secdef->imagelabel, vm, fn, append) < 0) {
             virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("cannot update AppArmor profile "
                                      "\'%s\'"),
@@ -340,7 +338,7 @@ AppArmorSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
     struct SDPDOP *ptr = opaque;
     virDomainObjPtr vm = ptr->vm;
 
-    if (reload_profile(ptr->drv, vm, file, true) < 0) {
+    if (reload_profile(ptr->mgr, vm, file, true) < 0) {
         const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot update AppArmor profile "
@@ -358,7 +356,7 @@ AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
     struct SDPDOP *ptr = opaque;
     virDomainObjPtr vm = ptr->vm;
 
-    if (reload_profile(ptr->drv, vm, file, true) < 0) {
+    if (reload_profile(ptr->mgr, vm, file, true) < 0) {
         const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot update AppArmor profile "
@@ -371,7 +369,7 @@ AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
 
 /* Called on libvirtd startup to see if AppArmor is available */
 static int
-AppArmorSecurityDriverProbe(void)
+AppArmorSecurityManagerProbe(void)
 {
     char *template = NULL;
     int rc = SECURITY_DRIVER_DISABLE;
@@ -403,21 +401,37 @@ AppArmorSecurityDriverProbe(void)
  * currently not used.
  */
 static int
-AppArmorSecurityDriverOpen(virSecurityDriverPtr drv,
-                           bool allowDiskFormatProbing)
+AppArmorSecurityManagerOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+AppArmorSecurityManagerClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
 {
-    virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
-    virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
     return 0;
 }
 
+static const char *
+AppArmorSecurityManagerGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return SECURITY_APPARMOR_NAME;
+}
+
+static const char *
+AppArmorSecurityManagerGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return SECURITY_APPARMOR_VOID_DOI;
+}
+
+
 /* Currently called in qemudStartVMDaemon to setup a 'label'. We look for and
  * use a profile based on the UUID, otherwise create one based on a template.
  * Keep in mind that this is called on 'start' with RestoreSecurityLabel being
  * called on shutdown.
 */
 static int
-AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                          virDomainObjPtr vm)
 {
     int rc = -1;
@@ -472,7 +486,7 @@ AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 }
 
 static int
-AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
+AppArmorSetSecurityAllLabel(virSecurityManagerPtr mgr,
                             virDomainObjPtr vm, const char *stdin_path)
 {
     if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
@@ -480,7 +494,7 @@ AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
 
     /* if the profile is not already loaded, then load one */
     if (profile_loaded(vm->def->seclabel.label) < 0) {
-        if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path,
+        if (load_profile(mgr, vm->def->seclabel.label, vm, stdin_path,
                          false) < 0) {
             virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("cannot generate AppArmor profile "
@@ -496,7 +510,7 @@ AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
  * running.
  */
 static int
-AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+AppArmorGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                 virDomainObjPtr vm,
                                 virSecurityLabelPtr sec)
 {
@@ -530,7 +544,7 @@ AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
  * more details. Currently called via qemudShutdownVMDaemon.
  */
 static int
-AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+AppArmorReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainObjPtr vm)
 {
     const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
@@ -544,7 +558,7 @@ AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 
 
 static int
-AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+AppArmorRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                 virDomainObjPtr vm,
                                 int migrated ATTRIBUTE_UNUSED)
 {
@@ -565,7 +579,7 @@ AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
  * LOCALSTATEDIR/log/libvirt/qemu/<vm name>.log
  */
 static int
-AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm)
+AppArmorSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm)
 {
     const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
     int rc = -1;
@@ -574,12 +588,12 @@ AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm)
     if ((profile_name = get_profile_name(vm)) == NULL)
         return rc;
 
-    if (STRNEQ(drv->name, secdef->model)) {
+    if (STRNEQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
                                "\'%s\' model configured for domain, but "
                                "hypervisor driver is \'%s\'."),
-                               secdef->model, drv->name);
+                               secdef->model, virSecurityManagerGetModel(mgr));
         if (use_apparmor() > 0)
             goto clean;
     }
@@ -597,19 +611,33 @@ AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm)
     return rc;
 }
 
+static int
+AppArmorSetSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+AppArmorClearSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                 virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
 
 /* Called when hotplugging */
 static int
-AppArmorRestoreSecurityImageLabel(virSecurityDriverPtr drv,
+AppArmorRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
                                   virDomainObjPtr vm,
                                   virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
 {
-    return reload_profile(drv, vm, NULL, false);
+    return reload_profile(mgr, vm, NULL, false);
 }
 
 /* Called when hotplugging */
 static int
-AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv,
+AppArmorSetSecurityImageLabel(virSecurityManagerPtr mgr,
                               virDomainObjPtr vm, virDomainDiskDefPtr disk)
 {
     const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
@@ -635,7 +663,7 @@ AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv,
 
         /* update the profile only if it is loaded */
         if (profile_loaded(secdef->imagelabel) >= 0) {
-            if (load_profile(drv, secdef->imagelabel, vm, disk->src,
+            if (load_profile(mgr, secdef->imagelabel, vm, disk->src,
                              false) < 0) {
                 virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                      _("cannot update AppArmor profile "
@@ -654,7 +682,8 @@ AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv,
 }
 
 static int
-AppArmorSecurityVerify(virDomainDefPtr def)
+AppArmorSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                       virDomainDefPtr def)
 {
     const virSecurityLabelDefPtr secdef = &def->seclabel;
 
@@ -670,7 +699,7 @@ AppArmorSecurityVerify(virDomainDefPtr def)
 }
 
 static int
-AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+AppArmorReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainObjPtr vm ATTRIBUTE_UNUSED)
 {
     /* NOOP. Nothing to reserve with AppArmor */
@@ -678,7 +707,7 @@ AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 }
 
 static int
-AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv,
+AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
                                 virDomainObjPtr vm,
                                 virDomainHostdevDefPtr dev)
 
@@ -698,7 +727,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv,
 
     if (VIR_ALLOC(ptr) < 0)
         return -1;
-    ptr->drv = drv;
+    ptr->mgr = mgr;
     ptr->vm = vm;
 
     switch (dev->source.subsys.type) {
@@ -740,7 +769,7 @@ done:
 
 
 static int
-AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv,
+AppArmorRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
                                     virDomainObjPtr vm,
                                     virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
 
@@ -749,42 +778,57 @@ AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv,
     if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
-    return reload_profile(drv, vm, NULL, false);
+    return reload_profile(mgr, vm, NULL, false);
 }
 
 static int
-AppArmorSetSavedStateLabel(virSecurityDriverPtr drv,
+AppArmorSetSavedStateLabel(virSecurityManagerPtr mgr,
                            virDomainObjPtr vm,
                            const char *savefile)
 {
-    return reload_profile(drv, vm, savefile, true);
+    return reload_profile(mgr, vm, savefile, true);
 }
 
 
 static int
-AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv,
+AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr,
                                virDomainObjPtr vm,
                                const char *savefile ATTRIBUTE_UNUSED)
 {
-    return reload_profile(drv, vm, NULL, false);
+    return reload_profile(mgr, vm, NULL, false);
 }
 
 virSecurityDriver virAppArmorSecurityDriver = {
-    .name = SECURITY_APPARMOR_NAME,
-    .probe = AppArmorSecurityDriverProbe,
-    .open = AppArmorSecurityDriverOpen,
-    .domainSecurityVerify = AppArmorSecurityVerify,
-    .domainSetSecurityImageLabel = AppArmorSetSecurityImageLabel,
-    .domainRestoreSecurityImageLabel = AppArmorRestoreSecurityImageLabel,
-    .domainGenSecurityLabel = AppArmorGenSecurityLabel,
-    .domainReserveSecurityLabel = AppArmorReserveSecurityLabel,
-    .domainReleaseSecurityLabel = AppArmorReleaseSecurityLabel,
-    .domainGetSecurityProcessLabel = AppArmorGetSecurityProcessLabel,
-    .domainSetSecurityProcessLabel = AppArmorSetSecurityProcessLabel,
-    .domainRestoreSecurityAllLabel = AppArmorRestoreSecurityAllLabel,
-    .domainSetSecurityAllLabel = AppArmorSetSecurityAllLabel,
-    .domainSetSecurityHostdevLabel = AppArmorSetSecurityHostdevLabel,
-    .domainRestoreSecurityHostdevLabel = AppArmorRestoreSecurityHostdevLabel,
-    .domainSetSavedStateLabel = AppArmorSetSavedStateLabel,
-    .domainRestoreSavedStateLabel = AppArmorRestoreSavedStateLabel,
+    0,
+    SECURITY_APPARMOR_NAME,
+    AppArmorSecurityManagerProbe,
+    AppArmorSecurityManagerOpen,
+    AppArmorSecurityManagerClose,
+
+    AppArmorSecurityManagerGetModel,
+    AppArmorSecurityManagerGetDOI,
+
+    AppArmorSecurityVerify,
+
+    AppArmorSetSecurityImageLabel,
+    AppArmorRestoreSecurityImageLabel,
+
+    AppArmorSetSecuritySocketLabel,
+    AppArmorClearSecuritySocketLabel,
+
+    AppArmorGenSecurityLabel,
+    AppArmorReserveSecurityLabel,
+    AppArmorReleaseSecurityLabel,
+
+    AppArmorGetSecurityProcessLabel,
+    AppArmorSetSecurityProcessLabel,
+
+    AppArmorSetSecurityAllLabel,
+    AppArmorRestoreSecurityAllLabel,
+
+    AppArmorSetSecurityHostdevLabel,
+    AppArmorRestoreSecurityHostdevLabel,
+
+    AppArmorSetSavedStateLabel,
+    AppArmorRestoreSavedStateLabel,
 };
diff --git a/src/security/security_apparmor.h b/src/security/security_apparmor.h
index eb7e140..90d9ddb 100644
--- a/src/security/security_apparmor.h
+++ b/src/security/security_apparmor.h
@@ -14,6 +14,8 @@
 #ifndef __VIR_SECURITY_APPARMOR_H__
 # define __VIR_SECURITY_APPARMOR_H__
 
+#include "security_driver.h"
+
 extern virSecurityDriver virAppArmorSecurityDriver;
 
 # define AA_PREFIX  "libvirt-"
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
new file mode 100644
index 0000000..b4b9c6e
--- /dev/null
+++ b/src/security/security_dac.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * QEMU POSIX DAC security driver
+ */
+#include <config.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "security_dac.h"
+#include "virterror_internal.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "pci.h"
+#include "hostusb.h"
+#include "storage_file.h"
+
+#define VIR_FROM_THIS VIR_FROM_SECURITY
+
+typedef struct _virSecurityDACData virSecurityDACData;
+typedef virSecurityDACData *virSecurityDACDataPtr;
+
+struct _virSecurityDACData {
+    uid_t user;
+    gid_t group;
+    bool dynamicOwnership;
+};
+
+void virSecurityDACSetUser(virSecurityManagerPtr mgr,
+                           uid_t user)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    priv->user = user;
+}
+
+void virSecurityDACSetGroup(virSecurityManagerPtr mgr,
+                            gid_t group)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    priv->group = group;
+}
+
+void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
+                                       bool dynamicOwnership)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    priv->dynamicOwnership = dynamicOwnership;
+}
+
+static virSecurityDriverStatus
+virSecurityDACProbe(void)
+{
+    return SECURITY_DRIVER_ENABLE;
+}
+
+static int
+virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static const char * virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return "dac";
+}
+
+static const char * virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return "0";
+}
+
+static int
+virSecurityDACSetOwnership(const char *path, int uid, int gid)
+{
+    VIR_INFO("Setting DAC user and group on '%s' to '%d:%d'", path, uid, gid);
+
+    if (chown(path, uid, gid) < 0) {
+        struct stat sb;
+        int chown_errno = errno;
+
+        if (stat(path, &sb) >= 0) {
+            if (sb.st_uid == uid &&
+                sb.st_gid == gid) {
+                /* It's alright, there's nothing to change anyway. */
+                return 0;
+            }
+        }
+
+        if (chown_errno == EOPNOTSUPP) {
+            VIR_INFO("Setting user and group to '%d:%d' on '%s' not supported by filesystem",
+                     uid, gid, path);
+        } else if (chown_errno == EPERM) {
+            VIR_INFO("Setting user and group to '%d:%d' on '%s' not permitted",
+                     uid, gid, path);
+        } else if (chown_errno == EROFS) {
+            VIR_INFO("Setting user and group to '%d:%d' on '%s' not possible on readonly filesystem",
+                     uid, gid, path);
+        } else {
+            virReportSystemError(chown_errno,
+                                 _("unable to set user and group to '%d:%d' on '%s'"),
+                                 uid, gid, path);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int
+virSecurityDACRestoreSecurityFileLabel(const char *path)
+{
+    struct stat buf;
+    int rc = -1;
+    char *newpath = NULL;
+
+    VIR_INFO("Restoring DAC user and group on '%s'", path);
+
+    if (virFileResolveLink(path, &newpath) < 0) {
+        virReportSystemError(errno,
+                             _("cannot resolve symlink %s"), path);
+        goto err;
+    }
+
+    if (stat(newpath, &buf) != 0)
+        goto err;
+
+    /* XXX record previous ownership */
+    rc = virSecurityDACSetOwnership(newpath, 0, 0);
+
+err:
+    VIR_FREE(newpath);
+    return rc;
+}
+
+
+static int
+virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
+                                   const char *path,
+                                   size_t depth ATTRIBUTE_UNUSED,
+                                   void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityDACSetOwnership(path, priv->user, priv->group);
+}
+
+
+static int
+virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
+                                    virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                    virDomainDiskDefPtr disk)
+
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+    return virDomainDiskDefForeachPath(disk,
+                                       virSecurityManagerGetAllowDiskFormatProbing(mgr),
+                                       false,
+                                       virSecurityDACSetSecurityFileLabel,
+                                       mgr);
+}
+
+
+static int
+virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
+                                           virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                           virDomainDiskDefPtr disk,
+                                           int migrated)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+    /* Don't restore labels on readoly/shared disks, because
+     * other VMs may still be accessing these
+     * Alternatively we could iterate over all running
+     * domains and try to figure out if it is in use, but
+     * this would not work for clustered filesystems, since
+     * we can't see running VMs using the file on other nodes
+     * Safest bet is thus to skip the restore step.
+     */
+    if (disk->readonly || disk->shared)
+        return 0;
+
+    if (!disk->src)
+        return 0;
+
+    /* If we have a shared FS & doing migrated, we must not
+     * change ownership, because that kills access on the
+     * destination host which is sub-optimal for the guest
+     * VM's I/O attempts :-)
+     */
+    if (migrated) {
+        int rc = virStorageFileIsSharedFS(disk->src);
+        if (rc < 0)
+            return -1;
+        if (rc == 1) {
+            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
+                      disk->src);
+            return 0;
+        }
+    }
+
+    return virSecurityDACRestoreSecurityFileLabel(disk->src);
+}
+
+
+static int
+virSecurityDACRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
+                                        virDomainObjPtr vm,
+                                        virDomainDiskDefPtr disk)
+{
+    return virSecurityDACRestoreSecurityImageLabelInt(mgr, vm, disk, 0);
+}
+
+
+static int
+virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
+                                  const char *file,
+                                  void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityDACSetOwnership(file, priv->user, priv->group);
+}
+
+
+static int
+virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
+                                  const char *file,
+                                  void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityDACSetOwnership(file, priv->user, priv->group);
+}
+
+
+static int
+virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                      virDomainHostdevDefPtr dev)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int ret = -1;
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+        return 0;
+
+    switch (dev->source.subsys.type) {
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
+        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                                      dev->source.subsys.u.usb.device);
+
+        if (!usb)
+            goto done;
+
+        ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr);
+        usbFreeDevice(usb);
+        break;
+    }
+
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
+        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
+                                      dev->source.subsys.u.pci.bus,
+                                      dev->source.subsys.u.pci.slot,
+                                      dev->source.subsys.u.pci.function);
+
+        if (!pci)
+            goto done;
+
+        ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr);
+        pciFreeDevice(pci);
+
+        break;
+    }
+
+    default:
+        ret = 0;
+        break;
+    }
+
+done:
+    return ret;
+}
+
+
+static int
+virSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
+                                      const char *file,
+                                      void *opaque ATTRIBUTE_UNUSED)
+{
+    return virSecurityDACRestoreSecurityFileLabel(file);
+}
+
+
+static int
+virSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
+                                       const char *file,
+                                       void *opaque ATTRIBUTE_UNUSED)
+{
+    return virSecurityDACRestoreSecurityFileLabel(file);
+}
+
+
+static int
+virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
+                                           virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                           virDomainHostdevDefPtr dev)
+
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int ret = -1;
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+        return 0;
+
+    switch (dev->source.subsys.type) {
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
+        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
+                                      dev->source.subsys.u.usb.device);
+
+        if (!usb)
+            goto done;
+
+        ret = usbDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
+        usbFreeDevice(usb);
+
+        break;
+    }
+
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
+        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
+                                      dev->source.subsys.u.pci.bus,
+                                      dev->source.subsys.u.pci.slot,
+                                      dev->source.subsys.u.pci.function);
+
+        if (!pci)
+            goto done;
+
+        ret = pciDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr);
+        pciFreeDevice(pci);
+
+        break;
+    }
+
+    default:
+        ret = 0;
+        break;
+    }
+
+done:
+    return ret;
+}
+
+
+static int
+virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
+                              virDomainChrDefPtr dev)
+
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    char *in = NULL, *out = NULL;
+    int ret = -1;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+        ret = virSecurityDACSetOwnership(dev->data.file.path, priv->user, priv->group);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
+            (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
+            virReportOOMError();
+            goto done;
+        }
+        if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) ||
+            (virSecurityDACSetOwnership(out, priv->user, priv->group) < 0))
+            goto done;
+        ret = 0;
+        break;
+
+    default:
+        ret = 0;
+        break;
+    }
+
+done:
+    VIR_FREE(in);
+    VIR_FREE(out);
+    return ret;
+}
+
+static int
+virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                  virDomainChrDefPtr dev)
+{
+    char *in = NULL, *out = NULL;
+    int ret = -1;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+        ret = virSecurityDACRestoreSecurityFileLabel(dev->data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
+            (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
+            virReportOOMError();
+            goto done;
+        }
+        if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
+            (virSecurityDACRestoreSecurityFileLabel(in) < 0))
+            goto done;
+        ret = 0;
+        break;
+
+    default:
+        ret = 0;
+        break;
+    }
+
+done:
+    VIR_FREE(in);
+    VIR_FREE(out);
+    return ret;
+}
+
+
+static int
+virSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                     virDomainChrDefPtr dev,
+                                     void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+
+    return virSecurityDACRestoreChardevLabel(mgr, dev);
+}
+
+
+static int
+virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      int migrated)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int i;
+    int rc = 0;
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+
+    VIR_DEBUG("Restoring security label on %s migrated=%d",
+              vm->def->name, migrated);
+
+    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
+        if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
+                                                      vm,
+                                                      vm->def->hostdevs[i]) < 0)
+            rc = -1;
+    }
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
+                                                       vm,
+                                                       vm->def->disks[i],
+                                                       migrated) < 0)
+            rc = -1;
+    }
+
+    if (virDomainChrDefForeach(vm->def,
+                               false,
+                               virSecurityDACRestoreChardevCallback,
+                               vm) < 0)
+        rc = -1;
+
+    if (vm->def->os.kernel &&
+        virSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
+        rc = -1;
+
+    if (vm->def->os.initrd &&
+        virSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                 virDomainChrDefPtr dev,
+                                 void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+
+    return virSecurityDACSetChardevLabel(mgr, dev);
+}
+
+
+static int
+virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
+                                  virDomainObjPtr vm,
+                                  const char *stdin_path ATTRIBUTE_UNUSED)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int i;
+
+    if (!priv->dynamicOwnership)
+        return 0;
+
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        /* XXX fixme - we need to recursively label the entriy tree :-( */
+        if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR)
+            continue;
+        if (virSecurityDACSetSecurityImageLabel(mgr,
+                                                vm,
+                                                vm->def->disks[i]) < 0)
+            return -1;
+    }
+    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
+        if (virSecurityDACSetSecurityHostdevLabel(mgr,
+                                                  vm,
+                                                  vm->def->hostdevs[i]) < 0)
+            return -1;
+    }
+
+    if (virDomainChrDefForeach(vm->def,
+                               true,
+                               virSecurityDACSetChardevCallback,
+                               vm) < 0)
+        return -1;
+
+    if (vm->def->os.kernel &&
+        virSecurityDACSetOwnership(vm->def->os.kernel,
+                                    priv->user,
+                                    priv->group) < 0)
+        return -1;
+
+    if (vm->def->os.initrd &&
+        virSecurityDACSetOwnership(vm->def->os.initrd,
+                                    priv->user,
+                                    priv->group) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
+                                  virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                  const char *savefile)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityDACSetOwnership(savefile, priv->user, priv->group);
+}
+
+
+static int
+virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                      virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                      const char *savefile)
+{
+    return virSecurityDACRestoreSecurityFileLabel(savefile);
+}
+
+
+static int
+virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
+                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    DEBUG("Dropping privileges of VM to %d:%d", priv->user, priv->group);
+
+    if (priv->group) {
+        if (setregid(priv->group, priv->group) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot change to '%d' group"),
+                                 priv->group);
+            return -1;
+        }
+    }
+    if (priv->user) {
+        if (setreuid(priv->user, priv->user) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot change to '%d' user"),
+                                 priv->user);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                     virDomainDefPtr def ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACGenLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                       virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                           virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                           virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                              virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                              virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityDACSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static int
+virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                 virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+virSecurityDriver virSecurityDriverDAC = {
+    sizeof(virSecurityDACData),
+    "virDAC",
+
+    virSecurityDACProbe,
+    virSecurityDACOpen,
+    virSecurityDACClose,
+
+    virSecurityDACGetModel,
+    virSecurityDACGetDOI,
+
+    virSecurityDACVerify,
+
+    virSecurityDACSetSecurityImageLabel,
+    virSecurityDACRestoreSecurityImageLabel,
+
+    virSecurityDACSetSocketLabel,
+    virSecurityDACClearSocketLabel,
+
+    virSecurityDACGenLabel,
+    virSecurityDACReserveLabel,
+    virSecurityDACReleaseLabel,
+
+    virSecurityDACGetProcessLabel,
+    virSecurityDACSetProcessLabel,
+
+    virSecurityDACSetSecurityAllLabel,
+    virSecurityDACRestoreSecurityAllLabel,
+
+    virSecurityDACSetSecurityHostdevLabel,
+    virSecurityDACRestoreSecurityHostdevLabel,
+
+    virSecurityDACSetSavedStateLabel,
+    virSecurityDACRestoreSavedStateLabel,
+};
diff --git a/src/security/security_dac.h b/src/security/security_dac.h
new file mode 100644
index 0000000..b690236
--- /dev/null
+++ b/src/security/security_dac.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * POSIX DAC security driver
+ */
+
+#include "security_driver.h"
+
+#ifndef __VIR_SECURITY_DAC
+# define __VIR_SECURITY_DAC
+
+extern virSecurityDriver virSecurityDriverDAC;
+
+void virSecurityDACSetUser(virSecurityManagerPtr mgr,
+                           uid_t user);
+void virSecurityDACSetGroup(virSecurityManagerPtr mgr,
+                            gid_t group);
+
+void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
+                                       bool dynamic);
+
+#endif /* __VIR_SECURITY_DAC */
diff --git a/src/security/security_driver.c b/src/security/security_driver.c
index 9e32fa4..6d75dcc 100644
--- a/src/security/security_driver.c
+++ b/src/security/security_driver.c
@@ -24,116 +24,52 @@
 # include "security_apparmor.h"
 #endif
 
+#include "security_nop.h"
+
 static virSecurityDriverPtr security_drivers[] = {
 #ifdef WITH_SECDRIVER_SELINUX
-    &virSELinuxSecurityDriver,
+    &virSecurityDriverSELinux,
 #endif
 #ifdef WITH_SECDRIVER_APPARMOR
     &virAppArmorSecurityDriver,
 #endif
-    NULL
+    &virSecurityDriverNop, /* Must always be last, since it will always probe */
 };
 
-int
-virSecurityDriverVerify(virDomainDefPtr def)
-{
-    unsigned int i;
-    const virSecurityLabelDefPtr secdef = &def->seclabel;
-
-    if (!secdef->model ||
-        STREQ(secdef->model, "none"))
-        return 0;
-
-    for (i = 0; security_drivers[i] != NULL ; i++) {
-        if (STREQ(security_drivers[i]->name, secdef->model)) {
-            return security_drivers[i]->domainSecurityVerify(def);
-        }
-    }
-    virSecurityReportError(VIR_ERR_XML_ERROR,
-                           _("invalid security model '%s'"), secdef->model);
-    return -1;
-}
-
-int
-virSecurityDriverStartup(virSecurityDriverPtr *drv,
-                         const char *name,
-                         bool allowDiskFormatProbing)
+virSecurityDriverPtr virSecurityDriverLookup(const char *name)
 {
-    unsigned int i;
-
-    if (name && STREQ(name, "none"))
-        return -2;
+    virSecurityDriverPtr drv = NULL;
+    int i;
 
-    for (i = 0; security_drivers[i] != NULL ; i++) {
+    for (i = 0; i < ARRAY_CARDINALITY(security_drivers) ; i++) {
         virSecurityDriverPtr tmp = security_drivers[i];
 
-        if (name && STRNEQ(tmp->name, name))
-            continue;
-
-        switch (tmp->probe()) {
-        case SECURITY_DRIVER_ENABLE:
-            virSecurityDriverInit(tmp);
-            if (tmp->open(tmp, allowDiskFormatProbing) == -1) {
-                return -1;
-            } else {
-                *drv = tmp;
-                return 0;
+        if (name) {
+            if (STREQ(tmp->name, name)) {
+                drv = tmp;
+                break;
             }
-            break;
+        } else {
+            switch (tmp->probe()) {
+            case SECURITY_DRIVER_ENABLE:
+                drv = tmp;
+                break;
 
-        case SECURITY_DRIVER_DISABLE:
-            break;
+            case SECURITY_DRIVER_DISABLE:
+                break;
 
-        default:
-            return -1;
+            default:
+                return NULL;
+            }
         }
     }
-    return -2;
-}
-
-/*
- * Helpers
- */
-void
-virSecurityDriverInit(virSecurityDriverPtr drv)
-{
-    memset(&drv->_private, 0, sizeof drv->_private);
-}
 
-int
-virSecurityDriverSetDOI(virSecurityDriverPtr drv,
-                        const char *doi)
-{
-    if (strlen(doi) >= VIR_SECURITY_DOI_BUFLEN) {
+    if (!drv) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("%s: DOI \'%s\' is "
-                               "longer than the maximum allowed length of %d"),
-                               __func__, doi, VIR_SECURITY_DOI_BUFLEN - 1);
-        return -1;
+                               "Security driver %s not found", NULLSTR(name));
+        return NULL;
     }
-    strcpy(drv->_private.doi, doi);
-    return 0;
-}
-
-const char *
-virSecurityDriverGetDOI(virSecurityDriverPtr drv)
-{
-    return drv->_private.doi;
-}
 
-const char *
-virSecurityDriverGetModel(virSecurityDriverPtr drv)
-{
-    return drv->name;
+    return drv;
 }
 
-void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
-                                                bool allowDiskFormatProbing)
-{
-    drv->_private.allowDiskFormatProbing = allowDiskFormatProbing;
-}
-
-bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv)
-{
-    return drv->_private.allowDiskFormatProbing;
-}
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index d768f32..e5a8d41 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -16,6 +16,8 @@
 # include "internal.h"
 # include "domain_conf.h"
 
+# include "security_manager.h"
+
 /*
  * Return values for security driver probing: the driver will determine
  * whether it should be enabled or disabled.
@@ -29,104 +31,91 @@ typedef enum {
 typedef struct _virSecurityDriver virSecurityDriver;
 typedef virSecurityDriver *virSecurityDriverPtr;
 
-typedef struct _virSecurityDriverState virSecurityDriverState;
-typedef virSecurityDriverState *virSecurityDriverStatePtr;
-
 typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void);
-typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv,
-                                      bool allowDiskFormatProbing);
-typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDriverOpen) (virSecurityManagerPtr mgr);
+typedef int (*virSecurityDriverClose) (virSecurityManagerPtr mgr);
+
+typedef const char *(*virSecurityDriverGetModel) (virSecurityManagerPtr mgr);
+typedef const char *(*virSecurityDriverGetDOI) (virSecurityManagerPtr mgr);
+
+typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityManagerPtr mgr,
                                                    virDomainObjPtr vm,
                                                    virDomainDiskDefPtr disk);
-typedef int (*virSecurityDomainSetSocketLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetSocketLabel) (virSecurityManagerPtr mgr,
                                                 virDomainObjPtr vm);
-typedef int (*virSecurityDomainClearSocketLabel)(virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainClearSocketLabel)(virSecurityManagerPtr mgr,
                                                 virDomainObjPtr vm);
-typedef int (*virSecurityDomainSetImageLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetImageLabel) (virSecurityManagerPtr mgr,
                                                virDomainObjPtr vm,
                                                virDomainDiskDefPtr disk);
-typedef int (*virSecurityDomainRestoreHostdevLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainRestoreHostdevLabel) (virSecurityManagerPtr mgr,
                                                      virDomainObjPtr vm,
                                                      virDomainHostdevDefPtr dev);
-typedef int (*virSecurityDomainSetHostdevLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetHostdevLabel) (virSecurityManagerPtr mgr,
                                                  virDomainObjPtr vm,
                                                  virDomainHostdevDefPtr dev);
-typedef int (*virSecurityDomainSetSavedStateLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetSavedStateLabel) (virSecurityManagerPtr mgr,
                                                     virDomainObjPtr vm,
                                                     const char *savefile);
-typedef int (*virSecurityDomainRestoreSavedStateLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainRestoreSavedStateLabel) (virSecurityManagerPtr mgr,
                                                         virDomainObjPtr vm,
                                                         const char *savefile);
-typedef int (*virSecurityDomainGenLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainGenLabel) (virSecurityManagerPtr mgr,
                                           virDomainObjPtr sec);
-typedef int (*virSecurityDomainReserveLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainReserveLabel) (virSecurityManagerPtr mgr,
                                               virDomainObjPtr sec);
-typedef int (*virSecurityDomainReleaseLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainReleaseLabel) (virSecurityManagerPtr mgr,
                                               virDomainObjPtr sec);
-typedef int (*virSecurityDomainSetAllLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetAllLabel) (virSecurityManagerPtr mgr,
                                              virDomainObjPtr sec,
                                              const char *stdin_path);
-typedef int (*virSecurityDomainRestoreAllLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainRestoreAllLabel) (virSecurityManagerPtr mgr,
                                                  virDomainObjPtr vm,
                                                  int migrated);
-typedef int (*virSecurityDomainGetProcessLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainGetProcessLabel) (virSecurityManagerPtr mgr,
                                                  virDomainObjPtr vm,
                                                  virSecurityLabelPtr sec);
-typedef int (*virSecurityDomainSetProcessLabel) (virSecurityDriverPtr drv,
+typedef int (*virSecurityDomainSetProcessLabel) (virSecurityManagerPtr mgr,
                                                  virDomainObjPtr vm);
-typedef int (*virSecurityDomainSecurityVerify) (virDomainDefPtr def);
+typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr,
+                                                virDomainDefPtr def);
+
 
 struct _virSecurityDriver {
+    size_t privateDataLen;
     const char *name;
     virSecurityDriverProbe probe;
     virSecurityDriverOpen open;
+    virSecurityDriverClose close;
+
+    virSecurityDriverGetModel getModel;
+    virSecurityDriverGetDOI getDOI;
+
     virSecurityDomainSecurityVerify domainSecurityVerify;
+
+    virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
     virSecurityDomainRestoreImageLabel domainRestoreSecurityImageLabel;
+
     virSecurityDomainSetSocketLabel domainSetSecuritySocketLabel;
     virSecurityDomainClearSocketLabel domainClearSecuritySocketLabel;
-    virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
+
     virSecurityDomainGenLabel domainGenSecurityLabel;
     virSecurityDomainReserveLabel domainReserveSecurityLabel;
     virSecurityDomainReleaseLabel domainReleaseSecurityLabel;
+
     virSecurityDomainGetProcessLabel domainGetSecurityProcessLabel;
     virSecurityDomainSetProcessLabel domainSetSecurityProcessLabel;
+
     virSecurityDomainSetAllLabel domainSetSecurityAllLabel;
     virSecurityDomainRestoreAllLabel domainRestoreSecurityAllLabel;
-    virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
+
     virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel;
+    virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
+
     virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
     virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
-
-    /*
-     * This is internally managed driver state and should only be accessed
-     * via helpers below.
-     */
-    struct {
-        char doi[VIR_SECURITY_DOI_BUFLEN];
-        bool allowDiskFormatProbing;
-    } _private;
 };
 
-/* Global methods */
-int virSecurityDriverStartup(virSecurityDriverPtr *drv,
-                             const char *name,
-                             bool allowDiskFormatProbing);
-
-int
-virSecurityDriverVerify(virDomainDefPtr def);
-
-# define virSecurityReportError(code, ...)                           \
-    virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__,   \
-                         __FUNCTION__, __LINE__, __VA_ARGS__)
-
-/* Helpers */
-void virSecurityDriverInit(virSecurityDriverPtr drv);
-int virSecurityDriverSetDOI(virSecurityDriverPtr drv,
-                            const char *doi);
-void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
-                                                bool allowDiskFormatProbing);
-const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv);
-const char *virSecurityDriverGetModel(virSecurityDriverPtr drv);
-bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv);
+virSecurityDriverPtr virSecurityDriverLookup(const char *name);
 
 #endif /* __VIR_SECURITY_H__ */
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
new file mode 100644
index 0000000..7ab6e37
--- /dev/null
+++ b/src/security/security_manager.c
@@ -0,0 +1,291 @@
+
+#include <config.h>
+
+
+#include "security_driver.h"
+#include "security_stack.h"
+#include "security_dac.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_SECURITY
+
+
+struct _virSecurityManager {
+    virSecurityDriverPtr drv;
+    bool allowDiskFormatProbing;
+};
+
+static virSecurityManagerPtr virSecurityManagerNewDriver(virSecurityDriverPtr drv,
+                                                         bool allowDiskFormatProbing)
+{
+    virSecurityManagerPtr mgr;
+
+    if (VIR_ALLOC_VAR(mgr, char, drv->privateDataLen) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    mgr->drv = drv;
+    mgr->allowDiskFormatProbing = allowDiskFormatProbing;
+
+    if (drv->open(mgr) < 0) {
+        virSecurityManagerFree(mgr);
+        return NULL;
+    }
+
+    return mgr;
+}
+
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary,
+                                                 virSecurityManagerPtr secondary)
+{
+    virSecurityManagerPtr mgr =
+        virSecurityManagerNewDriver(&virSecurityDriverStack,
+                                    virSecurityManagerGetAllowDiskFormatProbing(primary));
+
+    virSecurityStackSetPrimary(mgr, primary);
+    virSecurityStackSetSecondary(mgr, secondary);
+
+    return mgr;
+}
+
+virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user,
+                                               gid_t group,
+                                               bool allowDiskFormatProbing,
+                                               bool dynamicOwnership)
+{
+    virSecurityManagerPtr mgr =
+        virSecurityManagerNewDriver(&virSecurityDriverDAC,
+                                    allowDiskFormatProbing);
+
+    virSecurityDACSetUser(mgr, user);
+    virSecurityDACSetGroup(mgr, group);
+    virSecurityDACSetDynamicOwnership(mgr, dynamicOwnership);
+
+    return mgr;
+}
+
+virSecurityManagerPtr virSecurityManagerNew(const char *name,
+                                            bool allowDiskFormatProbing)
+{
+    virSecurityDriverPtr drv = virSecurityDriverLookup(name);
+    if (!drv)
+        return NULL;
+
+    return virSecurityManagerNewDriver(drv, allowDiskFormatProbing);
+}
+
+
+void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr)
+{
+    return mgr + sizeof(mgr);
+}
+
+
+void virSecurityManagerFree(virSecurityManagerPtr mgr)
+{
+    if (!mgr)
+        return;
+
+    if (mgr->drv->close)
+        mgr->drv->close(mgr);
+
+    VIR_FREE(mgr);
+}
+
+const char *
+virSecurityManagerGetDOI(virSecurityManagerPtr mgr)
+{
+    if (mgr->drv->getDOI)
+        return mgr->drv->getDOI(mgr);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+const char *
+virSecurityManagerGetModel(virSecurityManagerPtr mgr)
+{
+    if (mgr->drv->getModel)
+        return mgr->drv->getModel(mgr);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+bool virSecurityManagerGetAllowDiskFormatProbing(virSecurityManagerPtr mgr)
+{
+    return mgr->allowDiskFormatProbing;
+}
+
+int virSecurityManagerRestoreImageLabel(virSecurityManagerPtr mgr,
+                                        virDomainObjPtr vm,
+                                        virDomainDiskDefPtr disk)
+{
+    if (mgr->drv->domainRestoreSecurityImageLabel)
+        return mgr->drv->domainRestoreSecurityImageLabel(mgr, vm, disk);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetSocketLabel(virSecurityManagerPtr mgr,
+                                     virDomainObjPtr vm)
+{
+    if (mgr->drv->domainSetSecuritySocketLabel)
+        return mgr->drv->domainSetSecuritySocketLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerClearSocketLabel(virSecurityManagerPtr mgr,
+                                       virDomainObjPtr vm)
+{
+    if (mgr->drv->domainClearSecuritySocketLabel)
+        return mgr->drv->domainClearSecuritySocketLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetImageLabel(virSecurityManagerPtr mgr,
+                                    virDomainObjPtr vm,
+                                    virDomainDiskDefPtr disk)
+{
+    if (mgr->drv->domainSetSecurityImageLabel)
+        return mgr->drv->domainSetSecurityImageLabel(mgr, vm, disk);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerRestoreHostdevLabel(virSecurityManagerPtr mgr,
+                                          virDomainObjPtr vm,
+                                          virDomainHostdevDefPtr dev)
+{
+    if (mgr->drv->domainRestoreSecurityHostdevLabel)
+        return mgr->drv->domainRestoreSecurityHostdevLabel(mgr, vm, dev);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetHostdevLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      virDomainHostdevDefPtr dev)
+{
+    if (mgr->drv->domainSetSecurityHostdevLabel)
+        return mgr->drv->domainSetSecurityHostdevLabel(mgr, vm, dev);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetSavedStateLabel(virSecurityManagerPtr mgr,
+                                         virDomainObjPtr vm,
+                                         const char *savefile)
+{
+    if (mgr->drv->domainSetSavedStateLabel)
+        return mgr->drv->domainSetSavedStateLabel(mgr, vm, savefile);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr,
+                                             virDomainObjPtr vm,
+                                             const char *savefile)
+{
+    if (mgr->drv->domainRestoreSavedStateLabel)
+        return mgr->drv->domainRestoreSavedStateLabel(mgr, vm, savefile);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerGenLabel(virSecurityManagerPtr mgr,
+                               virDomainObjPtr vm)
+{
+    if (mgr->drv->domainGenSecurityLabel)
+        return mgr->drv->domainGenSecurityLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr,
+                                   virDomainObjPtr vm)
+{
+    if (mgr->drv->domainReserveSecurityLabel)
+        return mgr->drv->domainReserveSecurityLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr,
+                                   virDomainObjPtr vm)
+{
+    if (mgr->drv->domainReleaseSecurityLabel)
+        return mgr->drv->domainReleaseSecurityLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr,
+                                  virDomainObjPtr vm,
+                                  const char *stdin_path)
+{
+    if (mgr->drv->domainSetSecurityAllLabel)
+        return mgr->drv->domainSetSecurityAllLabel(mgr, vm, stdin_path);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerRestoreAllLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      int migrated)
+{
+    if (mgr->drv->domainRestoreSecurityAllLabel)
+        return mgr->drv->domainRestoreSecurityAllLabel(mgr, vm, migrated);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerGetProcessLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      virSecurityLabelPtr sec)
+{
+    if (mgr->drv->domainGetSecurityProcessLabel)
+        return mgr->drv->domainGetSecurityProcessLabel(mgr, vm, sec);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm)
+{
+    if (mgr->drv->domainSetSecurityProcessLabel)
+        return mgr->drv->domainSetSecurityProcessLabel(mgr, vm);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+int virSecurityManagerVerify(virSecurityManagerPtr mgr,
+                             virDomainDefPtr def)
+{
+    if (mgr->drv->domainSecurityVerify)
+        return mgr->drv->domainSecurityVerify(mgr, def);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
new file mode 100644
index 0000000..c0ef84f
--- /dev/null
+++ b/src/security/security_manager.h
@@ -0,0 +1,74 @@
+
+#ifndef VIR_SECURITY_MANAGER_H__
+#define VIR_SECURITY_MANAGER_H__
+
+# define virSecurityReportError(code, ...)                           \
+    virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__,   \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
+
+typedef struct _virSecurityManager virSecurityManager;
+typedef virSecurityManager *virSecurityManagerPtr;
+
+virSecurityManagerPtr virSecurityManagerNew(const char *name,
+                                            bool allowDiskFormatProbing);
+
+virSecurityManagerPtr virSecurityManagerNewStack(virSecurityManagerPtr primary,
+                                                 virSecurityManagerPtr secondary);
+
+virSecurityManagerPtr virSecurityManagerNewDAC(uid_t user,
+                                               gid_t group,
+                                               bool allowDiskFormatProbing,
+                                               bool dynamicOwnership);
+
+void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr);
+
+void virSecurityManagerFree(virSecurityManagerPtr mgr);
+
+const char *virSecurityManagerGetDOI(virSecurityManagerPtr mgr);
+const char *virSecurityManagerGetModel(virSecurityManagerPtr mgr);
+bool virSecurityManagerGetAllowDiskFormatProbing(virSecurityManagerPtr mgr);
+
+int virSecurityManagerRestoreImageLabel(virSecurityManagerPtr mgr,
+                                        virDomainObjPtr vm,
+                                        virDomainDiskDefPtr disk);
+int virSecurityManagerSetSocketLabel(virSecurityManagerPtr mgr,
+                                     virDomainObjPtr vm);
+int virSecurityManagerClearSocketLabel(virSecurityManagerPtr mgr,
+                                       virDomainObjPtr vm);
+int virSecurityManagerSetImageLabel(virSecurityManagerPtr mgr,
+                                    virDomainObjPtr vm,
+                                    virDomainDiskDefPtr disk);
+int virSecurityManagerRestoreHostdevLabel(virSecurityManagerPtr mgr,
+                                          virDomainObjPtr vm,
+                                          virDomainHostdevDefPtr dev);
+int virSecurityManagerSetHostdevLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      virDomainHostdevDefPtr dev);
+int virSecurityManagerSetSavedStateLabel(virSecurityManagerPtr mgr,
+                                         virDomainObjPtr vm,
+                                         const char *savefile);
+int virSecurityManagerRestoreSavedStateLabel(virSecurityManagerPtr mgr,
+                                             virDomainObjPtr vm,
+                                             const char *savefile);
+int virSecurityManagerGenLabel(virSecurityManagerPtr mgr,
+                               virDomainObjPtr sec);
+int virSecurityManagerReserveLabel(virSecurityManagerPtr mgr,
+                                   virDomainObjPtr sec);
+int virSecurityManagerReleaseLabel(virSecurityManagerPtr mgr,
+                                   virDomainObjPtr sec);
+int virSecurityManagerSetAllLabel(virSecurityManagerPtr mgr,
+                                  virDomainObjPtr sec,
+                                  const char *stdin_path);
+int virSecurityManagerRestoreAllLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      int migrated);
+int virSecurityManagerGetProcessLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      virSecurityLabelPtr sec);
+int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm);
+int virSecurityManagerVerify(virSecurityManagerPtr mgr,
+                             virDomainDefPtr def);
+
+#endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_nop.c b/src/security/security_nop.c
new file mode 100644
index 0000000..947cf55
--- /dev/null
+++ b/src/security/security_nop.c
@@ -0,0 +1,168 @@
+
+
+#include <config.h>
+
+#include "security_nop.h"
+
+static virSecurityDriverStatus virSecurityDriverProbeNop(void)
+{
+    return SECURITY_DRIVER_ENABLE;
+}
+
+static int virSecurityDriverOpenNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDriverCloseNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static const char * virSecurityDriverGetModelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return "none";
+}
+
+static const char * virSecurityDriverGetDOINop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return "0";
+}
+
+static int virSecurityDomainRestoreImageLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                                 virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                                 virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetSocketLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                              virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainClearSocketLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                                virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetImageLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                             virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                             virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainRestoreHostdevLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                                   virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                                   virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetHostdevLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                               virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                               virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetSavedStateLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                                  virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                                  const char *savefile ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+static int virSecurityDomainRestoreSavedStateLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                                      virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                                      const char *savefile ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainGenLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                        virDomainObjPtr sec ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainReserveLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                            virDomainObjPtr sec ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainReleaseLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                            virDomainObjPtr sec ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetAllLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                           virDomainObjPtr sec ATTRIBUTE_UNUSED,
+                                           const char *stdin_path ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainRestoreAllLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                               virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                               int migrated ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+static int virSecurityDomainGetProcessLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                               virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                                               virSecurityLabelPtr sec ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainSetProcessLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                      virDomainDefPtr def ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+virSecurityDriver virSecurityDriverNop = {
+    0,
+    "nop",
+    virSecurityDriverProbeNop,
+    virSecurityDriverOpenNop,
+    virSecurityDriverCloseNop,
+
+    virSecurityDriverGetModelNop,
+    virSecurityDriverGetDOINop,
+
+    virSecurityDomainVerifyNop,
+
+    virSecurityDomainSetImageLabelNop,
+    virSecurityDomainRestoreImageLabelNop,
+
+    virSecurityDomainSetSocketLabelNop,
+    virSecurityDomainClearSocketLabelNop,
+
+    virSecurityDomainGenLabelNop,
+    virSecurityDomainReserveLabelNop,
+    virSecurityDomainReleaseLabelNop,
+
+    virSecurityDomainGetProcessLabelNop,
+    virSecurityDomainSetProcessLabelNop,
+
+    virSecurityDomainSetAllLabelNop,
+    virSecurityDomainRestoreAllLabelNop,
+
+    virSecurityDomainSetHostdevLabelNop,
+    virSecurityDomainRestoreHostdevLabelNop,
+
+    virSecurityDomainSetSavedStateLabelNop,
+    virSecurityDomainRestoreSavedStateLabelNop,
+};
diff --git a/src/security/security_nop.h b/src/security/security_nop.h
new file mode 100644
index 0000000..714e646
--- /dev/null
+++ b/src/security/security_nop.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ */
+#ifndef __VIR_SECURITY_NOP_H__
+# define __VIR_SECURITY_NOP_H__
+
+#include "security_driver.h"
+
+extern virSecurityDriver virSecurityDriverNop;
+
+#endif /* __VIR_SECURITY_NOP_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 996177a..3f3fe90 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -157,7 +157,7 @@ SELinuxInitialize(void)
 }
 
 static int
-SELinuxGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                         virDomainObjPtr vm)
 {
     int rc = -1;
@@ -222,7 +222,7 @@ done:
 }
 
 static int
-SELinuxReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm)
 {
     security_context_t pctx;
@@ -267,20 +267,34 @@ SELinuxSecurityDriverProbe(void)
 }
 
 static int
-SELinuxSecurityDriverOpen(virSecurityDriverPtr drv,
-                          bool allowDiskFormatProbing)
+SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return SELinuxInitialize();
+}
+
+static int
+SELinuxSecurityDriverClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static const char *SELinuxSecurityGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return SECURITY_SELINUX_NAME;
+}
+
+static const char *SELinuxSecurityGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
 {
     /*
      * Where will the DOI come from?  SELinux configuration, or qemu
      * configuration? For the moment, we'll just set it to "0".
      */
-    virSecurityDriverSetDOI(drv, SECURITY_SELINUX_VOID_DOI);
-    virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
-    return SELinuxInitialize();
+    return SECURITY_SELINUX_VOID_DOI;
 }
 
 static int
-SELinuxGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
                                virSecurityLabelPtr sec)
 {
@@ -393,7 +407,7 @@ err:
 }
 
 static int
-SELinuxRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                     virDomainObjPtr vm,
                                     virDomainDiskDefPtr disk,
                                     int migrated)
@@ -438,11 +452,11 @@ SELinuxRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxRestoreSecurityImageLabel(virSecurityDriverPtr drv,
+SELinuxRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
                                  virDomainObjPtr vm,
                                  virDomainDiskDefPtr disk)
 {
-    return SELinuxRestoreSecurityImageLabelInt(drv, vm, disk, 0);
+    return SELinuxRestoreSecurityImageLabelInt(mgr, vm, disk, 0);
 }
 
 
@@ -476,13 +490,13 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
 }
 
 static int
-SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv,
+SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
                              virDomainObjPtr vm,
                              virDomainDiskDefPtr disk)
 
 {
     const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
-    bool allowDiskFormatProbing = virSecurityDriverGetAllowDiskFormatProbing(drv);
+    bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
 
     if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
@@ -516,7 +530,7 @@ SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
 }
 
 static int
-SELinuxSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
                                virDomainHostdevDefPtr dev)
 
@@ -585,7 +599,7 @@ SELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
 }
 
 static int
-SELinuxRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                    virDomainObjPtr vm,
                                    virDomainHostdevDefPtr dev)
 
@@ -734,7 +748,7 @@ SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
                                int migrated ATTRIBUTE_UNUSED)
 {
@@ -748,13 +762,13 @@ SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
         return 0;
 
     for (i = 0 ; i < vm->def->nhostdevs ; i++) {
-        if (SELinuxRestoreSecurityHostdevLabel(drv,
+        if (SELinuxRestoreSecurityHostdevLabel(mgr,
                                                vm,
                                                vm->def->hostdevs[i]) < 0)
             rc = -1;
     }
     for (i = 0 ; i < vm->def->ndisks ; i++) {
-        if (SELinuxRestoreSecurityImageLabelInt(drv,
+        if (SELinuxRestoreSecurityImageLabelInt(mgr,
                                                 vm,
                                                 vm->def->disks[i],
                                                 migrated) < 0)
@@ -779,7 +793,7 @@ SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 }
 
 static int
-SELinuxReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm)
 {
     const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
@@ -803,7 +817,7 @@ SELinuxReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                           virDomainObjPtr vm,
                           const char *savefile)
 {
@@ -817,7 +831,7 @@ SELinuxSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                               virDomainObjPtr vm,
                               const char *savefile)
 {
@@ -831,9 +845,19 @@ SELinuxRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxSecurityVerify(virDomainDefPtr def)
+SELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                      virDomainDefPtr def)
 {
     const virSecurityLabelDefPtr secdef = &def->seclabel;
+    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("security label driver mismatch: "
+                                 "'%s' model configured for domain, but "
+                                 "hypervisor driver is '%s'."),
+                               secdef->model, virSecurityManagerGetModel(mgr));
+        return -1;
+    }
+
     if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
         if (security_check_context(secdef->label) != 0) {
             virSecurityReportError(VIR_ERR_XML_ERROR,
@@ -845,7 +869,7 @@ SELinuxSecurityVerify(virDomainDefPtr def)
 }
 
 static int
-SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv,
+SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr,
                                virDomainObjPtr vm)
 {
     /* TODO: verify DOI */
@@ -854,12 +878,12 @@ SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv,
     if (vm->def->seclabel.label == NULL)
         return 0;
 
-    if (!STREQ(drv->name, secdef->model)) {
+    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
                                  "'%s' model configured for domain, but "
                                  "hypervisor driver is '%s'."),
-                               secdef->model, drv->name);
+                               secdef->model, virSecurityManagerGetModel(mgr));
         if (security_getenforce() == 1)
             return -1;
     }
@@ -876,7 +900,7 @@ SELinuxSetSecurityProcessLabel(virSecurityDriverPtr drv,
 }
 
 static int
-SELinuxSetSecuritySocketLabel(virSecurityDriverPtr drv,
+SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
                                virDomainObjPtr vm)
 {
     /* TODO: verify DOI */
@@ -889,12 +913,12 @@ SELinuxSetSecuritySocketLabel(virSecurityDriverPtr drv,
     if (vm->def->seclabel.label == NULL)
         return 0;
 
-    if (!STREQ(drv->name, secdef->model)) {
+    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
                                  "'%s' model configured for domain, but "
                                  "hypervisor driver is '%s'."),
-                               secdef->model, drv->name);
+                               secdef->model, virSecurityManagerGetModel(mgr));
         goto done;
     }
 
@@ -947,7 +971,7 @@ done:
 }
 
 static int
-SELinuxClearSecuritySocketLabel(virSecurityDriverPtr drv,
+SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
                                 virDomainObjPtr vm)
 {
     /* TODO: verify DOI */
@@ -956,12 +980,12 @@ SELinuxClearSecuritySocketLabel(virSecurityDriverPtr drv,
     if (vm->def->seclabel.label == NULL)
         return 0;
 
-    if (!STREQ(drv->name, secdef->model)) {
+    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("security label driver mismatch: "
                                  "'%s' model configured for domain, but "
                                  "hypervisor driver is '%s'."),
-                               secdef->model, drv->name);
+                               secdef->model, virSecurityManagerGetModel(mgr));
         if (security_getenforce() == 1)
             return -1;
     }
@@ -989,7 +1013,7 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
 
 
 static int
-SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv,
+SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
                            virDomainObjPtr vm,
                            const char *stdin_path)
 {
@@ -1006,12 +1030,12 @@ SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv,
                      vm->def->disks[i]->src, vm->def->disks[i]->dst);
             continue;
         }
-        if (SELinuxSetSecurityImageLabel(drv,
+        if (SELinuxSetSecurityImageLabel(mgr,
                                          vm, vm->def->disks[i]) < 0)
             return -1;
     }
     for (i = 0 ; i < vm->def->nhostdevs ; i++) {
-        if (SELinuxSetSecurityHostdevLabel(drv,
+        if (SELinuxSetSecurityHostdevLabel(mgr,
                                            vm,
                                            vm->def->hostdevs[i]) < 0)
             return -1;
@@ -1041,24 +1065,37 @@ SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv,
     return 0;
 }
 
-virSecurityDriver virSELinuxSecurityDriver = {
-    .name                       = SECURITY_SELINUX_NAME,
-    .probe                      = SELinuxSecurityDriverProbe,
-    .open                       = SELinuxSecurityDriverOpen,
-    .domainSecurityVerify       = SELinuxSecurityVerify,
-    .domainSetSecurityImageLabel = SELinuxSetSecurityImageLabel,
-    .domainSetSecuritySocketLabel     = SELinuxSetSecuritySocketLabel,
-    .domainClearSecuritySocketLabel     = SELinuxClearSecuritySocketLabel,
-    .domainRestoreSecurityImageLabel = SELinuxRestoreSecurityImageLabel,
-    .domainGenSecurityLabel     = SELinuxGenSecurityLabel,
-    .domainReserveSecurityLabel     = SELinuxReserveSecurityLabel,
-    .domainReleaseSecurityLabel     = SELinuxReleaseSecurityLabel,
-    .domainGetSecurityProcessLabel     = SELinuxGetSecurityProcessLabel,
-    .domainSetSecurityProcessLabel     = SELinuxSetSecurityProcessLabel,
-    .domainRestoreSecurityAllLabel = SELinuxRestoreSecurityAllLabel,
-    .domainSetSecurityAllLabel     = SELinuxSetSecurityAllLabel,
-    .domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel,
-    .domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel,
-    .domainSetSavedStateLabel = SELinuxSetSavedStateLabel,
-    .domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel,
+virSecurityDriver virSecurityDriverSELinux = {
+    0,
+    SECURITY_SELINUX_NAME,
+    SELinuxSecurityDriverProbe,
+    SELinuxSecurityDriverOpen,
+    SELinuxSecurityDriverClose,
+
+    SELinuxSecurityGetModel,
+    SELinuxSecurityGetDOI,
+
+    SELinuxSecurityVerify,
+
+    SELinuxSetSecurityImageLabel,
+    SELinuxRestoreSecurityImageLabel,
+
+    SELinuxSetSecuritySocketLabel,
+    SELinuxClearSecuritySocketLabel,
+
+    SELinuxGenSecurityLabel,
+    SELinuxReserveSecurityLabel,
+    SELinuxReleaseSecurityLabel,
+
+    SELinuxGetSecurityProcessLabel,
+    SELinuxSetSecurityProcessLabel,
+
+    SELinuxSetSecurityAllLabel,
+    SELinuxRestoreSecurityAllLabel,
+
+    SELinuxSetSecurityHostdevLabel,
+    SELinuxRestoreSecurityHostdevLabel,
+
+    SELinuxSetSavedStateLabel,
+    SELinuxRestoreSavedStateLabel,
 };
diff --git a/src/security/security_selinux.h b/src/security/security_selinux.h
index 056ba75..aa67421 100644
--- a/src/security/security_selinux.h
+++ b/src/security/security_selinux.h
@@ -13,6 +13,6 @@
 #ifndef __VIR_SECURITY_SELINUX_H__
 # define __VIR_SECURITY_SELINUX_H__
 
-extern virSecurityDriver virSELinuxSecurityDriver;
+extern virSecurityDriver virSecurityDriverSELinux;
 
 #endif /* __VIR_SECURITY_SELINUX_H__ */
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
new file mode 100644
index 0000000..9b3753a
--- /dev/null
+++ b/src/security/security_stack.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * QEMU stacked security driver
+ */
+
+#include <config.h>
+
+#include "security_stack.h"
+
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_SECURITY
+
+typedef struct _virSecurityStackData virSecurityStackData;
+typedef virSecurityStackData *virSecurityStackDataPtr;
+
+struct _virSecurityStackData {
+    virSecurityManagerPtr primary;
+    virSecurityManagerPtr secondary;
+};
+
+void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
+                                virSecurityManagerPtr primary)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    priv->primary = primary;
+}
+
+void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
+                                  virSecurityManagerPtr secondary)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    priv->secondary = secondary;
+}
+
+static virSecurityDriverStatus
+virSecurityStackProbe(void)
+{
+    return SECURITY_DRIVER_ENABLE;
+}
+
+static int
+virSecurityStackOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virSecurityStackClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static const char * virSecurityStackGetModel(virSecurityManagerPtr mgr)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityManagerGetModel(priv->primary);
+}
+
+static const char * virSecurityStackGetDOI(virSecurityManagerPtr mgr)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+
+    return virSecurityManagerGetDOI(priv->primary);
+}
+
+static int
+virSecurityStackVerify(virSecurityManagerPtr mgr,
+                       virDomainDefPtr def)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerVerify(priv->primary, def) < 0)
+        rc = -1;
+
+#if 0
+    if (virSecurityManagerVerify(priv->secondary, def) < 0)
+        rc = -1;
+#endif
+
+    return rc;
+}
+
+
+static int
+virSecurityStackGenLabel(virSecurityManagerPtr mgr,
+                         virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerGenLabel(priv->primary, vm) < 0)
+        rc = -1;
+#if 0
+    if (virSecurityManagerGenLabel(priv->secondary, vm) < 0)
+        rc = -1;
+#endif
+
+    return rc;
+}
+
+
+static int
+virSecurityStackReleaseLabel(virSecurityManagerPtr mgr,
+                             virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0)
+        rc = -1;
+#if 0
+    if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
+        rc = -1;
+#endif
+
+    return rc;
+}
+
+
+static int
+virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
+                             virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerReserveLabel(priv->primary, vm) < 0)
+        rc = -1;
+#if 0
+    if (virSecurityManagerReserveLabel(priv->secondary, vm) < 0)
+        rc = -1;
+#endif
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
+                                      virDomainObjPtr vm,
+                                      virDomainDiskDefPtr disk)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetImageLabel(priv->secondary, vm, disk) < 0)
+        rc = -1;
+    if (virSecurityManagerSetImageLabel(priv->primary, vm, disk) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
+                                          virDomainObjPtr vm,
+                                          virDomainDiskDefPtr disk)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerRestoreImageLabel(priv->secondary, vm, disk) < 0)
+        rc = -1;
+    if (virSecurityManagerRestoreImageLabel(priv->primary, vm, disk) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
+                                        virDomainObjPtr vm,
+                                        virDomainHostdevDefPtr dev)
+
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetHostdevLabel(priv->secondary, vm, dev) < 0)
+        rc = -1;
+    if (virSecurityManagerSetHostdevLabel(priv->primary, vm, dev) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
+                                            virDomainObjPtr vm,
+                                            virDomainHostdevDefPtr dev)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerRestoreHostdevLabel(priv->secondary, vm, dev) < 0)
+        rc = -1;
+    if (virSecurityManagerRestoreHostdevLabel(priv->primary, vm, dev) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
+                                    virDomainObjPtr vm,
+                                    const char *stdin_path)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetAllLabel(priv->secondary, vm, stdin_path) < 0)
+        rc = -1;
+    if (virSecurityManagerSetAllLabel(priv->primary, vm, stdin_path) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
+                                        virDomainObjPtr vm,
+                                        int migrated)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerRestoreAllLabel(priv->secondary, vm, migrated) < 0)
+        rc = -1;
+    if (virSecurityManagerRestoreAllLabel(priv->primary, vm, migrated) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
+                                   virDomainObjPtr vm,
+                                   const char *savefile)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetSavedStateLabel(priv->secondary, vm, savefile) < 0)
+        rc = -1;
+    if (virSecurityManagerSetSavedStateLabel(priv->primary, vm, savefile) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
+                                       virDomainObjPtr vm,
+                                       const char *savefile)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerRestoreSavedStateLabel(priv->secondary, vm, savefile) < 0)
+        rc = -1;
+    if (virSecurityManagerRestoreSavedStateLabel(priv->primary, vm, savefile) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
+                                virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetProcessLabel(priv->secondary, vm) < 0)
+        rc = -1;
+    if (virSecurityManagerSetProcessLabel(priv->primary, vm) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+static int
+virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
+                                virDomainObjPtr vm,
+                                virSecurityLabelPtr seclabel)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+#if 0
+    if (virSecurityManagerGetProcessLabel(priv->secondary, vm, seclabel) < 0)
+        rc = -1;
+#endif
+    if (virSecurityManagerGetProcessLabel(priv->primary, vm, seclabel) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
+                               virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetSocketLabel(priv->secondary, vm) < 0)
+        rc = -1;
+    if (virSecurityManagerSetSocketLabel(priv->primary, vm) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+static int
+virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
+                                 virDomainObjPtr vm)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerClearSocketLabel(priv->secondary, vm) < 0)
+        rc = -1;
+    if (virSecurityManagerClearSocketLabel(priv->primary, vm) < 0)
+        rc = -1;
+
+    return rc;
+}
+
+
+virSecurityDriver virSecurityDriverStack = {
+    sizeof(virSecurityStackData),
+    "stack",
+    virSecurityStackProbe,
+    virSecurityStackOpen,
+    virSecurityStackClose,
+
+    virSecurityStackGetModel,
+    virSecurityStackGetDOI,
+
+    virSecurityStackVerify,
+
+    virSecurityStackSetSecurityImageLabel,
+    virSecurityStackRestoreSecurityImageLabel,
+
+    virSecurityStackSetSocketLabel,
+    virSecurityStackClearSocketLabel,
+
+    virSecurityStackGenLabel,
+    virSecurityStackReserveLabel,
+    virSecurityStackReleaseLabel,
+
+    virSecurityStackGetProcessLabel,
+    virSecurityStackSetProcessLabel,
+
+    virSecurityStackSetSecurityAllLabel,
+    virSecurityStackRestoreSecurityAllLabel,
+
+    virSecurityStackSetSecurityHostdevLabel,
+    virSecurityStackRestoreSecurityHostdevLabel,
+
+    virSecurityStackSetSavedStateLabel,
+    virSecurityStackRestoreSavedStateLabel,
+};
diff --git a/src/security/security_stack.h b/src/security/security_stack.h
new file mode 100644
index 0000000..c924842
--- /dev/null
+++ b/src/security/security_stack.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * QEMU stacked security driver
+ */
+
+#include "security_driver.h"
+
+#ifndef __VIR_SECURITY_STACK
+# define __VIR_SECURITY_STACK
+
+extern virSecurityDriver virSecurityDriverStack;
+
+void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
+                                virSecurityManagerPtr primary);
+void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
+                                  virSecurityManagerPtr secondary);
+
+#endif /* __VIR_SECURITY_DAC */
-- 
1.7.2.3




More information about the libvir-list mailing list