From: Daniel Walsh <dwalsh@xxxxxxxxxx> Currently the SELinux driver stores its state in a set of global variables. This switches it to use a private data struct instead. This will enable different instances to have their own data. Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/security/security_selinux.c | 173 ++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 67 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 4bd33a5..7202e71 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 Red Hat, Inc. + * Copyright (C) 2008-2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,12 +33,30 @@ #include "storage_file.h" #include "virfile.h" #include "virrandom.h" +#include "util.h" +#include "conf.h" #define VIR_FROM_THIS VIR_FROM_SECURITY -static char default_domain_context[1024]; -static char default_content_context[1024]; -static char default_image_context[1024]; +#define MAX_CONTEXT 1024 + +typedef struct _virSecuritySELinuxData virSecuritySELinuxData; +typedef virSecuritySELinuxData *virSecuritySELinuxDataPtr; + +typedef struct _virSecuritySELinuxCallbackData virSecuritySELinuxCallbackData; +typedef virSecuritySELinuxCallbackData *virSecuritySELinuxCallbackDataPtr; + +struct _virSecuritySELinuxData { + char *domain_context; + char *file_context; + char *content_context; +}; + +struct _virSecuritySELinuxCallbackData { + virSecurityManagerPtr manager; + virSecurityLabelDefPtr secdef; +}; + #define SECURITY_SELINUX_VOID_DOI "0" #define SECURITY_SELINUX_NAME "selinux" @@ -109,60 +127,51 @@ err: } static int -SELinuxInitialize(void) +SELinuxInitialize(virSecurityManagerPtr mgr) { - char *ptr = NULL; - int fd = 0; + char *ptr; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); - fd = open(selinux_virtual_domain_context_path(), O_RDONLY); - if (fd < 0) { + if (virFileReadAll(selinux_virtual_domain_context_path(), MAX_CONTEXT, &(data->domain_context)) < 0) { virReportSystemError(errno, - _("cannot open SELinux virtual domain context file '%s'"), + _("cannot read SELinux virtual domain context file '%s'"), selinux_virtual_domain_context_path()); - return -1; + goto error; } - if (saferead(fd, default_domain_context, sizeof(default_domain_context)) < 0) { - virReportSystemError(errno, - _("cannot read SELinux virtual domain context file %s"), - selinux_virtual_domain_context_path()); - VIR_FORCE_CLOSE(fd); - return -1; - } - VIR_FORCE_CLOSE(fd); - - ptr = strchrnul(default_domain_context, '\n'); - *ptr = '\0'; - - if ((fd = open(selinux_virtual_image_context_path(), O_RDONLY)) < 0) { - virReportSystemError(errno, - _("cannot open SELinux virtual image context file %s"), - selinux_virtual_image_context_path()); - return -1; - } + ptr = strchrnul(data->domain_context, '\n'); + if (ptr) + *ptr = '\0'; - if (saferead(fd, default_image_context, sizeof(default_image_context)) < 0) { + if (virFileReadAll(selinux_virtual_image_context_path(), 2*MAX_CONTEXT, &(data->file_context)) < 0) { virReportSystemError(errno, _("cannot read SELinux virtual image context file %s"), selinux_virtual_image_context_path()); - VIR_FORCE_CLOSE(fd); - return -1; + goto error; } - VIR_FORCE_CLOSE(fd); - ptr = strchrnul(default_image_context, '\n'); - if (*ptr == '\n') { + ptr = strchrnul(data->file_context, '\n'); + if (ptr && *ptr == '\n') { *ptr = '\0'; - strcpy(default_content_context, ptr+1); - ptr = strchrnul(default_content_context, '\n'); - if (*ptr == '\n') + data->content_context = strdup(ptr+1); + if (!data->content_context) + goto error; + ptr = strchrnul(data->content_context, '\n'); + if (ptr && *ptr == '\n') *ptr = '\0'; } + return 0; + +error: + VIR_FREE(data->domain_context); + VIR_FREE(data->file_context); + VIR_FREE(data->content_context); + return -1; } static int -SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +SELinuxGenSecurityLabel(virSecurityManagerPtr mgr, virDomainDefPtr def) { int rc = -1; @@ -172,7 +181,9 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, int c2 = 0; context_t ctx = NULL; const char *range; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); + VIR_DEBUG("SELinuxGenSecurityLabel %s", virSecurityManagerGetDriver(mgr)); if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) && !def->seclabel.baselabel && def->seclabel.model) { @@ -202,6 +213,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, return rc; } + VIR_DEBUG("SELinuxGenSecurityLabel %d", def->seclabel.type); + switch (def->seclabel.type) { case VIR_DOMAIN_SECLABEL_STATIC: if (!(ctx = context_new(def->seclabel.label)) ) { @@ -245,7 +258,7 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, def->seclabel.label = SELinuxGenNewContext(def->seclabel.baselabel ? def->seclabel.baselabel : - default_domain_context, mcs); + data->domain_context, mcs); if (! def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); @@ -264,13 +277,11 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, goto cleanup; } - if (!def->seclabel.norelabel) { - def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs); - if (!def->seclabel.imagelabel) { - virSecurityReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot generate selinux context for %s"), mcs); - goto cleanup; - } + def->seclabel.imagelabel = SELinuxGenNewContext(data->file_context, mcs); + if (!def->seclabel.imagelabel) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot generate selinux context for %s"), mcs); + goto cleanup; } if (!def->seclabel.model && @@ -344,22 +355,39 @@ err: } - static int -SELinuxSecurityDriverProbe(const char *virtDriver ATTRIBUTE_UNUSED) +SELinuxSecurityDriverProbe(const char *virtDriver) { - return is_selinux_enabled() ? SECURITY_DRIVER_ENABLE : SECURITY_DRIVER_DISABLE; + if (!is_selinux_enabled()) + return SECURITY_DRIVER_DISABLE; + + if (virtDriver && STREQ(virtDriver, "LXC") && + !virFileExists(selinux_lxc_contexts_path())) + return SECURITY_DRIVER_DISABLE; + + return SECURITY_DRIVER_ENABLE; } + static int -SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr) { - return SELinuxInitialize(); + return SELinuxInitialize(mgr); } + static int -SELinuxSecurityDriverClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) +SELinuxSecurityDriverClose(virSecurityManagerPtr mgr) { + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); + + if (!data) + return 0; + + VIR_FREE(data->domain_context); + VIR_FREE(data->file_context); + VIR_FREE(data->content_context); + return 0; } @@ -405,6 +433,7 @@ SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, strcpy(sec->label, (char *) ctx); freecon(ctx); + VIR_DEBUG("SELinuxGetSecurityProcessLabel %s", sec->label); sec->enforcing = security_getenforce(); if (sec->enforcing == -1) { virReportSystemError(errno, "%s", @@ -639,8 +668,10 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, size_t depth, void *opaque) { - const virSecurityLabelDefPtr secdef = opaque; + virSecuritySELinuxCallbackDataPtr cbdata = opaque; + const virSecurityLabelDefPtr secdef = cbdata->secdef; int ret; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(cbdata->manager); if (disk->seclabel && disk->seclabel->norelabel) return 0; @@ -649,17 +680,18 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, disk->seclabel->label) { ret = SELinuxSetFilecon(path, disk->seclabel->label); } else if (depth == 0) { + if (disk->shared) { - ret = SELinuxSetFileconOptional(path, default_image_context); + ret = SELinuxSetFileconOptional(path, data->file_context); } else if (disk->readonly) { - ret = SELinuxSetFileconOptional(path, default_content_context); + ret = SELinuxSetFileconOptional(path, data->content_context); } else if (secdef->imagelabel) { ret = SELinuxSetFileconOptional(path, secdef->imagelabel); } else { ret = 0; } } else { - ret = SELinuxSetFileconOptional(path, default_content_context); + ret = SELinuxSetFileconOptional(path, data->content_context); } if (ret == 1 && !disk->seclabel) { /* If we failed to set a label, but virt_use_nfs let us @@ -680,10 +712,13 @@ SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr, virDomainDiskDefPtr disk) { - const virSecurityLabelDefPtr secdef = &def->seclabel; + virSecuritySELinuxCallbackData cbdata; + cbdata.secdef = &def->seclabel; + cbdata.manager = mgr; + bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr); - if (secdef->norelabel) + if (cbdata.secdef->norelabel) return 0; if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) @@ -700,7 +735,7 @@ SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr, true, -1, -1, /* current process uid:gid */ SELinuxSetSecurityFileLabel, - secdef); + &cbdata); } @@ -1119,6 +1154,7 @@ SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr, { /* TODO: verify DOI */ const virSecurityLabelDefPtr secdef = &def->seclabel; + VIR_DEBUG("SELinuxSetSecurityProcessLabel %s", secdef->label); if (def->seclabel.label == NULL) return 0; @@ -1300,9 +1336,11 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def, static int SELinuxSetSecuritySmartcardCallback(virDomainDefPtr def, virDomainSmartcardDefPtr dev, - void *opaque ATTRIBUTE_UNUSED) + void *opaque) { const char *database; + virSecurityManagerPtr mgr = opaque; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); switch (dev->type) { case VIR_DOMAIN_SMARTCARD_TYPE_HOST: @@ -1312,7 +1350,7 @@ SELinuxSetSecuritySmartcardCallback(virDomainDefPtr def, database = dev->data.cert.database; if (!database) database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE; - return SELinuxSetFilecon(database, default_content_context); + return SELinuxSetFilecon(database, data->content_context); case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: return SELinuxSetSecurityChardevLabel(def, &dev->data.passthru); @@ -1333,6 +1371,7 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, const char *stdin_path) { + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); const virSecurityLabelDefPtr secdef = &def->seclabel; int i; @@ -1368,19 +1407,19 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, if (virDomainSmartcardDefForeach(def, true, SELinuxSetSecuritySmartcardCallback, - NULL) < 0) + mgr) < 0) return -1; if (def->os.kernel && - SELinuxSetFilecon(def->os.kernel, default_content_context) < 0) + SELinuxSetFilecon(def->os.kernel, data->content_context) < 0) return -1; if (def->os.initrd && - SELinuxSetFilecon(def->os.initrd, default_content_context) < 0) + SELinuxSetFilecon(def->os.initrd, data->content_context) < 0) return -1; if (stdin_path) { - if (SELinuxSetFilecon(stdin_path, default_content_context) < 0 && + if (SELinuxSetFilecon(stdin_path, data->content_context) < 0 && virStorageFileIsSharedFSType(stdin_path, VIR_STORAGE_FILE_SHFS_NFS) != 1) return -1; @@ -1403,7 +1442,7 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, } virSecurityDriver virSecurityDriverSELinux = { - 0, + sizeof(virSecuritySELinuxData), SECURITY_SELINUX_NAME, SELinuxSecurityDriverProbe, SELinuxSecurityDriverOpen, -- 1.7.10.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list