Blame SOURCES/libvirt-security-Introduce-VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP-flag.patch

d76c62
From 04b7241a14015f67b68d9779be71f9e8f91791c3 Mon Sep 17 00:00:00 2001
d76c62
Message-Id: <04b7241a14015f67b68d9779be71f9e8f91791c3@dist-git>
d76c62
From: Michal Privoznik <mprivozn@redhat.com>
d76c62
Date: Mon, 9 Mar 2020 14:58:56 +0100
d76c62
Subject: [PATCH] security: Introduce
d76c62
 VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP flag
d76c62
d76c62
Our decision whether to remember seclabel for a disk image
d76c62
depends on a few factors. If the image is readonly or shared or
d76c62
not the chain top the remembering is suppressed for the image.
d76c62
However, the virSecurityManagerSetImageLabel() is too low level
d76c62
to determine whether passed @src is chain top or not. Even though
d76c62
the function has the @parent argument it does not necessarily
d76c62
reflect the chain top - it only points to the top level image in
d76c62
the chain we want to relabel and not to the topmost image of the
d76c62
whole chain. And this can't be derived from the passed domain
d76c62
definition reliably neither - in some cases (like snapshots or
d76c62
block copy) the @src is added to the definition only after the
d76c62
operation succeeded. Therefore, introduce a flag which callers
d76c62
can use to help us with the decision.
d76c62
d76c62
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
d76c62
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
d76c62
(cherry picked from commit 62f3d8adbc0381223499ff2bef45b23e7dca401d)
d76c62
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1803551
d76c62
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
d76c62
Message-Id: <bd4b1cca6feabd0c6d421603abe38397090c5394.1583760062.git.mprivozn@redhat.com>
d76c62
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
d76c62
---
d76c62
 src/security/security_dac.c     | 15 ++++++++++-----
d76c62
 src/security/security_manager.h |  4 ++++
d76c62
 src/security/security_selinux.c | 17 +++++++++++------
d76c62
 3 files changed, 25 insertions(+), 11 deletions(-)
d76c62
d76c62
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
d76c62
index 0cfe3626d4..66906245eb 100644
d76c62
--- a/src/security/security_dac.c
d76c62
+++ b/src/security/security_dac.c
d76c62
@@ -885,14 +885,14 @@ static int
d76c62
 virSecurityDACSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
                                     virDomainDefPtr def,
d76c62
                                     virStorageSourcePtr src,
d76c62
-                                    virStorageSourcePtr parent)
d76c62
+                                    virStorageSourcePtr parent,
d76c62
+                                    bool isChainTop)
d76c62
 {
d76c62
     virSecurityLabelDefPtr secdef;
d76c62
     virSecurityDeviceLabelDefPtr disk_seclabel;
d76c62
     virSecurityDeviceLabelDefPtr parent_seclabel = NULL;
d76c62
     virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
d76c62
     bool remember;
d76c62
-    bool is_toplevel = parent == src || parent->externalDataStore == src;
d76c62
     uid_t user;
d76c62
     gid_t group;
d76c62
 
d76c62
@@ -950,7 +950,7 @@ virSecurityDACSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
      * but the top layer, or read only image, or disk explicitly
d76c62
      * marked as shared.
d76c62
      */
d76c62
-    remember = is_toplevel && !src->readonly && !src->shared;
d76c62
+    remember = isChainTop && !src->readonly && !src->shared;
d76c62
 
d76c62
     return virSecurityDACSetOwnership(mgr, src, NULL, user, group, remember);
d76c62
 }
d76c62
@@ -966,7 +966,9 @@ virSecurityDACSetImageLabelRelative(virSecurityManagerPtr mgr,
d76c62
     virStorageSourcePtr n;
d76c62
 
d76c62
     for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
d76c62
-        if (virSecurityDACSetImageLabelInternal(mgr, def, n, parent) < 0)
d76c62
+        const bool isChainTop = flags & VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
d76c62
+
d76c62
+        if (virSecurityDACSetImageLabelInternal(mgr, def, n, parent, isChainTop) < 0)
d76c62
             return -1;
d76c62
 
d76c62
         if (n->externalDataStore &&
d76c62
@@ -979,6 +981,8 @@ virSecurityDACSetImageLabelRelative(virSecurityManagerPtr mgr,
d76c62
 
d76c62
         if (!(flags & VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN))
d76c62
             break;
d76c62
+
d76c62
+        flags &= ~VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
d76c62
     }
d76c62
 
d76c62
     return 0;
d76c62
@@ -2106,7 +2110,8 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr,
d76c62
         if (virDomainDiskGetType(def->disks[i]) == VIR_STORAGE_TYPE_DIR)
d76c62
             continue;
d76c62
         if (virSecurityDACSetImageLabel(mgr, def, def->disks[i]->src,
d76c62
-                                        VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN) < 0)
d76c62
+                                        VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN |
d76c62
+                                        VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0)
d76c62
             return -1;
d76c62
     }
