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

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