diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5e9c65eec3..4f64f878e5 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -245,7 +245,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "kvm-pit-lost-tick-policy", "boot-strict", /* 160 */ - "pvpanic", /* 161 */ + "pvpanic", + "enable-fips", ); struct _virQEMUCaps { @@ -2630,6 +2631,30 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, config.data.nix.path = monpath; config.data.nix.listen = false; + /* Qemu 1.2 and later have a binary flag -enable-fips that must be + * used for VNC auth to obey FIPS settings; but the flag only + * exists on Linux, and with no way to probe for it via QMP. Our + * solution: if FIPS mode is required, then unconditionally use + * the flag, regardless of qemu version, for the following matrix: + * + * old QEMU new QEMU + * FIPS enabled doesn't start VNC auth disabled + * FIPS disabled/missing VNC auth enabled VNC auth enabled + * + * Setting the flag here instead of in virQEMUCapsInitQMPMonitor + * or virQEMUCapsInitHelp also allows the testsuite to be + * independent of FIPS setting. + */ + if (virFileExists("/proc/sys/crypto/fips_enabled")) { + char *buf = NULL; + + if (virFileReadAll("/proc/sys/crypto/fips_enabled", 10, &buf) < 0) + goto cleanup; + if (STREQ(buf, "1\n")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_ENABLE_FIPS); + VIR_FREE(buf); + } + VIR_DEBUG("Try to get caps via QMP qemuCaps=%p", qemuCaps); /* diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index bbf4972cf1..efb3f43783 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -200,6 +200,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_KVM_PIT_TICK_POLICY = 159, /* kvm-pit.lost_tick_policy */ QEMU_CAPS_BOOT_STRICT = 160, /* -boot strict */ QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */ + QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a80559e755..d723dc8d16 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7747,6 +7747,8 @@ qemuBuildCommandLine(virConnectPtr conn, } } virCommandAddArg(cmd, "-S"); /* freeze CPU */ + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_FIPS)) + virCommandAddArg(cmd, "-enable-fips"); if (qemuBuildMachineArgStr(cmd, def, qemuCaps) < 0) goto error; diff --git a/tests/qemucapabilitiesdata/caps_1.2.2-1.caps b/tests/qemucapabilitiesdata/caps_1.2.2-1.caps index 73a561dc74..c3ae814b1c 100644 --- a/tests/qemucapabilitiesdata/caps_1.2.2-1.caps +++ b/tests/qemucapabilitiesdata/caps_1.2.2-1.caps @@ -112,4 +112,5 @@ + diff --git a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps index c7ce591ca7..2d50cf98fc 100644 --- a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps @@ -138,4 +138,5 @@ + diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c index d9121715e7..3b34f78004 100644 --- a/tests/qemucapabilitiestest.c +++ b/tests/qemucapabilitiestest.c @@ -31,6 +31,7 @@ typedef testQemuData *testQemuDataPtr; struct _testQemuData { virDomainXMLOptionPtr xmlopt; const char *base; + bool fips; }; static qemuMonitorTestPtr @@ -192,6 +193,12 @@ testQemuCaps(const void *opaque) qemuMonitorTestGetMonitor(mon)) < 0) goto cleanup; + /* So that our test does not depend on the contents of /proc, we + * hoisted the setting of ENABLE_FIPS to virQEMUCapsInitQMP. But + * we do want to test the effect of that flag. */ + if (data->fips) + virQEMUCapsSet(capsComputed, QEMU_CAPS_ENABLE_FIPS); + if (testQemuCapsCompare(capsProvided, capsComputed) < 0) goto cleanup; @@ -227,16 +234,19 @@ mymain(void) data.xmlopt = xmlopt; -#define DO_TEST(name) \ - data.base = name; \ - if (virtTestRun(name, testQemuCaps, &data) < 0) \ +#define DO_TEST_FULL(name, use_fips) \ + data.base = name; \ + data.fips = use_fips; \ + if (virtTestRun(name, testQemuCaps, &data) < 0) \ ret = -1 - DO_TEST("caps_1.2.2-1"); +#define DO_TEST(name) DO_TEST_FULL(name, false) + + DO_TEST_FULL("caps_1.2.2-1", true); DO_TEST("caps_1.3.1-1"); DO_TEST("caps_1.4.2-1"); DO_TEST("caps_1.5.3-1"); - DO_TEST("caps_1.6.0-1"); + DO_TEST_FULL("caps_1.6.0-1", true); DO_TEST("caps_1.6.50-1"); virObjectUnref(xmlopt);