On the SELinux driver, image FD labeling applies the domain imagelabel, which includes the per-domain MCS categories. This is correct behavior for exclusive resources, but not for host devices that are shared by multiple domains (e.g. an iommufd). Add virSecurityManagerSetSharedImageFDLabel() to address this issue. Reuse the imagelabel type in the SELinux driver, but strip the MCS categories so that the range is sensitivity-only. Preserve the pre- existing behavior in all other security drivers. Signed-off-by: Omar Elghoul <oelghoul@linux.ibm.com> --- src/libvirt_private.syms | 1 + src/security/security_apparmor.c | 1 + src/security/security_dac.c | 1 + src/security/security_driver.h | 4 ++ src/security/security_manager.c | 16 ++++++++ src/security/security_manager.h | 3 ++ src/security/security_nop.c | 1 + src/security/security_selinux.c | 63 ++++++++++++++++++++++++++++++++ src/security/security_stack.c | 18 +++++++++ 9 files changed, 108 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6c6cc7b4ff..c67e808b13 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1895,6 +1895,7 @@ virSecurityManagerSetChildProcessLabel; virSecurityManagerSetDaemonSocketLabel; virSecurityManagerSetHostdevLabel; virSecurityManagerSetImageFDLabel; +virSecurityManagerSetSharedImageFDLabel; virSecurityManagerSetImageLabel; virSecurityManagerSetInputLabel; virSecurityManagerSetMemoryLabel; diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index a66382fbac..5d292d7feb 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -1174,6 +1174,7 @@ virSecurityDriver virAppArmorSecurityDriver = { .domainRestoreSecurityNetdevLabel = AppArmorRestoreNetdevLabel, .domainSetSecurityImageFDLabel = AppArmorSetFDLabel, + .domainSetSecuritySharedImageFDLabel = AppArmorSetFDLabel, .domainSetSecurityTapFDLabel = AppArmorSetFDLabel, .domainGetSecurityMountOptions = AppArmorGetMountOptions, diff --git a/src/security/security_dac.c b/src/security/security_dac.c index e7cffa8e59..2da0af3336 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -2711,6 +2711,7 @@ virSecurityDriver virSecurityDriverDAC = { .domainRestoreSecurityHostdevLabel = virSecurityDACRestoreHostdevLabel, .domainSetSecurityImageFDLabel = virSecurityDACSetImageFDLabel, + .domainSetSecuritySharedImageFDLabel = virSecurityDACSetImageFDLabel, .domainSetSecurityTapFDLabel = virSecurityDACSetTapFDLabel, .domainGetSecurityMountOptions = virSecurityDACGetMountOptions, diff --git a/src/security/security_driver.h b/src/security/security_driver.h index b8c5b416e3..874e2f1d8e 100644 --- a/src/security/security_driver.h +++ b/src/security/security_driver.h @@ -107,6 +107,9 @@ typedef int (*virSecurityDomainSecurityVerify) (virSecurityManager *mgr, typedef int (*virSecurityDomainSetImageFDLabel) (virSecurityManager *mgr, virDomainDef *def, int fd); +typedef int (*virSecurityDomainSetSharedImageFDLabel) (virSecurityManager *mgr, + virDomainDef *def, + int fd); typedef int (*virSecurityDomainSetTapFDLabel) (virSecurityManager *mgr, virDomainDef *def, int fd); @@ -225,6 +228,7 @@ struct _virSecurityDriver { virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel; virSecurityDomainSetImageFDLabel domainSetSecurityImageFDLabel; + virSecurityDomainSetSharedImageFDLabel domainSetSecuritySharedImageFDLabel; virSecurityDomainSetTapFDLabel domainSetSecurityTapFDLabel; virSecurityDomainGetMountOptions domainGetSecurityMountOptions; diff --git a/src/security/security_manager.c b/src/security/security_manager.c index bef9863799..baa6094f2e 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -977,6 +977,22 @@ virSecurityManagerSetImageFDLabel(virSecurityManager *mgr, } +int +virSecurityManagerSetSharedImageFDLabel(virSecurityManager *mgr, + virDomainDef *vm, + int fd) +{ + VIR_LOCK_GUARD lock = virObjectLockGuard(mgr); + + if (!mgr->drv->domainSetSecuritySharedImageFDLabel) { + virReportUnsupportedError(); + return -1; + } + + return mgr->drv->domainSetSecuritySharedImageFDLabel(mgr, vm, fd); +} + + int virSecurityManagerSetTapFDLabel(virSecurityManager *mgr, virDomainDef *vm, diff --git a/src/security/security_manager.h b/src/security/security_manager.h index 068ca4e290..0c1828a20d 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -156,6 +156,9 @@ int virSecurityManagerVerify(virSecurityManager *mgr, int virSecurityManagerSetImageFDLabel(virSecurityManager *mgr, virDomainDef *def, int fd); +int virSecurityManagerSetSharedImageFDLabel(virSecurityManager *mgr, + virDomainDef *def, + int fd); int virSecurityManagerSetTapFDLabel(virSecurityManager *mgr, virDomainDef *vm, int fd); diff --git a/src/security/security_nop.c b/src/security/security_nop.c index e6e337a49d..d918455acb 100644 --- a/src/security/security_nop.c +++ b/src/security/security_nop.c @@ -302,6 +302,7 @@ virSecurityDriver virSecurityDriverNop = { .domainRestoreSecurityHostdevLabel = virSecurityDomainRestoreHostdevLabelNop, .domainSetSecurityImageFDLabel = virSecurityDomainSetFDLabelNop, + .domainSetSecuritySharedImageFDLabel = virSecurityDomainSetFDLabelNop, .domainSetSecurityTapFDLabel = virSecurityDomainSetFDLabelNop, .domainGetSecurityMountOptions = virSecurityDomainGetMountOptionsNop, diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 423dcd0bd9..14e210000a 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -607,6 +607,50 @@ virSecuritySELinuxContextAddRange(const char *src, } +static char * +virSecuritySELinuxContextStripMCS(const char *label) +{ + g_autoptr(context_s_t) ctx = NULL; + g_autofree char *range = NULL; + const char *r; + const char *str; + char *tmp; + + if (!(ctx = context_new(label))) { + virReportSystemError(errno, + _("unable to parse SELinux context '%1$s'"), + label); + return NULL; + } + + r = context_range_get(ctx); + if (!r) + r = "s0"; + + range = g_strdup(r); + + if ((tmp = strchr(range, ':'))) + *tmp = '\0'; + if ((tmp = strchr(range, '-'))) + *tmp = '\0'; + + if (context_range_set(ctx, range) != 0) { + virReportSystemError(errno, + _("unable to set SELinux context rnge '%1$s'"), + range); + return NULL; + } + + if (!(str = context_str(ctx))) { + virReportSystemError(errno, "%s", + _("unable to format SELinux context")); + return NULL; + } + + return g_strdup(str); +} + + static char * virSecuritySELinuxContextSetFromFile(const char *origLabel, const char *binaryPath) @@ -3492,6 +3536,24 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManager *mgr G_GNUC_UNUSED, return virSecuritySELinuxFSetFilecon(fd, secdef->imagelabel); } +static int +virSecuritySELinuxSetSharedImageFDLabel(virSecurityManager *mgr G_GNUC_UNUSED, + virDomainDef *def, + int fd) +{ + virSecurityLabelDef *secdef; + g_autofree char *label = NULL; + + secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (!secdef || !secdef->imagelabel) + return 0; + + if (!(label = virSecuritySELinuxContextStripMCS(secdef->imagelabel))) + return -1; + + return virSecuritySELinuxFSetFilecon(fd, label); +} + static int virSecuritySELinuxSetTapFDLabel(virSecurityManager *mgr, virDomainDef *def, @@ -3844,6 +3906,7 @@ virSecurityDriver virSecurityDriverSELinux = { .domainRestoreSavedStateLabel = virSecuritySELinuxRestoreSavedStateLabel, .domainSetSecurityImageFDLabel = virSecuritySELinuxSetImageFDLabel, + .domainSetSecuritySharedImageFDLabel = virSecuritySELinuxSetSharedImageFDLabel, .domainSetSecurityTapFDLabel = virSecuritySELinuxSetTapFDLabel, .domainGetSecurityMountOptions = virSecuritySELinuxGetSecurityMountOptions, diff --git a/src/security/security_stack.c b/src/security/security_stack.c index a55e94e764..e6dc64332e 100644 --- a/src/security/security_stack.c +++ b/src/security/security_stack.c @@ -590,6 +590,23 @@ virSecurityStackSetImageFDLabel(virSecurityManager *mgr, return rc; } +static int +virSecurityStackSetSharedImageFDLabel(virSecurityManager *mgr, + virDomainDef *vm, + int fd) +{ + virSecurityStackData *priv = virSecurityManagerGetPrivateData(mgr); + virSecurityStackItem *item = priv->itemsHead; + int rc = 0; + + for (; item; item = item->next) { + if (virSecurityManagerSetSharedImageFDLabel(item->securityManager, vm, fd) < 0) + rc = -1; + } + + return rc; +} + static int virSecurityStackSetTapFDLabel(virSecurityManager *mgr, virDomainDef *vm, @@ -1072,6 +1089,7 @@ virSecurityDriver virSecurityDriverStack = { .domainRestoreSavedStateLabel = virSecurityStackRestoreSavedStateLabel, .domainSetSecurityImageFDLabel = virSecurityStackSetImageFDLabel, + .domainSetSecuritySharedImageFDLabel = virSecurityStackSetSharedImageFDLabel, .domainSetSecurityTapFDLabel = virSecurityStackSetTapFDLabel, .domainGetSecurityMountOptions = virSecurityStackGetMountOptions, -- 2.55.0