mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
Add support for sVirt in the LXC driver
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.
This commit is contained in:
parent
b170eb99f5
commit
0f01192e7e
@ -1506,7 +1506,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) \
|
||||
@ -1516,6 +1523,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) \
|
||||
@ -1528,6 +1538,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)
|
||||
|
@ -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
|
||||
|
@ -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 labeling
|
||||
# will make guests confined. If set to zero, then guests
|
||||
# will be unconfined by default. Defaults to 0.
|
||||
# security_default_confined = 1
|
||||
|
||||
# If set to non-zero, then attempts to create unconfined
|
||||
# guests will be blocked. Defaults to 0.
|
||||
# security_require_confined = 1
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
#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");
|
||||
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:
|
||||
|
@ -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__, \
|
||||
|
@ -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;
|
||||
@ -1297,6 +1298,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);
|
||||
@ -1359,6 +1364,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,
|
||||
@ -1370,7 +1376,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 */
|
||||
|
@ -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,
|
||||
|
@ -1361,6 +1361,7 @@ cleanup:
|
||||
|
||||
static int
|
||||
lxcControllerRun(virDomainDefPtr def,
|
||||
virSecurityManagerPtr securityDriver,
|
||||
unsigned int nveths,
|
||||
char **veths,
|
||||
int monitor,
|
||||
@ -1515,6 +1516,7 @@ lxcControllerRun(virDomainDefPtr def,
|
||||
goto cleanup;
|
||||
|
||||
if ((container = lxcContainerStart(def,
|
||||
securityDriver,
|
||||
nveths,
|
||||
veths,
|
||||
control[1],
|
||||
@ -1623,11 +1625,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 ||
|
||||
@ -1639,7 +1643,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)
|
||||
@ -1687,6 +1691,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");
|
||||
@ -1699,12 +1711,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]);
|
||||
@ -1724,7 +1744,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,
|
||||
@ -1790,10 +1810,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);
|
||||
|
@ -441,6 +441,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;
|
||||
|
||||
@ -1394,7 +1397,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;
|
||||
@ -1437,6 +1454,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) {
|
||||
@ -1567,6 +1594,10 @@ lxcBuildControllerCmd(lxc_driver_t *driver,
|
||||
virCommandAddArgFormat(cmd, "%d", ttyFDs[i]);
|
||||
virCommandPreserveFD(cmd, ttyFDs[i]);
|
||||
}
|
||||
|
||||
if (driver->securityDriverName)
|
||||
virCommandAddArgPair(cmd, "--security", driver->securityDriverName);
|
||||
|
||||
virCommandAddArg(cmd, "--handshake");
|
||||
virCommandAddArgFormat(cmd, "%d", handshakefd);
|
||||
virCommandAddArg(cmd, "--background");
|
||||
@ -1761,6 +1792,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;
|
||||
|
||||
@ -1916,6 +1965,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]);
|
||||
@ -2040,6 +2099,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;
|
||||
|
||||
@ -2084,6 +2146,102 @@ 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;
|
||||
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;
|
||||
|
||||
if (!virStrcpy(secmodel->model, driver->caps->host.secModel.model,
|
||||
VIR_SECURITY_MODEL_BUFLEN)) {
|
||||
lxcError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("security model string exceeds max %d bytes"),
|
||||
VIR_SECURITY_MODEL_BUFLEN - 1);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!virStrcpy(secmodel->doi, driver->caps->host.secModel.doi,
|
||||
VIR_SECURITY_DOI_BUFLEN)) {
|
||||
lxcError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("security DOI string exceeds max %d bytes"),
|
||||
VIR_SECURITY_DOI_BUFLEN-1);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
lxcDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lxcDomainEventRegister(virConnectPtr conn,
|
||||
virConnectDomainEventCallback callback,
|
||||
@ -2332,6 +2490,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);
|
||||
@ -2348,6 +2510,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;
|
||||
@ -2408,7 +2591,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;
|
||||
@ -2500,6 +2686,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);
|
||||
@ -3671,6 +3858,8 @@ static virDriver lxcDriver = {
|
||||
.domainGetBlkioParameters = lxcDomainGetBlkioParameters, /* 0.9.8 */
|
||||
.domainGetInfo = lxcDomainGetInfo, /* 0.4.2 */
|
||||
.domainGetState = lxcDomainGetState, /* 0.9.2 */
|
||||
.domainGetSecurityLabel = lxcDomainGetSecurityLabel, /* 0.9.10 */
|
||||
.nodeGetSecurityModel = lxcNodeGetSecurityModel, /* 0.9.10 */
|
||||
.domainGetXMLDesc = lxcDomainGetXMLDesc, /* 0.4.2 */
|
||||
.listDefinedDomains = lxcListDefinedDomains, /* 0.4.2 */
|
||||
.numOfDefinedDomains = lxcNumDefinedDomains, /* 0.4.2 */
|
||||
|
@ -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" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user