[libvirt] [PATCH 6/7] Add support for sVirt in the LXC driver

Daniel P. Berrange berrange at redhat.com
Wed Jan 11 16:33:35 UTC 2012


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

For the sake of backwards compat, LXC guests are *not*
confined by default. This is because it is not practical
to dynamically relabel containers using large filesystem
trees. Applications can create confined containers though,
by giving suitable XML configs

* src/Makefile.am: Link libvirt_lxc to security drivers
* src/lxc/libvirtd_lxc.aug, src/lxc/lxc_conf.h,
  src/lxc/lxc_conf.c, src/lxc/lxc.conf,
  src/lxc/test_libvirtd_lxc.aug: Config file handling for
  security driver
* src/lxc/lxc_driver.c: Wire up security driver functions
* src/lxc/lxc_controller.c: Add a '--security' flag to
  specify which security driver to activate
* src/lxc/lxc_container.c, src/lxc/lxc_container.h: Set
  the process label just before exec'ing init.
---
 src/Makefile.am               |   13 +++
 src/lxc/libvirtd_lxc.aug      |   15 +++-
 src/lxc/lxc.conf              |   18 ++++
 src/lxc/lxc_conf.c            |   62 ++++++++++++--
 src/lxc/lxc_conf.h            |    8 ++-
 src/lxc/lxc_container.c       |    9 ++-
 src/lxc/lxc_container.h       |    2 +
 src/lxc/lxc_controller.c      |   28 +++++-
 src/lxc/lxc_driver.c          |  198 ++++++++++++++++++++++++++++++++++++++++-
 src/lxc/test_libvirtd_lxc.aug |    2 +
 10 files changed, 340 insertions(+), 15 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 0a1221a..a4688a1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1501,7 +1501,14 @@ libvirt_lxc_SOURCES =						\
 		$(DOMAIN_CONF_SOURCES)				\
 		$(SECRET_CONF_SOURCES)				\
 		$(CPU_CONF_SOURCES)				\
+		$(SECURITY_DRIVER_SOURCES)			\
 		$(NWFILTER_PARAM_CONF_SOURCES)
+if WITH_SECDRIVER_SELINUX
+libvirt_lxc_SOURCES += $(SECURITY_DRIVER_SELINUX_SOURCES)
+endif
+if WITH_SECDRIVER_APPARMOR
+libvirt_lxc_SOURCES += $(SECURITY_DRIVER_APPARMOR_SOURCES)
+endif
 libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
 libvirt_lxc_LDADD = $(CAPNG_LIBS) $(YAJL_LIBS) \
 		$(LIBXML_LIBS) $(NUMACTL_LIBS) $(THREAD_LIBS) \
@@ -1511,6 +1518,9 @@ libvirt_lxc_LDADD = $(CAPNG_LIBS) $(YAJL_LIBS) \
 if WITH_DTRACE
 libvirt_lxc_LDADD += probes.o
 endif
+if WITH_SECDRIVER_SELINUX
+libvirt_lxc_LDADD += $(SELINUX_LIBS)
+endif
 libvirt_lxc_CFLAGS =				\
 		$(LIBPARTED_CFLAGS)		\
 		$(NUMACTL_CFLAGS)		\
@@ -1523,6 +1533,9 @@ if HAVE_LIBBLKID
 libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
 libvirt_lxc_LDADD += $(BLKID_LIBS)
 endif
+if WITH_SECDRIVER_SELINUX
+libvirt_lxc_CFLAGS += $(SELINUX_CFLAGS)
+endif
 endif
 endif
 EXTRA_DIST += $(LXC_CONTROLLER_SOURCES)
diff --git a/src/lxc/libvirtd_lxc.aug b/src/lxc/libvirtd_lxc.aug
index 10f25e4..be6402c 100644
--- a/src/lxc/libvirtd_lxc.aug
+++ b/src/lxc/libvirtd_lxc.aug
@@ -7,13 +7,26 @@ module Libvirtd_lxc =
    let value_sep   = del /[ \t]*=[ \t]*/  " = "
    let indent = del /[ \t]*/ ""
 
+   let array_sep  = del /,[ \t\n]*/ ", "
+   let array_start = del /\[[ \t\n]*/ "[ "
+   let array_end = del /\]/ "]"
+
+   let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
    let bool_val = store /0|1/
+   let int_val = store /[0-9]+/
+   let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
+   let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
 