d76c62
 
d76c62
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
d76c62
index b92ea5dc87..7699bcbc6f 100644
d76c62
--- a/src/security/security_manager.h
d76c62
+++ b/src/security/security_manager.h
d76c62
@@ -151,6 +151,10 @@ virSecurityManagerPtr* virSecurityManagerGetNested(virSecurityManagerPtr mgr);
d76c62
 
d76c62
 typedef enum {
d76c62
     VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN = 1 << 0,
d76c62
+    /* The VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP should be set if the
d76c62
+     * image passed to virSecurityManagerSetImageLabel() is the top parent of
d76c62
+     * the whole backing chain. */
d76c62
+    VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP = 1 << 1,
d76c62
 } virSecurityDomainImageLabelFlags;
d76c62
 
d76c62
 int virSecurityManagerSetImageLabel(virSecurityManagerPtr mgr,
d76c62
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
d76c62
index d7362327e6..985c7eda1a 100644
d76c62
--- a/src/security/security_selinux.c
d76c62
+++ b/src/security/security_selinux.c
d76c62
@@ -1824,7 +1824,8 @@ static int
d76c62
 virSecuritySELinuxSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
                                         virDomainDefPtr def,
d76c62
                                         virStorageSourcePtr src,
d76c62
-                                        virStorageSourcePtr parent)
d76c62
+                                        virStorageSourcePtr parent,
d76c62
+                                        bool isChainTop)
d76c62
 {
d76c62
     virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
d76c62
     virSecurityLabelDefPtr secdef;
d76c62
@@ -1832,7 +1833,6 @@ virSecuritySELinuxSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
     virSecurityDeviceLabelDefPtr parent_seclabel = NULL;
d76c62
     char *use_label = NULL;
d76c62
     bool remember;
d76c62
-    bool is_toplevel = parent == src || parent->externalDataStore == src;
d76c62
     g_autofree char *vfioGroupDev = NULL;
d76c62
     const char *path = src->path;
d76c62
     int ret;
d76c62
@@ -1856,7 +1856,7 @@ virSecuritySELinuxSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
      * but the top layer, or read only image, or disk explicitly
d76c62
      * marked as shared.
d76c62
      */
d76c62
-    remember = is_toplevel && !src->readonly && !src->shared;
d76c62
+    remember = isChainTop && !src->readonly && !src->shared;
d76c62
 
d76c62
     disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
d76c62
                                                         SECURITY_SELINUX_NAME);
d76c62
@@ -1873,7 +1873,7 @@ virSecuritySELinuxSetImageLabelInternal(virSecurityManagerPtr mgr,
d76c62
             return 0;
d76c62
 
d76c62
         use_label = parent_seclabel->label;
d76c62
-    } else if (is_toplevel) {
d76c62
+    } else if (parent == src || parent->externalDataStore == src) {
d76c62
         if (src->shared) {
d76c62
             use_label = data->file_context;
d76c62
         } else if (src->readonly) {
d76c62
@@ -1930,7 +1930,9 @@ virSecuritySELinuxSetImageLabelRelative(virSecurityManagerPtr mgr,
d76c62
     virStorageSourcePtr n;
d76c62
 
d76c62
     for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
d76c62
-        if (virSecuritySELinuxSetImageLabelInternal(mgr, def, n, parent) < 0)
d76c62
+        const bool isChainTop = flags & VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
d76c62
+
d76c62
+        if (virSecuritySELinuxSetImageLabelInternal(mgr, def, n, parent, isChainTop) < 0)
d76c62
             return -1;
d76c62
 
d76c62
         if (n->externalDataStore &&
d76c62
@@ -1943,6 +1945,8 @@ virSecuritySELinuxSetImageLabelRelative(virSecurityManagerPtr mgr,
d76c62
 
d76c62
         if (!(flags & VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN))
d76c62
             break;
d76c62
+
d76c62
+        flags &= ~VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
d76c62
     }
d76c62
 
d76c62
     return 0;
d76c62
@@ -3142,7 +3146,8 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr,
d76c62
             continue;
d76c62
         }
d76c62
         if (virSecuritySELinuxSetImageLabel(mgr, def, def->disks[i]->src,
d76c62
-                                            VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN) < 0)
d76c62
+                                            VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN |
d76c62
+                                            VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 0)
d76c62
             return -1;
d76c62
     }
d76c62
     /* XXX fixme process  def->fss if relabel == true */
d76c62
-- 
d76c62
2.25.1
d76c62