From: Michal Privoznik <[email protected]>

Here's the problem. When starting a QEMU domain, the process is
split into several phases. A simplified process looks like this:

1)  qemuProcessPrepareDomain()
1a)  qemuSecurityGenLabel()
1b)  generate run time paths
1c)  qemuSecurityManagerLoadProfile()

2)  qemuProcessPrepareHost()
2a)  qemuSecurityDomainSetPathLabel() /* transitively */

3)  qemuProcessLaunch()
3a)  qemuSecuritySetAllLabel()

NB, step 2a) also contains helper processes used to set up host,
that we want to run in the security context of the domain (e.g.
swtpm_setup).

This works well for SELinux and DAC because their APIs basically
match 1:1 to ours. But it's not that simple with AppArmor. It
doesn't contain any profile upfront, so one is generated in step
1a) (among with seclabel). But at that point, the domain
definition has no run time info. This can then lead to some paths
being left out (for instance, disks which source wasn't
translated from storage pool/vol spec into a path).

After previous commits, there's this new step 1c) which can
actually load the profile. Therefore, move profile loading into
.domainLoadProfile callback.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/135
Signed-off-by: Michal Privoznik <[email protected]>
---
 src/security/security_apparmor.c | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 68ac39611f..98fad9034d 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -387,23 +387,36 @@ AppArmorGenSecurityLabel(virSecurityManager *mgr 
G_GNUC_UNUSED,
     if (!secdef->model)
         secdef->model = g_strdup(SECURITY_APPARMOR_NAME);
 
-    /* Now that we have a label, load the profile into the kernel. */
+    return 0;
+}
+
+
+static int
+AppArmorLoadProfile(virSecurityManager *mgr G_GNUC_UNUSED,
+                    virDomainDef *def)
+{
+    virSecurityLabelDef *secdef = virDomainDefGetSecurityLabelDef(def,
+                                                 SECURITY_APPARMOR_NAME);
+
+    if (!secdef)
+        return 0;
+
+    if ((secdef->type == VIR_DOMAIN_SECLABEL_STATIC) ||
+        (secdef->type == VIR_DOMAIN_SECLABEL_NONE)) {
+        return 0;
+    }
+
     if (load_profile(mgr, secdef->label, def, NULL, false) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot load AppArmor profile \'%1$s\'"),
                        secdef->label);
-        goto err;
+        return -1;
     }
 
     return 0;
-
- err:
-    VIR_FREE(secdef->label);
-    VIR_FREE(secdef->imagelabel);
-    VIR_FREE(secdef->model);
-    return -1;
 }
 
+
 static int
 AppArmorSetSecurityAllLabel(virSecurityManager *mgr,
                             char *const *sharedFilesystems G_GNUC_UNUSED,
@@ -1157,6 +1170,8 @@ virSecurityDriver virAppArmorSecurityDriver = {
     .domainReserveSecurityLabel         = AppArmorReserveSecurityLabel,
     .domainReleaseSecurityLabel         = AppArmorReleaseSecurityLabel,
 
+    .domainLoadProfile                  = AppArmorLoadProfile,
+
     .domainGetSecurityProcessLabel      = AppArmorGetSecurityProcessLabel,
     .domainSetSecurityProcessLabel      = AppArmorSetSecurityProcessLabel,
     .domainSetSecurityChildProcessLabel = AppArmorSetSecurityChildProcessLabel,
-- 
2.52.0

Reply via email to