+   let str_entry       (kw:string) = [ key kw . value_sep . str_val ]
    let bool_entry      (kw:string) = [ key kw . value_sep . bool_val ]
-
+   let int_entry       (kw:string) = [ key kw . value_sep . int_val ]
+   let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
 
    (* Config entry grouped by function - same order as example config *)
    let log_entry = bool_entry "log_with_libvirtd"
+                 | str_entry "security_driver"
+                 | bool_entry "security_default_confined"
+                 | bool_entry "security_require_confined"
 
    (* Each enty in the config is one of the following three ... *)
    let entry = log_entry
diff --git a/src/lxc/lxc.conf b/src/lxc/lxc.conf
index 7a5066f..ca3f4c6 100644
--- a/src/lxc/lxc.conf
+++ b/src/lxc/lxc.conf
@@ -11,3 +11,21 @@
 # This is disabled by default, uncomment below to enable it.
 #
 # log_with_libvirtd = 1
+
+
+# The default security driver is SELinux. If SELinux is disabled
+# on the host, then the security driver will automatically disable
+# itself. If you wish to disable QEMU SELinux security driver while
+# leaving SELinux enabled for the host in general, then set this
+# to 'none' instead.
+#
+# security_driver = "selinux"
+
+# If set to non-zero, then the default security labelling
+# will make guests confined. If set to zero, then guests
+# will be unconfined by default. Defaults to zero
+# security_default_confined = 1
+
+# If set to non-zero, then attempts to create unconfined
+# guests will be blocked. Defaults to zero.
+# security_require_confined = 1
\ No newline at end of file
diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index e842736..72547c4 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -49,7 +49,7 @@ static int lxcDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
 
 
 /* Functions */
-virCapsPtr lxcCapsInit(void)
+virCapsPtr lxcCapsInit(lxc_driver_t *driver)
 {
     struct utsname utsname;
     virCapsPtr caps;
@@ -127,8 +127,30 @@ virCapsPtr lxcCapsInit(void)
     /* LXC Requires an emulator in the XML */
     virCapabilitiesSetEmulatorRequired(caps);
 
+    if (driver) {
+        /* Security driver data */
+        const char *doi, *model;
+
+        doi = virSecurityManagerGetDOI(driver->securityManager);
+        model = virSecurityManagerGetModel(driver->securityManager);
+        if (STRNEQ(model, "none")) {
+            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);
+    } else {
+        VIR_INFO("No driver, not initializing security driver");
+    }
+
     return caps;
 
+no_memory:
+    virReportOOMError();
+
 error:
     virCapabilitiesFree(caps);
     return NULL;
@@ -140,6 +162,9 @@ int lxcLoadDriverConfig(lxc_driver_t *driver)
     virConfPtr conf;
     virConfValuePtr p;
 
+    driver->securityDefaultConfined = false;
+    driver->securityRequireConfined = false;
+
     /* Set the container configuration directory */
     if ((driver->configDir = strdup(LXC_CONFIG_DIR)) == NULL)
         goto no_memory;
@@ -161,14 +186,39 @@ int lxcLoadDriverConfig(lxc_driver_t *driver)
     if (!conf)
         goto done;
 
+#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) {               \
+        lxcError(VIR_ERR_INTERNAL_ERROR,                                \
+                 "%s: %s: expected type " #typ,                         \
+                 filename, (name));                                     \
+        virConfFree(conf);                                              \
+        return -1;                                                      \
+    }
+
     p = virConfGetValue(conf, "log_with_libvirtd");
