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

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