c401cc
From eb3271a8659be0305eb9138da27dd4a3e74f6718 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <eb3271a8659be0305eb9138da27dd4a3e74f6718.1389183248.git.jdenemar@redhat.com>
c401cc
From: Eric Blake <eblake@redhat.com>
c401cc
Date: Wed, 18 Dec 2013 08:21:44 -0700
c401cc
Subject: [PATCH] qemu: ask for -enable-fips when FIPS is required
c401cc
c401cc
RHEL 7.0: https://bugzilla.redhat.com/show_bug.cgi?id=1035474
c401cc
c401cc
On a system that is enforcing FIPS, most libraries honor the
c401cc
current mode by default.  Qemu, on the other hand, refused to
c401cc
honor FIPS mode unless you add the '-enable-fips' command
c401cc
line option; worse, this option is not discoverable via QMP,
c401cc
and is only present on binaries built for Linux.  So, if we
c401cc
detect FIPS mode, then we unconditionally ask for FIPS; either
c401cc
qemu is new enough to have the option and then correctly
c401cc
cripple insecure VNC passwords, or it is so old that we are
c401cc
correctly avoiding a FIPS violation by preventing qemu from
c401cc
starting.  Meanwhile, if we don't detect FIPS mode, then
c401cc
omitting the argument is safe whether the qemu has the option
c401cc
(but it would do nothing because FIPS is disabled) or whether
c401cc
qemu lacks the option (including in the case where we are not
c401cc
running on Linux).
c401cc
c401cc
The testsuite was a bit interesting: we don't want our test
c401cc
to depend on whether it is being run in FIPS mode, so I had
c401cc
to tweak things to set the capability bit outside of our
c401cc
normal interaction with capability parsing.
c401cc
c401cc
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1035474
c401cc
c401cc
* src/qemu/qemu_capabilities.h (QEMU_CAPS_ENABLE_FIPS): New bit.
c401cc
* src/qemu/qemu_capabilities.c (virQEMUCapsInitQMP): Conditionally
c401cc
set capability according to detection of FIPS mode.
c401cc
* src/qemu/qemu_command.c (qemuBuildCommandLine): Use it.
c401cc
* tests/qemucapabilitiestest.c (testQemuCaps): Conditionally set
c401cc
capability to test expected output.
c401cc
* tests/qemucapabilitiesdata/caps_1.2.2-1.caps: Update list.
c401cc
* tests/qemucapabilitiesdata/caps_1.6.0-1.caps: Likewise.
c401cc
c401cc
Signed-off-by: Eric Blake <eblake@redhat.com>
c401cc
(cherry picked from commit a21cfb0f4864e891cee93eed94ed2e76efdb02ec)
c401cc
c401cc
Conflicts:
c401cc
	src/qemu/qemu_capabilities.c - not all upstream caps have been backported
c401cc
	src/qemu/qemu_capabilities.h - likewise
c401cc
	tests/qemucapabilitiesdata/caps_1.2.2-1.caps - test not backported
c401cc
	tests/qemucapabilitiesdata/caps_1.6.0-1.caps - likewise
c401cc
	tests/qemucapabilitiestest.c - likewise
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/qemu/qemu_capabilities.c | 25 +++++++++++++++++++++++++
c401cc
 src/qemu/qemu_capabilities.h |  1 +
c401cc
 src/qemu/qemu_command.c      |  2 ++
c401cc
 3 files changed, 28 insertions(+)
c401cc
c401cc
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
c401cc
index ba17cce..565d9ca 100644
c401cc
--- a/src/qemu/qemu_capabilities.c
c401cc
+++ b/src/qemu/qemu_capabilities.c
c401cc
@@ -240,6 +240,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
c401cc
               "ich9-intel-hda",
c401cc
               "boot-strict",
c401cc
               "pvpanic",
c401cc
+              "enable-fips",
c401cc
     );
c401cc
 
c401cc
 struct _virQEMUCaps {
c401cc
@@ -2514,6 +2515,30 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps,
c401cc
     config.data.nix.path = monpath;
c401cc
     config.data.nix.listen = false;
c401cc
 
c401cc
+    /* Qemu 1.2 and later have a binary flag -enable-fips that must be
c401cc
+     * used for VNC auth to obey FIPS settings; but the flag only
c401cc
+     * exists on Linux, and with no way to probe for it via QMP.  Our
c401cc
+     * solution: if FIPS mode is required, then unconditionally use
c401cc
+     * the flag, regardless of qemu version, for the following matrix:
c401cc
+     *
c401cc
+     *                          old QEMU            new QEMU
c401cc
+     * FIPS enabled             doesn't start       VNC auth disabled
c401cc
+     * FIPS disabled/missing    VNC auth enabled    VNC auth enabled
c401cc
+     *
c401cc
+     * Setting the flag here instead of in virQEMUCapsInitQMPMonitor
c401cc
+     * or virQEMUCapsInitHelp also allows the testsuite to be
c401cc
+     * independent of FIPS setting.
c401cc
+     */
c401cc
+    if (virFileExists("/proc/sys/crypto/fips_enabled")) {
c401cc
+        char *buf = NULL;
c401cc
+
c401cc
+        if (virFileReadAll("/proc/sys/crypto/fips_enabled", 10, &buf) < 0)
c401cc
+            goto cleanup;
c401cc
+        if (STREQ(buf, "1\n"))
c401cc
+            virQEMUCapsSet(qemuCaps, QEMU_CAPS_ENABLE_FIPS);
c401cc
+        VIR_FREE(buf);
c401cc
+    }
c401cc
+
c401cc
     VIR_DEBUG("Try to get caps via QMP qemuCaps=%p", qemuCaps);
c401cc
 
c401cc
     /*
c401cc
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
c401cc
index dea1e13..4117d87 100644
c401cc
--- a/src/qemu/qemu_capabilities.h
c401cc
+++ b/src/qemu/qemu_capabilities.h
c401cc
@@ -197,6 +197,7 @@ enum virQEMUCapsFlags {
c401cc
     QEMU_CAPS_DEVICE_ICH9_INTEL_HDA,    /* -device ich9-intel-hda */
c401cc
     QEMU_CAPS_BOOT_STRICT,              /* -boot strict */
c401cc
     QEMU_CAPS_DEVICE_PANIC,             /* -device pvpanic */
c401cc
+    QEMU_CAPS_ENABLE_FIPS,              /* -enable-fips */
c401cc
 
c401cc
     QEMU_CAPS_LAST,                   /* this must always be the last item */
c401cc
 };
c401cc
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
c401cc
index 35355b7..d43fdc9 100644
c401cc
--- a/src/qemu/qemu_command.c
c401cc
+++ b/src/qemu/qemu_command.c
c401cc
@@ -7556,6 +7556,8 @@ qemuBuildCommandLine(virConnectPtr conn,
c401cc
         }
c401cc
     }
c401cc
     virCommandAddArg(cmd, "-S"); /* freeze CPU */
c401cc
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_FIPS))
c401cc
+        virCommandAddArg(cmd, "-enable-fips");
c401cc
 
c401cc
     if (qemuBuildMachineArgStr(cmd, def, qemuCaps) < 0)
c401cc
         goto error;
c401cc
-- 
c401cc
1.8.5.2
c401cc