-    if (p) {
-        if (p->type != VIR_CONF_LONG)
-            VIR_WARN("lxcLoadDriverConfig: invalid setting: log_with_libvirtd");
-        else
-            driver->log_libvirtd = p->l;
+    CHECK_TYPE ("log_with_libvirtd", VIR_CONF_LONG);
+    if (p) driver->log_libvirtd = p->l;
+
+    p = virConfGetValue (conf, "security_driver");
+    CHECK_TYPE ("security_driver", VIR_CONF_STRING);
+    if (p && p->str) {
+        if (!(driver->securityDriverName = strdup(p->str))) {
+            virReportOOMError();
+            virConfFree(conf);
+            return -1;
+        }
     }
 
+    p = virConfGetValue (conf, "security_default_confined");
+    CHECK_TYPE ("security_default_confined", VIR_CONF_LONG);
+    if (p) driver->securityDefaultConfined = p->l;
+
+    p = virConfGetValue (conf, "security_require_confined");
+    CHECK_TYPE ("security_require_confined", VIR_CONF_LONG);
+    if (p) driver->securityRequireConfined = p->l;
+
+
+#undef CHECK_TYPE
+
     virConfFree(conf);
 
 done:
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index b124330..ebdc173 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -33,6 +33,7 @@
 # include "capabilities.h"
 # include "threads.h"
 # include "cgroup.h"
+# include "security/security_manager.h"
 # include "configmake.h"
 
 # define LXC_CONFIG_DIR SYSCONFDIR "/libvirt/lxc"
@@ -57,6 +58,11 @@ struct __lxc_driver {
 
     virDomainEventStatePtr domainEventState;
 
+    char *securityDriverName;
+    bool securityDefaultConfined;
+    bool securityRequireConfined;
+    virSecurityManagerPtr securityManager;
+
     /* Mapping of 'char *uuidstr' -> virConnectPtr
      * of guests which will be automatically killed
      * when the virConnectPtr is closed*/
@@ -64,7 +70,7 @@ struct __lxc_driver {
 };
 
 int lxcLoadDriverConfig(lxc_driver_t *driver);
-virCapsPtr lxcCapsInit(void);
+virCapsPtr lxcCapsInit(lxc_driver_t *driver);
 
 # define lxcError(code, ...)                                             \
     virReportErrorHelper(VIR_FROM_LXC, code, __FILE__,                   \
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 3fb7d06..4df0b55 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -91,6 +91,7 @@ typedef char lxc_message_t;
 typedef struct __lxc_child_argv lxc_child_argv_t;
 struct __lxc_child_argv {
     virDomainDefPtr config;
+    virSecurityManagerPtr securityDriver;
     unsigned int nveths;
     char **veths;
     int monitor;
@@ -1273,6 +1274,10 @@ static int lxcContainerChild( void *data )
         goto cleanup;
     }
 
+    VIR_DEBUG("Setting up security labeling");
+    if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)
+        goto cleanup;
+
     ret = 0;
 cleanup:
     VIR_FREE(ttyPath);
@@ -1335,6 +1340,7 @@ const char *lxcContainerGetAlt32bitArch(const char *arch)
  * Returns PID of container on success or -1 in case of error
  */
 int lxcContainerStart(virDomainDefPtr def,
+                      virSecurityManagerPtr securityDriver,
                       unsigned int nveths,
                       char **veths,
                       int control,
@@ -1346,7 +1352,8 @@ int lxcContainerStart(virDomainDefPtr def,
     int cflags;
     int stacksize = getpagesize() * 4;
     char *stack, *stacktop;
-    lxc_child_argv_t args = { def, nveths, veths, control,
+    lxc_child_argv_t args = { def, securityDriver,
+                              nveths, veths, control,
                               ttyPaths, nttyPaths, handshakefd};
 
     /* allocate a stack for the container */
diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index ffeda5e..77fb9b2 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -25,6 +25,7 @@
 # define LXC_CONTAINER_H
 
 # include "lxc_conf.h"
+# include "security/security_manager.h"
 
 enum {
     LXC_CONTAINER_FEATURE_NET = (1 << 0),
@@ -49,6 +50,7 @@ int lxcContainerSendContinue(int control);
 int lxcContainerWaitForContinue(int control);
 
 int lxcContainerStart(virDomainDefPtr def,
+                      virSecurityManagerPtr securityDriver,
                       unsigned int nveths,
                       char **veths,
                       int control,
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index bb936ee..6bc54b7 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1267,6 +1267,7 @@ cleanup:
 
 static int
 lxcControllerRun(virDomainDefPtr def,
+                 virSecurityManagerPtr securityDriver,
                  unsigned int nveths,
                  char **veths,
                  int monitor,
@@ -1421,6 +1422,7 @@ lxcControllerRun(virDomainDefPtr def,
         goto cleanup;
 
     if ((container = lxcContainerStart(def,
+                                       securityDriver,
                                        nveths,
                                        veths,
                                        control[1],
@@ -1529,11 +1531,13 @@ int main(int argc, char *argv[])
         { "veth",   1, NULL, 'v' },
         { "console", 1, NULL, 'c' },
         { "handshakefd", 1, NULL, 's' },
+        { "security", 1, NULL, 'S' },
         { "help", 0, NULL, 'h' },
         { 0, 0, 0, 0 },
     };
     int *ttyFDs = NULL;
     size_t nttyFDs = 0;
+    virSecurityManagerPtr securityDriver = NULL;
 
     if (setlocale(LC_ALL, "") == NULL ||
         bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
@@ -1545,7 +1549,7 @@ int main(int argc, char *argv[])
     while (1) {
         int c;
 
-        c = getopt_long(argc, argv, "dn:v:m:c:s:h",
+        c = getopt_long(argc, argv, "dn:v:m:c:s:h:S:",
                        options, NULL);
 
         if (c == -1)
@@ -1593,6 +1597,14 @@ int main(int argc, char *argv[])
             }
             break;
 
+        case 'S':
+            if (!(securityDriver = virSecurityManagerNew(optarg, false, false, false))) {
+                fprintf(stderr, "Cannot create security manager '%s'",
+                        optarg);
+                goto cleanup;
+            }
+            break;
+
         case 'h':
         case '?':
             fprintf(stderr, "\n");
@@ -1605,12 +1617,20 @@ int main(int argc, char *argv[])
             fprintf(stderr, "  -c FD, --console FD\n");
             fprintf(stderr, "  -v VETH, --veth VETH\n");
             fprintf(stderr, "  -s FD, --handshakefd FD\n");
+            fprintf(stderr, "  -S NAME, --security NAME\n");
             fprintf(stderr, "  -h, --help\n");
             fprintf(stderr, "\n");
             goto cleanup;
         }
     }
 
+    if (securityDriver == NULL) {
+        if (!(securityDriver = virSecurityManagerNew("none", false, false, false))) {
+            fprintf(stderr, "%s: cannot initialize nop security manager", argv[0]);
+            goto cleanup;
+        }
+    }
+
 
     if (name == NULL) {
         fprintf(stderr, "%s: missing --name argument for configuration\n", argv[0]);
@@ -1630,7 +1650,7 @@ int main(int argc, char *argv[])
 
     virEventRegisterDefaultImpl();
 
-    if ((caps = lxcCapsInit()) == NULL)
+    if ((caps = lxcCapsInit(NULL)) == NULL)
         goto cleanup;
 
     if ((configFile = virDomainConfigFile(LXC_STATE_DIR,
@@ -1696,10 +1716,10 @@ int main(int argc, char *argv[])
         goto cleanup;
     }
 
-    rc = lxcControllerRun(def, nveths, veths, monitor, client,
+    rc = lxcControllerRun(def, securityDriver,
+                          nveths, veths, monitor, client,
                           ttyFDs, nttyFDs, handshakefd);
 
-
 cleanup:
     if (def)
         virPidFileDelete(LXC_STATE_DIR, def->name);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 3baff19..0cd1ffd 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -440,6 +440,9 @@ static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml)
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto cleanup;
 
+    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
+        goto cleanup;
+
     if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
         goto cleanup;
 
@@ -1425,7 +1428,21 @@ static int lxcMonitorClient(lxc_driver_t * driver,
         return -1;
     }
 
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+    if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) {
+        VIR_ERROR(_("Failed to set security context for monitor for %s"),
+                  vm->def->name);
+        goto error;
+    }
+
+    fd = socket(PF_UNIX, SOCK_STREAM, 0);
+
+    if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) {
+        VIR_ERROR(_("Failed to clear security context for monitor for %s"),
+                  vm->def->name);
+        goto error;
+    }
+
+    if (fd < 0) {
         virReportSystemError(errno, "%s",
                              _("Failed to create client socket"));
         goto error;
@@ -1468,6 +1485,16 @@ static int lxcVmTerminate(lxc_driver_t *driver,
         return -1;
     }
 
+    virSecurityManagerRestoreAllLabel(driver->securityManager,
+                                      vm->def, false);
+    virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
+    /* Clear out dynamically assigned labels */
+    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+        VIR_FREE(vm->def->seclabel.model);
+        VIR_FREE(vm->def->seclabel.label);
+        VIR_FREE(vm->def->seclabel.imagelabel);
+    }
+
     if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) == 0) {
         rc = virCgroupKillPainfully(group);
         if (rc < 0) {
@@ -1598,6 +1625,12 @@ lxcBuildControllerCmd(lxc_driver_t *driver,
         virCommandAddArgFormat(cmd, "%d", ttyFDs[i]);
         virCommandPreserveFD(cmd, ttyFDs[i]);
     }
+
+    if (driver->securityDriverName) {
+        virCommandAddArg(cmd, "--security");
+        virCommandAddArg(cmd, driver->securityDriverName);
+    }
+
     virCommandAddArg(cmd, "--handshake");
     virCommandAddArgFormat(cmd, "%d", handshakefd);
     virCommandAddArg(cmd, "--background");
@@ -1792,6 +1825,24 @@ static int lxcVmStart(virConnectPtr conn,
         virReportOOMError();
         goto cleanup;
     }
+
+    /* If you are using a SecurityDriver with dynamic labelling,
+       then generate a security label for isolation */
+    VIR_DEBUG("Generating domain security label (if required)");
+    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DEFAULT)
+        vm->def->seclabel.type = VIR_DOMAIN_SECLABEL_NONE;
+
+    if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) {
+        virDomainAuditSecurityLabel(vm, false);
+        goto cleanup;
+    }
+    virDomainAuditSecurityLabel(vm, true);
+
+    VIR_DEBUG("Setting domain security labels");
+    if (virSecurityManagerSetAllLabel(driver->securityManager,
+                                      vm->def, NULL) < 0)
+        goto cleanup;
+
     for (i = 0 ; i < vm->def->nconsoles ; i++)
         ttyFDs[i] = -1;
 
@@ -1947,6 +1998,16 @@ cleanup:
     if (rc != 0) {
         VIR_FORCE_CLOSE(priv->monitor);
         virDomainConfVMNWFilterTeardown(vm);
+
+        virSecurityManagerRestoreAllLabel(driver->securityManager,
+                                          vm->def, false);
+        virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
+        /* Clear out dynamically assigned labels */
+        if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+            VIR_FREE(vm->def->seclabel.model);
+            VIR_FREE(vm->def->seclabel.label);
+            VIR_FREE(vm->def->seclabel.imagelabel);
+        }
     }
     for (i = 0 ; i < nttyFDs ; i++)
         VIR_FORCE_CLOSE(ttyFDs[i]);
@@ -2071,6 +2132,9 @@ lxcDomainCreateAndStart(virConnectPtr conn,
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto cleanup;
 
+    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
+        goto cleanup;
+
     if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
         goto cleanup;
 
@@ -2115,6 +2179,105 @@ cleanup:
 }
 
 
+static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
+{
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+    memset(seclabel, 0, sizeof(*seclabel));
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(VIR_ERR_NO_DOMAIN,
+                 _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!virDomainVirtTypeToString(vm->def->virtType)) {
+        lxcError(VIR_ERR_INTERNAL_ERROR,
+                 _("unknown virt type in domain definition '%d'"),
+                 vm->def->virtType);
+        goto cleanup;
+    }
+
+    /*
+     * Theoretically, the pid can be replaced during this operation and
+     * return the label of a different process.  If atomicity is needed,
+     * further validation will be required.
+     *
+     * Comment from Dan Berrange:
+     *
+     *   Well the PID as stored in the virDomainObjPtr can't be changed
+     *   because you've got a locked object.  The OS level PID could have
+     *   exited, though and in extreme circumstances have cycled through all
+     *   PIDs back to ours. We could sanity check that our PID still exists
+     *   after reading the label, by checking that our FD connecting to the
+     *   LXC monitor hasn't seen SIGHUP/ERR on poll().
+     */
+    if (virDomainObjIsActive(vm)) {
+        if (virSecurityManagerGetProcessLabel(driver->securityManager,
+                                              vm->def, vm->pid, seclabel) < 0) {
+            lxcError(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("Failed to get security label"));
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    lxcDriverUnlock(driver);
+    return ret;
+}
+
+static int lxcNodeGetSecurityModel(virConnectPtr conn,
+                                   virSecurityModelPtr secmodel)
+{
+    lxc_driver_t *driver = conn->privateData;
+    char *p;
+    int ret = 0;
+
+    lxcDriverLock(driver);
+    memset(secmodel, 0, sizeof(*secmodel));
+
+    /* NULL indicates no driver, which we treat as
+     * success, but simply return no data in *secmodel */
+    if (driver->caps->host.secModel.model == NULL)
+        goto cleanup;
+
+    p = driver->caps->host.secModel.model;
+    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
+        lxcError(VIR_ERR_INTERNAL_ERROR,
+                 _("security model string exceeds max %d bytes"),
+                 VIR_SECURITY_MODEL_BUFLEN-1);
+        ret = -1;
+        goto cleanup;
+    }
+    strcpy(secmodel->model, p);
+
+    p = driver->caps->host.secModel.doi;
+    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
+        lxcError(VIR_ERR_INTERNAL_ERROR,
+                 _("security DOI string exceeds max %d bytes"),
+                 VIR_SECURITY_DOI_BUFLEN-1);
+        ret = -1;
+        goto cleanup;
+    }
+    strcpy(secmodel->doi, p);
+
+cleanup:
+    lxcDriverUnlock(driver);
+    return ret;
+}
+
+
 static int
 lxcDomainEventRegister(virConnectPtr conn,
                        virConnectDomainEventCallback callback,
@@ -2363,6 +2526,10 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
                  lxcMonitorEvent,
                  vm, NULL)) < 0)
             goto error;
+
+        if (virSecurityManagerReserveLabel(driver->securityManager,
+                                           vm->def, vm->pid) < 0)
+            goto error;
     } else {
         vm->def->id = -1;
         VIR_FORCE_CLOSE(priv->monitor);
@@ -2379,6 +2546,27 @@ error:
 }
 
 
+static int
+lxcSecurityInit(lxc_driver_t *driver)
+{
+    virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName,
+                                                      false,
+                                                      driver->securityDefaultConfined,
+                                                      driver->securityRequireConfined);
+    if (!mgr)
+        goto error;
+
+    driver->securityManager = mgr;
+
+    return 0;
+
+error:
+    VIR_ERROR(_("Failed to initialize security drivers"));
+    virSecurityManagerFree(mgr);
+    return -1;
+}
+
+
 static int lxcStartup(int privileged)
 {
     char *ld;
@@ -2439,7 +2627,10 @@ static int lxcStartup(int privileged)
     if (lxcLoadDriverConfig(lxc_driver) < 0)
         goto cleanup;
 
-    if ((lxc_driver->caps = lxcCapsInit()) == NULL)
+    if (lxcSecurityInit(lxc_driver) < 0)
+        goto cleanup;
+
+    if ((lxc_driver->caps = lxcCapsInit(lxc_driver)) == NULL)
         goto cleanup;
 
     lxc_driver->caps->privateDataAllocFunc = lxcDomainObjPrivateAlloc;
@@ -2531,6 +2722,7 @@ static int lxcShutdown(void)
     lxcProcessAutoDestroyShutdown(lxc_driver);
 
     virCapabilitiesFree(lxc_driver->caps);
+    virSecurityManagerFree(lxc_driver->securityManager);
     VIR_FREE(lxc_driver->configDir);
     VIR_FREE(lxc_driver->autostartDir);
     VIR_FREE(lxc_driver->stateDir);
@@ -3859,6 +4051,8 @@ static virDriver lxcDriver = {
     .domainGetBlkioParameters = lxcDomainGetBlkioParameters, /* 0.9.8 */
     .domainGetInfo = lxcDomainGetInfo, /* 0.4.2 */
     .domainGetState = lxcDomainGetState, /* 0.9.2 */
+    .domainGetSecurityLabel = lxcDomainGetSecurityLabel, /* 0.9.4 */
+    .nodeGetSecurityModel = lxcNodeGetSecurityModel, /* 0.9.4 */
     .domainGetXMLDesc = lxcDomainGetXMLDesc, /* 0.4.2 */
     .listDefinedDomains = lxcListDefinedDomains, /* 0.4.2 */
     .numOfDefinedDomains = lxcNumDefinedDomains, /* 0.4.2 */
diff --git a/src/lxc/test_libvirtd_lxc.aug b/src/lxc/test_libvirtd_lxc.aug
index e757b82..f8544a0 100644
--- a/src/lxc/test_libvirtd_lxc.aug
+++ b/src/lxc/test_libvirtd_lxc.aug
@@ -13,6 +13,7 @@ module Test_libvirtd_lxc =
 # This is disabled by default, uncomment below to enable it.
 #
 log_with_libvirtd = 1
+security_driver = \"selinux\"
 "
 
    test Libvirtd_lxc.lns get conf =
@@ -29,3 +30,4 @@ log_with_libvirtd = 1
 { "#comment" = "This is disabled by default, uncomment below to enable it." }
 { "#comment" = "" }
 { "log_with_libvirtd" = "1" }
+{ "security_driver" = "selinux" }
-- 
1.7.7.5




More information about the libvir-list mailing list