Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/security/security_selinux.c | 161 ++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 47 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 715d9a428b..4990d94b5f 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -33,6 +33,7 @@ #include "security_driver.h" #include "security_selinux.h" +#include "security_util.h" #include "virerror.h" #include "viralloc.h" #include "virlog.h" @@ -197,14 +198,40 @@ virSecuritySELinuxTransactionAppend(const char *path, } +static int +virSecuritySELinuxRememberLabel(const char *path, + const security_context_t con) +{ + return virSecuritySetRememberedLabel(SECURITY_SELINUX_NAME, + path, con); +} + + +static int +virSecuritySELinuxRecallLabel(const char *path, + security_context_t *con) +{ + if (virSecurityGetRememberedLabel(SECURITY_SELINUX_NAME, + path, con) < 0) + return -1; + + if (!con) + return 1; + + return 0; +} + + static int virSecuritySELinuxSetFileconHelper(const char *path, const char *tcon, bool optional, - bool privileged); + bool privileged, + bool remember); static int virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr, - const char *path); + const char *path, + bool recall); /** @@ -255,10 +282,12 @@ virSecuritySELinuxTransactionRun(pid_t pid ATTRIBUTE_UNUSED, rv = virSecuritySELinuxSetFileconHelper(item->path, item->tcon, item->optional, - privileged); + privileged, + list->lock); } else { rv = virSecuritySELinuxRestoreFileLabel(list->manager, - item->path); + item->path, + list->lock); } if (rv < 0) @@ -1275,16 +1304,38 @@ virSecuritySELinuxSetFileconImpl(const char *path, const char *tcon, static int virSecuritySELinuxSetFileconHelper(const char *path, const char *tcon, - bool optional, bool privileged) + bool optional, bool privileged, bool remember) { + security_context_t econ = NULL; int rc; + int ret = -1; if ((rc = virSecuritySELinuxTransactionAppend(path, tcon, optional, false)) < 0) return -1; else if (rc > 0) return 0; - return virSecuritySELinuxSetFileconImpl(path, tcon, optional, privileged); + if (remember) { + if (getfilecon_raw(path, &econ) < 0 && + errno != ENOTSUP && errno != ENODATA) { + virReportSystemError(errno, + _("unable to get SELinux context of %s"), + path); + goto cleanup; + } + + if (econ && + virSecuritySELinuxRememberLabel(path, econ) < 0) + goto cleanup; + } + + if (virSecuritySELinuxSetFileconImpl(path, tcon, optional, privileged) < 0) + goto cleanup; + + ret = 0; + cleanup: + freecon(econ); + return ret; } @@ -1293,7 +1344,7 @@ virSecuritySELinuxSetFileconOptional(virSecurityManagerPtr mgr, const char *path, const char *tcon) { bool privileged = virSecurityManagerGetPrivileged(mgr); - return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged); + return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged, false); } static int @@ -1301,7 +1352,7 @@ virSecuritySELinuxSetFilecon(virSecurityManagerPtr mgr, const char *path, const char *tcon) { bool privileged = virSecurityManagerGetPrivileged(mgr); - return virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged); + return virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged, false); } static int @@ -1362,7 +1413,8 @@ getContext(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, * errors that the caller(s) are already dealing with */ static int virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr, - const char *path) + const char *path, + bool recall) { bool privileged = virSecurityManagerGetPrivileged(mgr); struct stat buf; @@ -1386,26 +1438,35 @@ virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr, goto cleanup; } - if (stat(newpath, &buf) != 0) { - VIR_WARN("cannot stat %s: %s", newpath, - virStrerror(errno, ebuf, sizeof(ebuf))); - goto cleanup; - } - - 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 - */ - VIR_WARN("cannot lookup default selinux label for %s", newpath); - ret = 0; - goto cleanup; - } - - if ((rc = virSecuritySELinuxTransactionAppend(path, fcon, false, true)) < 0) + if ((rc = virSecuritySELinuxTransactionAppend(path, NULL, false, true)) < 0) return -1; else if (rc > 0) return 0; + if (recall) { + if ((rc = virSecuritySELinuxRecallLabel(newpath, &fcon)) < 0) { + goto cleanup; + } else if (rc > 0) { + ret = 0; + goto cleanup; + } + } else { + if (stat(newpath, &buf) != 0) { + VIR_WARN("cannot stat %s: %s", newpath, + virStrerror(errno, ebuf, sizeof(ebuf))); + goto cleanup; + } + + 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 + */ + VIR_WARN("cannot lookup default selinux label for %s", newpath); + ret = 0; + goto cleanup; + } + } + if (virSecuritySELinuxSetFileconImpl(newpath, fcon, false, privileged) < 0) goto cleanup; @@ -1460,7 +1521,7 @@ virSecuritySELinuxRestoreInputLabel(virSecurityManagerPtr mgr, switch ((virDomainInputType)input->type) { case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH: - rc = virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev); + rc = virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev, false); break; case VIR_DOMAIN_INPUT_TYPE_MOUSE: @@ -1516,7 +1577,7 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManagerPtr mgr, if (!seclabel || !seclabel->relabel) return 0; - ret = virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath); + ret = virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath, false); break; case VIR_DOMAIN_MEMORY_MODEL_DIMM: @@ -1595,10 +1656,10 @@ virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManagerPtr mgr, switch (tpm->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: tpmdev = tpm->data.passthrough.source.data.file.path; - rc = virSecuritySELinuxRestoreFileLabel(mgr, tpmdev); + rc = virSecuritySELinuxRestoreFileLabel(mgr, tpmdev, false); if ((cancel_path = virTPMCreateCancelPath(tpmdev)) != NULL) { - if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path) < 0) + if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path, false) < 0) rc = -1; VIR_FREE(cancel_path); } @@ -1665,7 +1726,7 @@ virSecuritySELinuxRestoreImageLabelInt(virSecurityManagerPtr mgr, } } - return virSecuritySELinuxRestoreFileLabel(mgr, src->path); + return virSecuritySELinuxRestoreFileLabel(mgr, src->path, false); } @@ -2053,7 +2114,7 @@ virSecuritySELinuxRestorePCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr = opaque; - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } static int @@ -2063,7 +2124,7 @@ virSecuritySELinuxRestoreUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr = opaque; - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } @@ -2080,7 +2141,7 @@ virSecuritySELinuxRestoreSCSILabel(virSCSIDevicePtr dev, if (virSCSIDeviceGetShareable(dev) || virSCSIDeviceGetReadonly(dev)) return 0; - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } static int @@ -2090,7 +2151,7 @@ virSecuritySELinuxRestoreHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr = opaque; - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } @@ -2194,7 +2255,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr, if (!(vfiodev = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr))) goto done; - ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiodev); + ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiodev, false); VIR_FREE(vfiodev); break; @@ -2228,7 +2289,7 @@ virSecuritySELinuxRestoreHostdevCapsLabel(virSecurityManagerPtr mgr, if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0) return -1; } - ret = virSecuritySELinuxRestoreFileLabel(mgr, path); + ret = virSecuritySELinuxRestoreFileLabel(mgr, path, false); VIR_FREE(path); break; } @@ -2242,7 +2303,7 @@ virSecuritySELinuxRestoreHostdevCapsLabel(virSecurityManagerPtr mgr, if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0) return -1; } - ret = virSecuritySELinuxRestoreFileLabel(mgr, path); + ret = virSecuritySELinuxRestoreFileLabel(mgr, path, false); VIR_FREE(path); break; } @@ -2390,14 +2451,18 @@ virSecuritySELinuxRestoreChardevLabel(virSecurityManagerPtr mgr, switch (dev_source->type) { case VIR_DOMAIN_CHR_TYPE_DEV: case VIR_DOMAIN_CHR_TYPE_FILE: - if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0) + if (virSecuritySELinuxRestoreFileLabel(mgr, + dev_source->data.file.path, + false) < 0) goto done; ret = 0; break; case VIR_DOMAIN_CHR_TYPE_UNIX: if (!dev_source->data.nix.listen) { - if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0) + if (virSecuritySELinuxRestoreFileLabel(mgr, + dev_source->data.file.path, + false) < 0) goto done; } ret = 0; @@ -2408,11 +2473,13 @@ virSecuritySELinuxRestoreChardevLabel(virSecurityManagerPtr mgr, (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0)) goto done; if (virFileExists(in) && virFileExists(out)) { - if ((virSecuritySELinuxRestoreFileLabel(mgr, out) < 0) || - (virSecuritySELinuxRestoreFileLabel(mgr, in) < 0)) { + if ((virSecuritySELinuxRestoreFileLabel(mgr, out, false) < 0) || + (virSecuritySELinuxRestoreFileLabel(mgr, in, false) < 0)) { goto done; } - } else if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0) { + } else if (virSecuritySELinuxRestoreFileLabel(mgr, + dev_source->data.file.path, + false) < 0) { goto done; } ret = 0; @@ -2464,7 +2531,7 @@ virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def, database = dev->data.cert.database; if (!database) database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE; - return virSecuritySELinuxRestoreFileLabel(mgr, database); + return virSecuritySELinuxRestoreFileLabel(mgr, database, false); case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: return virSecuritySELinuxRestoreChardevLabel(mgr, def, @@ -2559,7 +2626,7 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, rc = -1; if (def->os.loader && def->os.loader->nvram && - virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram) < 0) + virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram, false) < 0) rc = -1; return rc; @@ -2619,7 +2686,7 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr, if (!secdef || !secdef->relabel) return 0; - return virSecuritySELinuxRestoreFileLabel(mgr, savefile); + return virSecuritySELinuxRestoreFileLabel(mgr, savefile, false); } @@ -3214,7 +3281,7 @@ virSecuritySELinuxRestoreFileLabels(virSecurityManagerPtr mgr, char *filename = NULL; DIR *dir; - if ((ret = virSecuritySELinuxRestoreFileLabel(mgr, path))) + if ((ret = virSecuritySELinuxRestoreFileLabel(mgr, path, false))) return ret; if (!virFileIsDir(path)) @@ -3231,7 +3298,7 @@ virSecuritySELinuxRestoreFileLabels(virSecurityManagerPtr mgr, ret = -1; break; } - ret = virSecuritySELinuxRestoreFileLabel(mgr, filename); + ret = virSecuritySELinuxRestoreFileLabel(mgr, filename, false); VIR_FREE(filename); if (ret < 0) break; -- 2.18.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list