From: "Richard W.M. Jones" <rjones@xxxxxxxxxx> According to Eric Paris this is slightly more efficient because it only loads the regular expressions in libselinux once. --- src/security/security_selinux.c | 129 ++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 46 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index a3ef728..d1f80b2 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -63,6 +63,9 @@ struct _virSecuritySELinuxData { char *content_context; virHashTablePtr mcs; bool skipAllLabel; +#if HAVE_SELINUX_LABEL_H + struct selabel_handle *label_handle; +#endif }; struct _virSecuritySELinuxCallbackData { @@ -367,12 +370,21 @@ virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr) data->skipAllLabel = true; +#if HAVE_SELINUX_LABEL_H + data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (!data->label_handle) { + virReportSystemError(errno, + _("cannot open SELinux label_handle")); + return -1; + } +#endif + selinux_conf = virConfReadFile(selinux_lxc_contexts_path(), 0); if (!selinux_conf) { virReportSystemError(errno, _("cannot open SELinux lxc contexts file '%s'"), selinux_lxc_contexts_path()); - return -1; + goto error; } scon = virConfGetValue(selinux_conf, "process"); @@ -418,6 +430,9 @@ virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr) return 0; error: +#if HAVE_SELINUX_LABEL_H + selabel_close(data->label_handle); +#endif virConfFree(selinux_conf); VIR_FREE(data->domain_context); VIR_FREE(data->file_context); @@ -444,6 +459,15 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr) data->skipAllLabel = false; +#if HAVE_SELINUX_LABEL_H + data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (!data->label_handle) { + virReportSystemError(errno, + _("cannot open SELinux label_handle")); + return -1; + } +#endif + if (virFileReadAll(selinux_virtual_domain_context_path(), MAX_CONTEXT, &(data->domain_context)) < 0) { virReportSystemError(errno, _("cannot read SELinux virtual domain context file '%s'"), @@ -499,6 +523,9 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr) return 0; error: +#if HAVE_SELINUX_LABEL_H + selabel_close(data->label_handle); +#endif VIR_FREE(data->domain_context); VIR_FREE(data->alt_domain_context); VIR_FREE(data->file_context); @@ -763,6 +790,10 @@ virSecuritySELinuxSecurityDriverClose(virSecurityManagerPtr mgr) if (!data) return 0; +#if HAVE_SELINUX_LABEL_H + selabel_close(data->label_handle); +#endif + virHashFree(data->mcs); VIR_FREE(data->domain_context); @@ -937,18 +968,13 @@ virSecuritySELinuxFSetFilecon(int fd, char *tcon) /* Set fcon to the appropriate label for path and mode, or return -1. */ static int -getContext(const char *newpath, mode_t mode, security_context_t *fcon) +getContext(virSecurityManagerPtr mgr, + const char *newpath, mode_t mode, security_context_t *fcon) { #if HAVE_SELINUX_LABEL_H - struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); - int ret; - - if (handle == NULL) - return -1; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); - ret = selabel_lookup_raw(handle, fcon, newpath, mode); - selabel_close(handle); - return ret; + return selabel_lookup_raw(data->label_handle, fcon, newpath, mode); #else return matchpathcon(newpath, mode, fcon); #endif @@ -958,7 +984,8 @@ getContext(const char *newpath, mode_t mode, security_context_t *fcon) /* This method shouldn't raise errors, since they'll overwrite * errors that the caller(s) are already dealing with */ static int -virSecuritySELinuxRestoreSecurityFileLabel(const char *path) +virSecuritySELinuxRestoreSecurityFileLabel(virSecurityManagerPtr mgr, + const char *path) { struct stat buf; security_context_t fcon = NULL; @@ -980,7 +1007,7 @@ virSecuritySELinuxRestoreSecurityFileLabel(const char *path) goto err; } - if (getContext(newpath, buf.st_mode, &fcon) < 0) { + if (getContext(mgr, newpath, buf.st_mode, &fcon) < 0) { /* Any user created path likely does not have a default label, * which makes this an expected non error */ @@ -997,7 +1024,7 @@ err: } static int -virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainDiskDefPtr disk, int migrated) @@ -1044,7 +1071,7 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBU } } - return virSecuritySELinuxRestoreSecurityFileLabel(disk->src); + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, disk->src); } @@ -1301,22 +1328,27 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN static int virSecuritySELinuxRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, const char *file, - void *opaque ATTRIBUTE_UNUSED) + void *opaque) { - return virSecuritySELinuxRestoreSecurityFileLabel(file); + virSecurityManagerPtr mgr = opaque; + + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file); } static int virSecuritySELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, const char *file, - void *opaque ATTRIBUTE_UNUSED) + void *opaque) { - return virSecuritySELinuxRestoreSecurityFileLabel(file); + virSecurityManagerPtr mgr = opaque; + + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file); } static int -virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev, +virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr, + virDomainHostdevDefPtr dev, const char *vroot) { @@ -1335,7 +1367,7 @@ virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev, if (!usb) goto done; - ret = usbDeviceFileIterate(usb, virSecuritySELinuxRestoreSecurityUSBLabel, NULL); + ret = usbDeviceFileIterate(usb, virSecuritySELinuxRestoreSecurityUSBLabel, mgr); usbFreeDevice(usb); break; @@ -1350,7 +1382,7 @@ virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev, if (!pci) goto done; - ret = pciDeviceFileIterate(pci, virSecuritySELinuxRestoreSecurityPCILabel, NULL); + ret = pciDeviceFileIterate(pci, virSecuritySELinuxRestoreSecurityPCILabel, mgr); pciFreeDevice(pci); break; @@ -1367,7 +1399,8 @@ done: static int -virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev, +virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virSecurityManagerPtr mgr, + virDomainHostdevDefPtr dev, const char *vroot) { int ret = -1; @@ -1387,7 +1420,7 @@ virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev, return -1; } } - ret = virSecuritySELinuxRestoreSecurityFileLabel(path); + ret = virSecuritySELinuxRestoreSecurityFileLabel(mgr, path); VIR_FREE(path); break; } @@ -1405,7 +1438,7 @@ virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev, return -1; } } - ret = virSecuritySELinuxRestoreSecurityFileLabel(path); + ret = virSecuritySELinuxRestoreSecurityFileLabel(mgr, path); VIR_FREE(path); break; } @@ -1420,7 +1453,7 @@ virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev, static int -virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainHostdevDefPtr dev, const char *vroot) @@ -1437,10 +1470,10 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT switch (dev->mode) { case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: - return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(dev, vroot); + return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(mgr, dev, vroot); case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: - return virSecuritySELinuxRestoreSecurityHostdevCapsLabel(dev, vroot); + return virSecuritySELinuxRestoreSecurityHostdevCapsLabel(mgr, dev, vroot); default: return 0; @@ -1522,7 +1555,8 @@ done: } static int -virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def, +virSecuritySELinuxRestoreSecurityChardevLabel(virSecurityManagerPtr mgr, + virDomainDefPtr def, virDomainChrDefPtr dev, virDomainChrSourceDefPtr dev_source) @@ -1545,14 +1579,14 @@ virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def, switch (dev_source->type) { case VIR_DOMAIN_CHR_TYPE_DEV: case VIR_DOMAIN_CHR_TYPE_FILE: - if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) + if (virSecuritySELinuxRestoreSecurityFileLabel(mgr, dev_source->data.file.path) < 0) goto done; ret = 0; break; case VIR_DOMAIN_CHR_TYPE_UNIX: if (!dev_source->data.nix.listen) { - if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) + if (virSecuritySELinuxRestoreSecurityFileLabel(mgr, dev_source->data.file.path) < 0) goto done; } ret = 0; @@ -1565,11 +1599,11 @@ virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def, goto done; } if (virFileExists(in) && virFileExists(out)) { - if ((virSecuritySELinuxRestoreSecurityFileLabel(out) < 0) || - (virSecuritySELinuxRestoreSecurityFileLabel(in) < 0)) { + if ((virSecuritySELinuxRestoreSecurityFileLabel(mgr, out) < 0) || + (virSecuritySELinuxRestoreSecurityFileLabel(mgr, in) < 0)) { goto done; } - } else if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) { + } else if (virSecuritySELinuxRestoreSecurityFileLabel(mgr, dev_source->data.file.path) < 0) { goto done; } ret = 0; @@ -1590,14 +1624,16 @@ done: static int virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDefPtr def, virDomainChrDefPtr dev, - void *opaque ATTRIBUTE_UNUSED) + void *opaque) { + virSecurityManagerPtr mgr = opaque; + /* This is taken care of by processing of def->serials */ if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) return 0; - return virSecuritySELinuxRestoreSecurityChardevLabel(def, dev, + return virSecuritySELinuxRestoreSecurityChardevLabel(mgr, def, dev, &dev->source); } @@ -1605,8 +1641,9 @@ virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDefPtr def, static int virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def, virDomainSmartcardDefPtr dev, - void *opaque ATTRIBUTE_UNUSED) + void *opaque) { + virSecurityManagerPtr mgr = opaque; const char *database; switch (dev->type) { @@ -1617,10 +1654,10 @@ virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def, database = dev->data.cert.database; if (!database) database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE; - return virSecuritySELinuxRestoreSecurityFileLabel(database); + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, database); case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: - return virSecuritySELinuxRestoreSecurityChardevLabel(def, NULL, &dev->data.passthru); + return virSecuritySELinuxRestoreSecurityChardevLabel(mgr, def, NULL, &dev->data.passthru); default: virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1670,21 +1707,21 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr, if (virDomainChrDefForeach(def, false, virSecuritySELinuxRestoreSecurityChardevCallback, - NULL) < 0) + mgr) < 0) rc = -1; if (virDomainSmartcardDefForeach(def, false, virSecuritySELinuxRestoreSecuritySmartcardCallback, - NULL) < 0) + mgr) < 0) rc = -1; if (def->os.kernel && - virSecuritySELinuxRestoreSecurityFileLabel(def->os.kernel) < 0) + virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.kernel) < 0) rc = -1; if (def->os.initrd && - virSecuritySELinuxRestoreSecurityFileLabel(def->os.initrd) < 0) + virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.initrd) < 0) rc = -1; return rc; @@ -1737,7 +1774,7 @@ virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, static int -virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, const char *savefile) { @@ -1750,7 +1787,7 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNU if (secdef->norelabel) return 0; - return virSecuritySELinuxRestoreSecurityFileLabel(savefile); + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, savefile); } @@ -2080,7 +2117,7 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, } static int -virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, int fd) { @@ -2108,7 +2145,7 @@ virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, goto cleanup; } - if (getContext("/dev/tap.*", buf.st_mode, &fcon) < 0) { + if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot lookup default selinux label for tap fd %d"), fd); goto cleanup; -- 1.8.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list