summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/security/security_selinux.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 6ef61c767f..cdc28adb80 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -394,8 +394,11 @@ SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
return 0;
}
+/* Attempt to change the label of PATH to TCON. If OPTIONAL is true,
+ * return 1 if labelling was not possible. Otherwise, require a label
+ * change, and return 0 for success, -1 for failure. */
static int
-SELinuxSetFilecon(const char *path, char *tcon)
+SELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
{
security_context_t econ;
@@ -408,7 +411,7 @@ SELinuxSetFilecon(const char *path, char *tcon)
if (STREQ(tcon, econ)) {
freecon(econ);
/* It's alright, there's nothing to change anyway. */
- return 0;
+ return optional ? 1 : 0;
}
freecon(econ);
}
@@ -440,12 +443,26 @@ SELinuxSetFilecon(const char *path, char *tcon)
VIR_INFO("Setting security context '%s' on '%s' not supported",
tcon, path);
}
+ if (optional)
+ return 1;
}
}
return 0;
}
static int
+SELinuxSetFileconOptional(const char *path, char *tcon)
+{
+ return SELinuxSetFileconHelper(path, tcon, true);
+}
+
+static int
+SELinuxSetFilecon(const char *path, char *tcon)
+{
+ return SELinuxSetFileconHelper(path, tcon, false);
+}
+
+static int
SELinuxFSetFilecon(int fd, char *tcon)
{
security_context_t econ;
@@ -549,7 +566,7 @@ SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- if (secdef->norelabel)
+ if (secdef->norelabel || (disk->seclabel && disk->seclabel->norelabel))
return 0;
/* Don't restore labels on readoly/shared disks, because
@@ -604,23 +621,35 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
const virSecurityLabelDefPtr secdef = opaque;
int ret;
- if (depth == 0) {
+ if (disk->seclabel && disk->seclabel->norelabel)
+ return 0;
+
+ if (disk->seclabel && !disk->seclabel->norelabel &&
+ disk->seclabel->label) {
+ ret = SELinuxSetFilecon(path, disk->seclabel->label);
+ } else if (depth == 0) {
if (disk->shared) {
- ret = SELinuxSetFilecon(path, default_image_context);
+ ret = SELinuxSetFileconOptional(path, default_image_context);
} else if (disk->readonly) {
- ret = SELinuxSetFilecon(path, default_content_context);
+ ret = SELinuxSetFileconOptional(path, default_content_context);
} else if (secdef->imagelabel) {
- ret = SELinuxSetFilecon(path, secdef->imagelabel);
+ ret = SELinuxSetFileconOptional(path, secdef->imagelabel);
} else {
ret = 0;
}
} else {
- ret = SELinuxSetFilecon(path, default_content_context);
+ ret = SELinuxSetFileconOptional(path, default_content_context);
+ }
+ if (ret == 1 && !disk->seclabel) {
+ /* If we failed to set a label, but virt_use_nfs let us
+ * proceed anyway, then we don't need to relabel later. */
+ if (VIR_ALLOC(disk->seclabel) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ disk->seclabel->norelabel = true;
+ ret = 0;
}
- if (ret < 0 &&
- virStorageFileIsSharedFSType(path,
- VIR_STORAGE_FILE_SHFS_NFS) == 1)
- ret = 0;
return ret;
}