]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
security: Always forget labels for TPM state directory
authorAndrea Bolognani <abologna@redhat.com>
Fri, 30 Aug 2024 12:25:25 +0000 (14:25 +0200)
committerAndrea Bolognani <abologna@redhat.com>
Thu, 3 Oct 2024 11:29:56 +0000 (13:29 +0200)
In the case of outgoing migration, we avoid restoring the
remembered labels for the TPM state directory because doing so
would risk cutting off storage access for the target node.

Even in that case though, we should still forget (unref) the
remembered labels: if we don't, the source node will keep
thinking that the state directory is in use.

Note that this change only affects the SELinux driver because
the DAC driver doesn't currently implement label remembering
for TPM state at all.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/security/security_selinux.c

index 3e213a553b7e22191fb9d57a5b85a3231f57fbea..05f54cc9f5479aad7795fdec5658286cd122fae5 100644 (file)
@@ -210,6 +210,48 @@ virSecuritySELinuxRecallLabel(const char *path,
 }
 
 
+/**
+ * virSecuritySELinuxForgetLabels:
+ * @path: file or directory to work on
+ *
+ * Forgets rememebered SELinux labels for @path, including its
+ * children if it is a directory.
+ *
+ * This is intended to be used in cleanup paths, so failure to forget
+ * a single label is not considered fatal; instead, a best-effort
+ * attempt to continue and forget as many labels as possible will be
+ * made.
+ */
+static void
+virSecuritySELinuxForgetLabels(const char *path)
+{
+    struct dirent *ent;
+    g_autoptr(DIR) dir = NULL;
+    g_autofree char *con = NULL;
+
+    if (virSecuritySELinuxRecallLabel(path, &con) < 0)
+        VIR_WARN("Failed to forget remembered SELinux labels for %s, ignoring", path);
+
+    if (!virFileIsDir(path))
+        return;
+
+    if (virDirOpen(&dir, path) < 0)
+        return;
+
+    while (virDirRead(dir, &ent, NULL) > 0) {
+        g_autofree char *spath = NULL;
+        g_autofree char *scon = NULL;
+
+        spath = g_strdup_printf("%s/%s", path, ent->d_name);
+
+        if (virSecuritySELinuxRecallLabel(spath, &scon) < 0)
+            VIR_WARN("Failed to forget remembered SELinux labels for %s, ignoring", spath);
+    }
+
+    return;
+}
+
+
 static int virSecuritySELinuxSetFilecon(virSecurityManager *mgr,
                                         const char *path,
                                         const char *tcon,
@@ -3709,6 +3751,13 @@ virSecuritySELinuxRestoreTPMLabels(virSecurityManager *mgr,
         if (restoreTPMStateLabel) {
             ret = virSecuritySELinuxRestoreFileLabels(mgr,
                                                       def->tpms[i]->data.emulator.storagepath);
+        } else {
+            /* Even if we're not restoring the original label for the
+             * TPM state directory, we should still forget any
+             * remembered label so that a subsequent attempt at TPM
+             * startup will not fail due to the state directory being
+             * considered as still in use */
+            virSecuritySELinuxForgetLabels(def->tpms[i]->data.emulator.storagepath);
         }
 
         if (ret == 0 &&