From: "Daniel P. Berrange" <berrange(a)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