From nobody Mon Dec 8 02:36:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1544618504971580.0711571167097; Wed, 12 Dec 2018 04:41:44 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2C57E31256B9; Wed, 12 Dec 2018 12:41:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DCF2360C64; Wed, 12 Dec 2018 12:41:42 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 8E50F249A6; Wed, 12 Dec 2018 12:41:42 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id wBCCfMce017536 for ; Wed, 12 Dec 2018 07:41:22 -0500 Received: by smtp.corp.redhat.com (Postfix) id 29FA25D73F; Wed, 12 Dec 2018 12:41:22 +0000 (UTC) Received: from moe.brq.redhat.com (unknown [10.43.2.192]) by smtp.corp.redhat.com (Postfix) with ESMTP id A356F5D70A for ; Wed, 12 Dec 2018 12:41:19 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 12 Dec 2018 13:40:55 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v3 11/18] security_selinux: Remember old labels X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Wed, 12 Dec 2018 12:41:44 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Similarly to what I did in DAC driver, this also requires the same SELinux label to be used for shared paths. If a path is already in use by a domain (or domains) then and the domain we are starting now wants to access the path it has to have the same SELinux label. This might look too restrictive as the new label can still guarantee access to already running domains but in reality it is very unlikely and usually an admin mistake. Signed-off-by: Michal Privoznik --- src/security/security_selinux.c | 177 +++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 47 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinu= x.c index 715d9a428b..43d2ef32a5 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -33,6 +33,7 @@ =20 #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, } =20 =20 +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); =20 =20 static int virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr, - const char *path); + const char *path, + bool recall); =20 =20 /** @@ -255,10 +282,12 @@ virSecuritySELinuxTransactionRun(pid_t pid ATTRIBUTE_= UNUSED, rv =3D virSecuritySELinuxSetFileconHelper(item->path, item->tcon, item->optional, - privileged); + privileged, + list->lock); } else { rv =3D virSecuritySELinuxRestoreFileLabel(list->manager, - item->path); + item->path, + list->lock); } =20 if (rv < 0) @@ -1275,16 +1304,54 @@ virSecuritySELinuxSetFileconImpl(const char *path, = const char *tcon, =20 static int virSecuritySELinuxSetFileconHelper(const char *path, const char *tcon, - bool optional, bool privileged) + bool optional, bool privileged, bool re= member) { + security_context_t econ =3D NULL; + int refcount; int rc; + int ret =3D -1; =20 if ((rc =3D virSecuritySELinuxTransactionAppend(path, tcon, optional, = false)) < 0) return -1; else if (rc > 0) return 0; =20 - return virSecuritySELinuxSetFileconImpl(path, tcon, optional, privileg= ed); + if (remember) { + if (getfilecon_raw(path, &econ) < 0 && + errno !=3D ENOTSUP && errno !=3D ENODATA) { + virReportSystemError(errno, + _("unable to get SELinux context of %s"), + path); + goto cleanup; + } + + if (econ) { + refcount =3D virSecuritySELinuxRememberLabel(path, econ); + if (refcount < 0) { + goto cleanup; + } else if (refcount > 1) { + /* Refcount is greater than 1 which means that there + * is @refcount domains using the @path. Do not + * change the label (as it would almost certainly + * cause the other domains to lose access to the + * @path). */ + if (STRNEQ(econ, tcon)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("Setting different SELinux label on %= s " + "which is already in use"), path); + goto cleanup; + } + } + } + } + + if (virSecuritySELinuxSetFileconImpl(path, tcon, optional, privileged)= < 0) + goto cleanup; + + ret =3D 0; + cleanup: + freecon(econ); + return ret; } =20 =20 @@ -1293,7 +1360,7 @@ virSecuritySELinuxSetFileconOptional(virSecurityManag= erPtr mgr, const char *path, const char *tcon) { bool privileged =3D virSecurityManagerGetPrivileged(mgr); - return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged= ); + return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged= , false); } =20 static int @@ -1301,7 +1368,7 @@ virSecuritySELinuxSetFilecon(virSecurityManagerPtr mg= r, const char *path, const char *tcon) { bool privileged =3D virSecurityManagerGetPrivileged(mgr); - return virSecuritySELinuxSetFileconHelper(path, tcon, false, privilege= d); + return virSecuritySELinuxSetFileconHelper(path, tcon, false, privilege= d, false); } =20 static int @@ -1362,7 +1429,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 =3D virSecurityManagerGetPrivileged(mgr); struct stat buf; @@ -1386,26 +1454,35 @@ virSecuritySELinuxRestoreFileLabel(virSecurityManag= erPtr mgr, goto cleanup; } =20 - if (stat(newpath, &buf) !=3D 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 =3D 0; - goto cleanup; - } - - if ((rc =3D virSecuritySELinuxTransactionAppend(path, fcon, false, tru= e)) < 0) + if ((rc =3D virSecuritySELinuxTransactionAppend(path, NULL, false, tru= e)) < 0) return -1; else if (rc > 0) return 0; =20 + if (recall) { + if ((rc =3D virSecuritySELinuxRecallLabel(newpath, &fcon)) < 0) { + goto cleanup; + } else if (rc > 0) { + ret =3D 0; + goto cleanup; + } + } else { + if (stat(newpath, &buf) !=3D 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 =3D 0; + goto cleanup; + } + } + if (virSecuritySELinuxSetFileconImpl(newpath, fcon, false, privileged)= < 0) goto cleanup; =20 @@ -1460,7 +1537,7 @@ virSecuritySELinuxRestoreInputLabel(virSecurityManage= rPtr mgr, =20 switch ((virDomainInputType)input->type) { case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH: - rc =3D virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev= ); + rc =3D virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev= , false); break; =20 case VIR_DOMAIN_INPUT_TYPE_MOUSE: @@ -1516,7 +1593,7 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManag= erPtr mgr, if (!seclabel || !seclabel->relabel) return 0; =20 - ret =3D virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath); + ret =3D virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath, f= alse); break; =20 case VIR_DOMAIN_MEMORY_MODEL_DIMM: @@ -1595,10 +1672,10 @@ virSecuritySELinuxRestoreTPMFileLabelInt(virSecurit= yManagerPtr mgr, switch (tpm->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: tpmdev =3D tpm->data.passthrough.source.data.file.path; - rc =3D virSecuritySELinuxRestoreFileLabel(mgr, tpmdev); + rc =3D virSecuritySELinuxRestoreFileLabel(mgr, tpmdev, false); =20 if ((cancel_path =3D virTPMCreateCancelPath(tpmdev)) !=3D NULL) { - if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path) < 0) + if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path, false= ) < 0) rc =3D -1; VIR_FREE(cancel_path); } @@ -1665,7 +1742,7 @@ virSecuritySELinuxRestoreImageLabelInt(virSecurityMan= agerPtr mgr, } } =20 - return virSecuritySELinuxRestoreFileLabel(mgr, src->path); + return virSecuritySELinuxRestoreFileLabel(mgr, src->path, false); } =20 =20 @@ -2053,7 +2130,7 @@ virSecuritySELinuxRestorePCILabel(virPCIDevicePtr dev= ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr =3D opaque; =20 - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } =20 static int @@ -2063,7 +2140,7 @@ virSecuritySELinuxRestoreUSBLabel(virUSBDevicePtr dev= ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr =3D opaque; =20 - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } =20 =20 @@ -2080,7 +2157,7 @@ virSecuritySELinuxRestoreSCSILabel(virSCSIDevicePtr d= ev, if (virSCSIDeviceGetShareable(dev) || virSCSIDeviceGetReadonly(dev)) return 0; =20 - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } =20 static int @@ -2090,7 +2167,7 @@ virSecuritySELinuxRestoreHostLabel(virSCSIVHostDevice= Ptr dev ATTRIBUTE_UNUSED, { virSecurityManagerPtr mgr =3D opaque; =20 - return virSecuritySELinuxRestoreFileLabel(mgr, file); + return virSecuritySELinuxRestoreFileLabel(mgr, file, false); } =20 =20 @@ -2194,7 +2271,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecuri= tyManagerPtr mgr, if (!(vfiodev =3D virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuids= tr))) goto done; =20 - ret =3D virSecuritySELinuxRestoreFileLabel(mgr, vfiodev); + ret =3D virSecuritySELinuxRestoreFileLabel(mgr, vfiodev, false); =20 VIR_FREE(vfiodev); break; @@ -2228,7 +2305,7 @@ virSecuritySELinuxRestoreHostdevCapsLabel(virSecurity= ManagerPtr mgr, if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0) return -1; } - ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path); + ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path, false); VIR_FREE(path); break; } @@ -2242,7 +2319,7 @@ virSecuritySELinuxRestoreHostdevCapsLabel(virSecurity= ManagerPtr mgr, if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0) return -1; } - ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path); + ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path, false); VIR_FREE(path); break; } @@ -2390,14 +2467,18 @@ virSecuritySELinuxRestoreChardevLabel(virSecurityMa= nagerPtr 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 =3D 0; break; =20 case VIR_DOMAIN_CHR_TYPE_UNIX: if (!dev_source->data.nix.listen) { - if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.f= ile.path) < 0) + if (virSecuritySELinuxRestoreFileLabel(mgr, + dev_source->data.file.p= ath, + false) < 0) goto done; } ret =3D 0; @@ -2408,11 +2489,13 @@ virSecuritySELinuxRestoreChardevLabel(virSecurityMa= nagerPtr 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->dat= a.file.path) < 0) { + } else if (virSecuritySELinuxRestoreFileLabel(mgr, + dev_source->data.fil= e.path, + false) < 0) { goto done; } ret =3D 0; @@ -2464,7 +2547,7 @@ virSecuritySELinuxRestoreSecuritySmartcardCallback(vi= rDomainDefPtr def, database =3D dev->data.cert.database; if (!database) database =3D VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE; - return virSecuritySELinuxRestoreFileLabel(mgr, database); + return virSecuritySELinuxRestoreFileLabel(mgr, database, false); =20 case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: return virSecuritySELinuxRestoreChardevLabel(mgr, def, @@ -2559,7 +2642,7 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerP= tr mgr, rc =3D -1; =20 if (def->os.loader && def->os.loader->nvram && - virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram) < 0) + virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram, fal= se) < 0) rc =3D -1; =20 return rc; @@ -2619,7 +2702,7 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityM= anagerPtr mgr, if (!secdef || !secdef->relabel) return 0; =20 - return virSecuritySELinuxRestoreFileLabel(mgr, savefile); + return virSecuritySELinuxRestoreFileLabel(mgr, savefile, false); } =20 =20 @@ -3214,7 +3297,7 @@ virSecuritySELinuxRestoreFileLabels(virSecurityManage= rPtr mgr, char *filename =3D NULL; DIR *dir; =20 - if ((ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path))) + if ((ret =3D virSecuritySELinuxRestoreFileLabel(mgr, path, false))) return ret; =20 if (!virFileIsDir(path)) @@ -3231,7 +3314,7 @@ virSecuritySELinuxRestoreFileLabels(virSecurityManage= rPtr mgr, ret =3D -1; break; } - ret =3D virSecuritySELinuxRestoreFileLabel(mgr, filename); + ret =3D virSecuritySELinuxRestoreFileLabel(mgr, filename, false); VIR_FREE(filename); if (ret < 0) break; --=20 2.19.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list