diff --git a/0009-Introduce-virt-what-cvm-program.patch b/0009-Introduce-virt-what-cvm-program.patch new file mode 100644 index 0000000..04a089b --- /dev/null +++ b/0009-Introduce-virt-what-cvm-program.patch @@ -0,0 +1,714 @@ +From 772dfd3a966d766d4566fd048f8b0178f7f827e5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Fri, 26 May 2023 12:39:03 +0100 +Subject: [PATCH] Introduce 'virt-what-cvm' program +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 'virt-what' program prints facts that reflect the hypervisor that +the guest is running under. + +The new complementary 'virt-what-cvm' program prints facts that reflect +the confidential virtualization technology the guest is running under, +if any. + +It is kept as a separate tool, rather than incorporating the facts into +'virt-what' output because it is considering a different aspect of the +virtualization. Furthermore there are specific security concerns around +the usage of facts reported by 'virt-what-cvm'. + +The tool has been tested in a number of environments + + * Azure confidential guest with AMD SEV-SNP (GA) + * Azure confidential guest with Intel TDX (technology preview) + * Fedora 37 QEMU/KVM guest with AMD SEV (GA) + * Fedora 37 QEMU/KVM guest with AMD SEV-ES (GA) + * Fedora 38 QEMU/KVM guest with AMD SEV-SNP + SVSM (devel snapshot) + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 22e33361e980ddefe08e2c68bf145943af8375f9) +--- + .gitignore | 3 + + Makefile.am | 12 +- + configure.ac | 3 + + virt-what-cvm.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++ + virt-what-cvm.pod | 195 ++++++++++++++++++++++ + 5 files changed, 613 insertions(+), 4 deletions(-) + create mode 100644 virt-what-cvm.c + create mode 100644 virt-what-cvm.pod + +diff --git a/.gitignore b/.gitignore +index 4833fd6be..ba897a162 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -26,5 +26,8 @@ Makefile.in + /test-driver + /virt-what + /virt-what-cpuid-helper ++/virt-what-cvm ++/virt-what-cvm.1 ++/virt-what-cvm.txt + /virt-what.1 + /virt-what.txt +diff --git a/Makefile.am b/Makefile.am +index 543513204..2050bef8d 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -24,20 +24,24 @@ EXTRA_DIST = .gitignore virt-what.in virt-what.pod + SUBDIRS = . tests + + sbin_SCRIPTS = virt-what ++sbin_PROGRAMS = virt-what-cvm + libexec_PROGRAMS = virt-what-cpuid-helper + if HOST_CPU_IA64 + libexec_PROGRAMS += virt-what-ia64-xen-rdtsc-test + endif + ++virt_what_cvm_LDADD = $(TPM2_TSS_LIBS) ++virt_what_cvm_CFLAGS = $(TPM2_TSS_CFLAGS) ++ + if HAVE_POD2MAN + +-CLEANFILES += virt-what.1 virt-what.txt +-man_MANS = virt-what.1 ++CLEANFILES += virt-what.1 virt-what-cvm.1 virt-what.txt virt-what-cvm.txt ++man_MANS = virt-what.1 virt-what-cvm.1 + +-virt-what.1: virt-what.pod ++%.1: %.pod + pod2man -c "Virtualization Support" --release "$(PACKAGE)-$(VERSION)" \ + $? > $@ +-virt-what.txt: virt-what.pod ++%.txt: %.pod + pod2text $? > $@ + + endif +diff --git a/configure.ac b/configure.ac +index 4dd2c9731..b1dadd64d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -32,6 +32,9 @@ dnl Architecture we are compiling for. + AC_CANONICAL_HOST + AM_CONDITIONAL([HOST_CPU_IA64], [ test "x$host_cpu" = "xia64" ]) + ++PKG_HAVE_DEFINE_WITH_MODULES(TPM2_TSS, tss2-esys, [tpm2-tss package]) ++ ++ + dnl List of tests. + tests="\ + alibaba-cloud-arm \ +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +new file mode 100644 +index 000000000..407efb492 +--- /dev/null ++++ b/virt-what-cvm.c +@@ -0,0 +1,404 @@ ++/* virt-what-cvm-helper: Are we running inside confidential VM ++ * Copyright (C) 2023 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_TPM2_TSS ++#include ++#include ++#endif ++ ++static bool dodebug = false; ++ ++#define debug(...) do { if (dodebug) fprintf(stderr, __VA_ARGS__); } while(0) ++ ++/* ++ * AMD64 Architecture Programmer’s Manual Volume 3: ++ * General-Purpose and System Instructions. ++ * Chapter: E4.1 - Maximum Extended Function Number and Vendor String ++ * https://www.amd.com/system/files/TechDocs/24594.pdf ++ */ ++#define CPUID_GET_HIGHEST_FUNCTION 0x80000000 ++ ++/* ++ * AMD64 Architecture Programmer’s Manual Volume 3: ++ * General-Purpose and System Instructions. ++ * Chapter: E4.17 - Encrypted Memory Capabilities ++ * https://www.amd.com/system/files/TechDocs/24594.pdf ++ */ ++#define CPUID_AMD_GET_ENCRYPTED_MEMORY_CAPABILITIES 0x8000001f ++ ++/* ++ * AMD64 Architecture Programmer’s Manual Volume 3: ++ * General-Purpose and System Instructions. ++ * Chapter: 15.34.10 - SEV_STATUS MSR ++ * https://www.amd.com/system/files/TechDocs/24593.pdf ++ */ ++#define MSR_AMD64_SEV 0xc0010131 ++ ++/* ++ * Intel® TDX Module v1.5 Base Architecture Specification ++ * Chapter: 11.2 ++ * https://www.intel.com/content/www/us/en/content-details/733575/intel-tdx-module-v1-5-base-architecture-specification.html ++ */ ++ ++#define CPUID_INTEL_TDX_ENUMERATION 0x21 ++ ++ ++#define CPUID_SIG_AMD "AuthenticAMD" ++#define CPUID_SIG_INTEL "GenuineIntel" ++#define CPUID_SIG_INTEL_TDX "IntelTDX " ++ ++/* ++ * This TPM NV data format is not explicitly documented anywhere, ++ * but the header definition is present in code at: ++ * ++ * https://github.com/kinvolk/azure-cvm-tooling/blob/main/az-snp-vtpm/src/hcl.rs ++ */ ++#define TPM_AZURE_HCLA_REPORT_INDEX 0x01400001 ++ ++struct TPMAzureHCLAHeader { ++ uint32_t signature; ++ uint32_t version; ++ uint32_t report_len; ++ uint32_t report_type; ++ uint32_t unknown[4]; ++}; ++ ++/* The bytes for "HCLA" */ ++#define TPM_AZURE_HCLA_SIGNATURE 0x414C4348 ++#define TPM_AZURE_HCLA_VERSION 0x1 ++#define TPM_AZURE_HCLA_REPORT_TYPE_SNP 0x2 ++ ++#if defined(__x86_64__) ++ ++#ifdef HAVE_TPM2_TSS ++static char * ++tpm_nvread(uint32_t nvindex, size_t *retlen) ++{ ++ TSS2_RC rc; ++ ESYS_CONTEXT *ctx = NULL; ++ ESYS_TR primary = ESYS_TR_NONE; ++ ESYS_TR session = ESYS_TR_NONE; ++ ESYS_TR nvobj = ESYS_TR_NONE; ++ TPM2B_NV_PUBLIC *pubData = NULL; ++ TPMT_SYM_DEF sym = { ++ .algorithm = TPM2_ALG_AES, ++ .keyBits = { .aes = 128 }, ++ .mode = { .aes = TPM2_ALG_CFB } ++ }; ++ char *ret; ++ size_t retwant; ++ ++ rc = Esys_Initialize(&ctx, NULL, NULL); ++ if (rc != TSS2_RC_SUCCESS) ++ return NULL; ++ ++ rc = Esys_Startup(ctx, TPM2_SU_CLEAR); ++ debug("tpm startup %d\n", rc); ++ if (rc != TSS2_RC_SUCCESS) ++ goto error; ++ ++ rc = Esys_StartAuthSession(ctx, ESYS_TR_NONE, ESYS_TR_NONE, ++ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, ++ NULL, 0, ++ &sym, TPM2_ALG_SHA256, &session); ++ debug("tpm auth session %d\n", rc); ++ if (rc != TSS2_RC_SUCCESS) ++ goto error; ++ ++ rc = Esys_TR_FromTPMPublic(ctx, nvindex, ESYS_TR_NONE, ++ ESYS_TR_NONE, ESYS_TR_NONE, &nvobj); ++ debug("tpm from public %d\n", rc); ++ if (rc != TSS2_RC_SUCCESS) ++ goto error; ++ ++ rc = Esys_NV_ReadPublic(ctx, nvobj, ESYS_TR_NONE, ++ ESYS_TR_NONE, ESYS_TR_NONE, ++ &pubData, NULL); ++ debug("tpm read public %d\n", rc); ++ if (rc != TPM2_RC_SUCCESS) ++ goto error; ++ ++ retwant = pubData->nvPublic.dataSize; ++ free(pubData); ++ *retlen = 0; ++ ret = malloc(retwant); ++ assert(ret); ++ while (*retlen < retwant) { ++ size_t want = retwant - *retlen; ++ TPM2B_MAX_NV_BUFFER *data = NULL; ++ if (want > 1024) ++ want = 1024; ++ rc = Esys_NV_Read(ctx, ESYS_TR_RH_OWNER, nvobj, session, ESYS_TR_NONE, ESYS_TR_NONE, ++ want, *retlen, &data); ++ debug("tpm nv read %d\n", rc); ++ if (rc != TPM2_RC_SUCCESS) { ++ free(ret); ++ goto error; ++ } ++ ++ memcpy(ret + *retlen, data->buffer, data->size); ++ *retlen += data->size; ++ free(data); ++ } ++ ++ return ret; ++ ++ error: ++ if (nvobj != ESYS_TR_NONE) ++ Esys_FlushContext(ctx, nvobj); ++ if (session != ESYS_TR_NONE) ++ Esys_FlushContext(ctx, session); ++ if (primary != ESYS_TR_NONE) ++ Esys_FlushContext(ctx, primary); ++ Esys_Finalize(&ctx); ++ *retlen = 0; ++ return NULL; ++} ++#else /* ! HAVE_TPM2_TSS */ ++static char * ++tpm_nvread(uint32_t nvindex, size_t *retlen) ++{ ++ return NULL; ++} ++#endif /* ! HAVE_TPM2_TSS */ ++ ++/* Copied from the Linux kernel definition in ++ * arch/x86/include/asm/processor.h ++ */ ++static inline void ++cpuid (uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) ++{ ++ debug("CPUID func %x %x\n", *eax, *ecx); ++ asm volatile ("cpuid" ++ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) ++ : "0" (*eax), "2" (*ecx) ++ : "memory"); ++ debug("CPUID result %x %x %x %x\n", *eax, *ebx, *ecx, *edx); ++} ++ ++ ++static uint32_t ++cpuid_leaf (uint32_t eax, char *sig) ++{ ++ uint32_t *sig32 = (uint32_t *) sig; ++ ++ cpuid (&eax, &sig32[0], &sig32[2], &sig32[1]); ++ sig[12] = 0; /* \0-terminate the string to make string comparison possible */ ++ debug("CPUID sig %s\n", sig); ++ return eax; ++} ++ ++#define MSR_DEVICE "/dev/cpu/0/msr" ++ ++static uint64_t ++msr (off_t index) ++{ ++ uint64_t ret; ++ int fd = open (MSR_DEVICE, O_RDONLY); ++ if (fd < 0) { ++ debug ("Cannot open MSR device %s", MSR_DEVICE); ++ return 0; ++ } ++ ++ if (pread (fd, &ret, sizeof(ret), index) != sizeof(ret)) ++ ret = 0; ++ ++ close (fd); ++ ++ debug ("MSR %llx result %llx\n", (unsigned long long)index, ++ (unsigned long long)ret); ++ return ret; ++} ++ ++bool ++cpu_sig_amd_azure (void) ++{ ++ size_t datalen = 0; ++ char *data = tpm_nvread(TPM_AZURE_HCLA_REPORT_INDEX, &datalen); ++ struct TPMAzureHCLAHeader *header = (struct TPMAzureHCLAHeader *)data; ++ bool ret; ++ ++ if (!data) ++ return false; ++ ++ if (datalen < sizeof(struct TPMAzureHCLAHeader)) { ++ debug ("TPM data len is too small to be an Azure HCLA report"); ++ return false; ++ } ++ ++ debug ("Azure TPM HCLA report header sig %x ver %x type %x\n", ++ header->signature, header->version, header->report_type); ++ ++ ret = (header->signature == TPM_AZURE_HCLA_SIGNATURE && ++ header->version == TPM_AZURE_HCLA_VERSION && ++ header->report_type == TPM_AZURE_HCLA_REPORT_TYPE_SNP); ++ debug ("Azure TPM HCLA report present ? %d\n", ret); ++ ++ free(data); ++ return ret; ++} ++ ++static void ++cpu_sig_amd (void) ++{ ++ uint32_t eax, ebx, ecx, edx; ++ uint64_t msrval; ++ ++ eax = CPUID_GET_HIGHEST_FUNCTION; ++ ebx = ecx = edx = 0; ++ ++ cpuid (&eax, &ebx, &ecx, &edx); ++ ++ if (eax < CPUID_AMD_GET_ENCRYPTED_MEMORY_CAPABILITIES) ++ return; ++ ++ eax = CPUID_AMD_GET_ENCRYPTED_MEMORY_CAPABILITIES; ++ ebx = ecx = edx = 0; ++ ++ cpuid (&eax, &ebx, &ecx, &edx); ++ ++ /* bit 1 == CPU supports SEV feature ++ * ++ * Note, Azure blocks this CPUID leaf from its SEV-SNP ++ * guests, so we must fallback to probing the TPM which ++ * exposes a SEV-SNP attestation report as evidence. ++ */ ++ if (!(eax & (1 << 1))) { ++ debug ("No sev in CPUID, try azure TPM NV\n"); ++ ++ if (cpu_sig_amd_azure()) { ++ puts ("amd-sev-snp"); ++ puts ("azure-hcl"); ++ } else { ++ debug("No azure TPM NV\n"); ++ } ++ return; ++ } ++ ++ msrval = msr (MSR_AMD64_SEV); ++ ++ /* Test reverse order, since the SEV-SNP bit implies ++ * the SEV-ES bit, which implies the SEV bit */ ++ if (msrval & (1 << 2)) { ++ puts ("amd-sev-snp"); ++ } else if (msrval & (1 << 1)) { ++ puts ("amd-sev-es"); ++ } else if (msrval & (1 << 0)) { ++ puts ("amd-sev"); ++ } ++} ++ ++static void ++cpu_sig_intel (void) ++{ ++ uint32_t eax, ebx, ecx, edx; ++ char sig[13]; ++ ++ eax = CPUID_GET_HIGHEST_FUNCTION; ++ ebx = ecx = edx = 0; ++ ++ cpuid (&eax, &ebx, &ecx, &edx); ++ debug ("CPUID max function: %x %x %x %x\n", eax, ebx, ecx,edx); ++ ++ if (eax < CPUID_INTEL_TDX_ENUMERATION) ++ return; ++ ++ memset (sig, 0, sizeof sig); ++ cpuid_leaf (CPUID_INTEL_TDX_ENUMERATION, sig); ++ ++ if (memcmp (sig, CPUID_SIG_INTEL_TDX, sizeof(sig)) == 0) ++ puts ("intel-tdx"); ++} ++ ++static void ++cpu_sig (void) ++{ ++ char sig[13]; ++ ++ memset (sig, 0, sizeof sig); ++ cpuid_leaf (0, sig); ++ ++ if (memcmp (sig, CPUID_SIG_AMD, sizeof(sig)) == 0) ++ cpu_sig_amd (); ++ else if (memcmp (sig, CPUID_SIG_INTEL, sizeof(sig)) == 0) ++ cpu_sig_intel (); ++} ++ ++#else /* !x86_64 */ ++ ++static void ++cpu_sig (void) ++{ ++ /* nothing for other architectures */ ++} ++ ++#endif ++ ++int ++main(int argc, char **argv) ++{ ++ int c; ++ ++ while (true) { ++ int option_index = 0; ++ static struct option long_options[] = { ++ {"debug", no_argument, 0, 'd' }, ++ {"version", no_argument, 0, 'v' }, ++ {"help", no_argument, 0, 'h'}, ++ {0, 0, 0, 0 } ++ }; ++ ++ c = getopt_long(argc, argv, "dvh", ++ long_options, &option_index); ++ if (c == -1) ++ break; ++ ++ switch (c) { ++ case 'd': ++ dodebug = true; ++ break; ++ case 'v': ++ fprintf(stdout, "%s\n", PACKAGE_VERSION); ++ exit(EXIT_SUCCESS); ++ break; ++ case 'h': ++ default: /* '?' */ ++ fprintf(c == 'h' ? stdout : stderr, ++ "Usage: %s [--debug|-d] [--help|-h] [--version|-v]\n", ++ argv[0]); ++ exit(c == 'h' ? EXIT_SUCCESS : EXIT_FAILURE); ++ } ++ } ++ ++ if (!dodebug) ++ setenv("TSS2_LOG", "all+none", 1); ++ ++ cpu_sig (); ++ ++ exit(EXIT_SUCCESS); ++} +diff --git a/virt-what-cvm.pod b/virt-what-cvm.pod +new file mode 100644 +index 000000000..12cfc6a96 +--- /dev/null ++++ b/virt-what-cvm.pod +@@ -0,0 +1,195 @@ ++=encoding utf8 ++ ++=head1 NAME ++ ++virt-what-cvm - detect if we are running in a confidential virtual machine ++ ++=head1 SUMMARY ++ ++virt-what-cvm [options] ++ ++=head1 DESCRIPTION ++ ++C is a tool which can be used to detect if the program ++is running in a confidential virtual machine. ++ ++The program prints out a list of "facts" about the confidential virtual ++machine, derived from heuristics. One fact is printed per line. ++ ++If nothing is printed and the script exits with code 0 (no error), ++then it can mean I that the program is running on bare-metal ++I the program is running inside a non-confidential virtual machine, ++I inside a type of confidential virtual machine which we don't know ++about or cannot detect. ++ ++=head1 FACTS ++ ++=over 4 ++ ++=item B ++ ++This is a confidential guest running with AMD SEV technology ++ ++Status: tested on Fedora 37 QEMU+KVM ++ ++=item B ++ ++This is a confidential guest running with AMD SEV-ES technology ++ ++Status: tested on Fedora 37 QEMU+KVM ++ ++=item B ++ ++This is a confidential guest running with AMD SEV-SNP technology ++ ++Status: tested on Microsoft Azure SEV-SNP CVM ++ ++Status: tested on Fedora 38 QEMU+KVM SEV-SNP (devel snapshot) ++ ++=item B ++ ++This is a confidential guest running with Intel TDX technology ++ ++Status: tested on Microsoft Azure TDX CVM (preview) ++ ++=item B ++ ++This is a confidential guest running unenlightened under the ++Azure HCL (Host Compatibility Layer). This will be paired with ++B. ++ ++Status: tested on Microsoft Azure SEV-SNP CVM ++ ++=back ++ ++=head1 EXIT STATUS ++ ++Programs that use or wrap C should check that the exit ++status is 0 before they attempt to parse the output of the command. ++ ++A non-zero exit status indicates some error, for example, an ++unrecognized command line argument. If the exit status is non-zero ++then the output "facts" (if any were printed) cannot be guaranteed and ++should be ignored. ++ ++The exit status does I have anything to do with whether the ++program is running on baremetal or under confidential virtualization, ++nor with whether C managed detection "correctly" (which ++is basically unknowable given the large variety of virtualization ++systems out there) ++ ++=head1 RUNNING VIRT-WHAT-CVM FROM OTHER PROGRAMS ++ ++C is designed so that you can easily run it from ++other programs or wrap it up in a library. ++ ++Your program should check the exit status (see the section above). ++ ++=head1 IMPORTANT NOTE ++ ++This program detects whether it is likely to be running within a known ++confidential VM, but does I prove that the environment is trustworthy. ++To attain trust in the environment requires an attestation report for the ++virtual machine, which is then verified by an already trusted 3rd party. ++ ++The hardware features that this program relies on to establish facts ++about the confidential virtualization environment, are those features ++whose behaviour will be proved by verification of an attestation report. ++ ++This program I have false positives. ie it may report that it is a ++confidential VM when it is in fact a non-confidential VM faking it. ++ ++This program I have false negatives. ie it should not fail to ++report existance of a confidential VM. Caveat that this only applies to ++environments which have been explicitly tested. ++ ++If this program does print a fact, this can be used for enabling or ++disabling use of certain features, according to whether they are ++appropriate for a confidential environment. None the less, the VM ++I be trusted until an attestation report is verified. ++ ++As a protection against false negatives from this tool, environments ++requiring high assurance should take one or more of these measures: ++ ++ * The facts reported by this program I should be measured ++ into one of the TPM PCRs ++ * The attestation report I cover the facts reported by ++ this program ++ * The attestation report I should cover the enablement ++ status of any features affected by decisions involving facts ++ reported by this tool ++ ++=head1 SEE ALSO ++ ++L, ++L, ++L ++ ++=head1 AUTHORS ++ ++Daniel P. Berrangé ++ ++=head1 COPYRIGHT ++ ++(C) Copyright 2023 Red Hat Inc., ++L ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, write to the Free Software ++Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++=head1 REPORTING BUGS ++ ++Bugs can be viewed on the Red Hat Bugzilla page: ++L. ++ ++If you find a bug in virt-what-cvm, please follow these steps to report it: ++ ++=over 4 ++ ++=item 1. Check for existing bug reports ++ ++Go to L and search for similar bugs. ++Someone may already have reported the same bug, and they may even ++have fixed it. ++ ++=item 2. Capture debug and error messages ++ ++Run ++ ++ virt-what-cvm -d > virt-what-cvm.log 2>&1 ++ ++and keep I. It may contain error messages which you ++should submit with your bug report. ++ ++=item 3. Get version of virt-what-cvm. ++ ++Run ++ ++ virt-what-cvm --version ++ ++=item 4. Submit a bug report. ++ ++Go to L and enter a new bug. ++Please describe the problem in as much detail as possible. ++ ++Remember to include the version numbers (step 3) and the debug ++messages file (step 2) and as much other detail as possible. ++ ++=item 5. Assign the bug to rjones @ redhat.com ++ ++Assign or reassign the bug to B (without the ++spaces). You can also send me an email with the bug number if you ++want a faster response. ++ ++=back +-- +2.43.0 + diff --git a/0010-docs-Add-cross-reference-to-virt-what-cvm-1-to-virt-.patch b/0010-docs-Add-cross-reference-to-virt-what-cvm-1-to-virt-.patch new file mode 100644 index 0000000..8cc5738 --- /dev/null +++ b/0010-docs-Add-cross-reference-to-virt-what-cvm-1-to-virt-.patch @@ -0,0 +1,25 @@ +From dbd90b1a4ceae884b06907da0b7964bcb8ff01d3 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 30 May 2023 08:46:06 +0100 +Subject: [PATCH] docs: Add cross reference to virt-what-cvm(1) to virt-what(1) + +(cherry picked from commit 52c833c7c6ede0b7fcefa7ad225206f410407eda) +--- + virt-what.pod | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/virt-what.pod b/virt-what.pod +index 45dd7c933..d60449d02 100644 +--- a/virt-what.pod ++++ b/virt-what.pod +@@ -409,6 +409,7 @@ specific features your drivers need (eg. for the presence of PCI devices). + + =head1 SEE ALSO + ++L, + L, + L, + L, +-- +2.43.0 + diff --git a/0011-virt-what-cvm-check-if-hypervisor-bit-is-set.patch b/0011-virt-what-cvm-check-if-hypervisor-bit-is-set.patch new file mode 100644 index 0000000..b3f1bc3 --- /dev/null +++ b/0011-virt-what-cvm-check-if-hypervisor-bit-is-set.patch @@ -0,0 +1,77 @@ +From 0b4886bea5fce89f588a1ac3c885b6860bb2deed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 29 Jun 2023 17:51:02 +0100 +Subject: [PATCH] virt-what-cvm: check if hypervisor bit is set +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before doing any probes for a confidential VM, check that the +tool is running under a hypervisor, rather than bare metal + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 64718d09a504bd10c6ab973acc0779925482b62f) +--- + virt-what-cvm.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +index 407efb492..f1847688b 100644 +--- a/virt-what-cvm.c ++++ b/virt-what-cvm.c +@@ -35,6 +35,9 @@ static bool dodebug = false; + + #define debug(...) do { if (dodebug) fprintf(stderr, __VA_ARGS__); } while(0) + ++ ++#define CPUID_PROCESSOR_INFO_AND_FEATURE_BITS 0x1 ++ + /* + * AMD64 Architecture Programmer’s Manual Volume 3: + * General-Purpose and System Instructions. +@@ -72,6 +75,9 @@ static bool dodebug = false; + #define CPUID_SIG_INTEL "GenuineIntel" + #define CPUID_SIG_INTEL_TDX "IntelTDX " + ++/* ecx bit 31: set => hyperpvisor, unset => bare metal */ ++#define CPUID_FEATURE_HYPERVISOR (1 << 31) ++ + /* + * This TPM NV data format is not explicitly documented anywhere, + * but the header definition is present in code at: +@@ -335,11 +341,32 @@ cpu_sig_intel (void) + puts ("intel-tdx"); + } + ++static bool ++cpu_is_hv (void) ++{ ++ uint32_t eax, ebx, ecx, edx; ++ bool is_hv; ++ ++ eax = CPUID_PROCESSOR_INFO_AND_FEATURE_BITS; ++ ebx = ecx = edx = 0; ++ ++ cpuid(&eax, &ebx, &ecx, &edx); ++ ++ is_hv = ecx & CPUID_FEATURE_HYPERVISOR; ++ ++ debug ("CPUID is hypervisor: %s\n", is_hv ? "yes" : "no"); ++ return is_hv; ++} ++ + static void + cpu_sig (void) + { + char sig[13]; + ++ /* Skip everything on bare metal */ ++ if (!cpu_is_hv ()) ++ return; ++ + memset (sig, 0, sizeof sig); + cpuid_leaf (0, sig); + +-- +2.43.0 + diff --git a/0012-virt-what-cvm-support-alternative-cpuid-leaf-orderin.patch b/0012-virt-what-cvm-support-alternative-cpuid-leaf-orderin.patch new file mode 100644 index 0000000..6449715 --- /dev/null +++ b/0012-virt-what-cvm-support-alternative-cpuid-leaf-orderin.patch @@ -0,0 +1,59 @@ +From 56498baf2eddf072b9dcab7570febc6ce8f58504 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 29 Jun 2023 17:51:03 +0100 +Subject: [PATCH] virt-what-cvm: support alternative cpuid leaf ordering +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The HyperV CPUID leaf for reporting the vendor string has an +alternative ordering of ecx/edx. + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 15d3e4a92fd9c1490fb6f86b7ab3a2dff8364837) +--- + virt-what-cvm.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +index f1847688b..1e7c50bb0 100644 +--- a/virt-what-cvm.c ++++ b/virt-what-cvm.c +@@ -209,11 +209,14 @@ cpuid (uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) + + + static uint32_t +-cpuid_leaf (uint32_t eax, char *sig) ++cpuid_leaf (uint32_t eax, char *sig, bool swapped) + { + uint32_t *sig32 = (uint32_t *) sig; + +- cpuid (&eax, &sig32[0], &sig32[2], &sig32[1]); ++ if (swapped) ++ cpuid (&eax, &sig32[0], &sig32[2], &sig32[1]); ++ else ++ cpuid (&eax, &sig32[0], &sig32[1], &sig32[2]); + sig[12] = 0; /* \0-terminate the string to make string comparison possible */ + debug("CPUID sig %s\n", sig); + return eax; +@@ -335,7 +338,7 @@ cpu_sig_intel (void) + return; + + memset (sig, 0, sizeof sig); +- cpuid_leaf (CPUID_INTEL_TDX_ENUMERATION, sig); ++ cpuid_leaf (CPUID_INTEL_TDX_ENUMERATION, sig, true); + + if (memcmp (sig, CPUID_SIG_INTEL_TDX, sizeof(sig)) == 0) + puts ("intel-tdx"); +@@ -368,7 +371,7 @@ cpu_sig (void) + return; + + memset (sig, 0, sizeof sig); +- cpuid_leaf (0, sig); ++ cpuid_leaf (0, sig, true); + + if (memcmp (sig, CPUID_SIG_AMD, sizeof(sig)) == 0) + cpu_sig_amd (); +-- +2.43.0 + diff --git a/0013-virt-what-cvm-probe-for-SNP-HCL-on-HyperV-Azure-via-.patch b/0013-virt-what-cvm-probe-for-SNP-HCL-on-HyperV-Azure-via-.patch new file mode 100644 index 0000000..25df415 --- /dev/null +++ b/0013-virt-what-cvm-probe-for-SNP-HCL-on-HyperV-Azure-via-.patch @@ -0,0 +1,117 @@ +From eecffe8b20d7e136e64d7360ef6655c8eee4250e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 29 Jun 2023 17:51:04 +0100 +Subject: [PATCH] virt-what-cvm: probe for SNP/HCL on HyperV/Azure via CPUID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When running a confidential VM on Azure (HyperV) we can probe +CPUID leaf 0x40000003 to detect if VM isolation is present, +and 0x4000000c to detect what kind of isolation is used. + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit bb0055b491501e16fca3ab61dc7a969effbf48f3) +--- + virt-what-cvm.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 60 insertions(+), 2 deletions(-) + +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +index 1e7c50bb0..a7a224f94 100644 +--- a/virt-what-cvm.c ++++ b/virt-what-cvm.c +@@ -70,14 +70,33 @@ static bool dodebug = false; + + #define CPUID_INTEL_TDX_ENUMERATION 0x21 + ++/* Requirements for Implementing the Microsoft Hypervisor Interface ++ * https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/tlfs ++ */ ++#define CPUID_HYPERV_VENDOR_AND_MAX_FUNCTIONS 0x40000000 ++ ++#define CPUID_HYPERV_FEATURES 0x40000003 ++ ++#define CPUID_HYPERV_ISOLATION_CONFIG 0x4000000C ++ ++#define CPUID_HYPERV_MIN 0x40000005 ++#define CPUID_HYPERV_MAX 0x4000ffff + + #define CPUID_SIG_AMD "AuthenticAMD" + #define CPUID_SIG_INTEL "GenuineIntel" + #define CPUID_SIG_INTEL_TDX "IntelTDX " ++#define CPUID_SIG_HYPERV "Microsoft Hv" + + /* ecx bit 31: set => hyperpvisor, unset => bare metal */ + #define CPUID_FEATURE_HYPERVISOR (1 << 31) + ++/* Linux include/asm-generic/hyperv-tlfs.h */ ++#define CPUID_HYPERV_CPU_MANAGEMENT (1 << 12) /* root partition */ ++#define CPUID_HYPERV_ISOLATION (1 << 22) /* confidential VM partition */ ++ ++#define CPUID_HYPERV_ISOLATION_TYPE_MASK 0xf ++#define CPUID_HYPERV_ISOLATION_TYPE_SNP 2 ++ + /* + * This TPM NV data format is not explicitly documented anywhere, + * but the header definition is present in code at: +@@ -272,6 +291,44 @@ cpu_sig_amd_azure (void) + return ret; + } + ++static bool ++cpu_sig_amd_hyperv (void) ++{ ++ uint32_t eax, ebx, ecx, edx; ++ char sig[13]; ++ uint32_t feat; ++ ++ feat = cpuid_leaf (CPUID_HYPERV_VENDOR_AND_MAX_FUNCTIONS, sig, false); ++ ++ if (feat < CPUID_HYPERV_MIN || ++ feat > CPUID_HYPERV_MAX) ++ return false; ++ ++ if (memcmp (sig, CPUID_SIG_HYPERV, sizeof(sig)) != 0) ++ return false; ++ ++ debug ("CPUID is on hyperv\n"); ++ eax = CPUID_HYPERV_FEATURES; ++ ebx = ecx = edx = 0; ++ ++ cpuid(&eax, &ebx, &ecx, &edx); ++ ++ if (ebx & CPUID_HYPERV_ISOLATION && ++ !(ebx & CPUID_HYPERV_CPU_MANAGEMENT)) { ++ ++ eax = CPUID_HYPERV_ISOLATION_CONFIG; ++ ebx = ecx = edx = 0; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ ++ if ((ebx & CPUID_HYPERV_ISOLATION_TYPE_MASK) == ++ CPUID_HYPERV_ISOLATION_TYPE_SNP) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + static void + cpu_sig_amd (void) + { +@@ -298,9 +355,10 @@ cpu_sig_amd (void) + * exposes a SEV-SNP attestation report as evidence. + */ + if (!(eax & (1 << 1))) { +- debug ("No sev in CPUID, try azure TPM NV\n"); ++ debug ("No sev in CPUID, try hyperv CPUID/azure TPM NV\n"); + +- if (cpu_sig_amd_azure()) { ++ if (cpu_sig_amd_hyperv () || ++ cpu_sig_amd_azure()) { + puts ("amd-sev-snp"); + puts ("azure-hcl"); + } else { +-- +2.43.0 + diff --git a/0014-virt-what-cvm-drop-TPM-logic-for-detecting-SNP-on-Hy.patch b/0014-virt-what-cvm-drop-TPM-logic-for-detecting-SNP-on-Hy.patch new file mode 100644 index 0000000..8afe804 --- /dev/null +++ b/0014-virt-what-cvm-drop-TPM-logic-for-detecting-SNP-on-Hy.patch @@ -0,0 +1,258 @@ +From 5658e72cb0de7e0e31fd16df7a3b80015ce6dc71 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 29 Jun 2023 17:51:05 +0100 +Subject: [PATCH] virt-what-cvm: drop TPM logic for detecting SNP on + HyperV/Azure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now we have proper CPUID detection, we no longer need the TPM +hacks. + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 82c0e9c469953a36f18db1e329629cecd950134a) +--- + Makefile.am | 3 - + configure.ac | 2 - + virt-what-cvm.c | 161 ++---------------------------------------------- + 3 files changed, 6 insertions(+), 160 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 2050bef8d..b68540f39 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -30,9 +30,6 @@ if HOST_CPU_IA64 + libexec_PROGRAMS += virt-what-ia64-xen-rdtsc-test + endif + +-virt_what_cvm_LDADD = $(TPM2_TSS_LIBS) +-virt_what_cvm_CFLAGS = $(TPM2_TSS_CFLAGS) +- + if HAVE_POD2MAN + + CLEANFILES += virt-what.1 virt-what-cvm.1 virt-what.txt virt-what-cvm.txt +diff --git a/configure.ac b/configure.ac +index b1dadd64d..0309a80bd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -32,8 +32,6 @@ dnl Architecture we are compiling for. + AC_CANONICAL_HOST + AM_CONDITIONAL([HOST_CPU_IA64], [ test "x$host_cpu" = "xia64" ]) + +-PKG_HAVE_DEFINE_WITH_MODULES(TPM2_TSS, tss2-esys, [tpm2-tss package]) +- + + dnl List of tests. + tests="\ +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +index a7a224f94..8b8a4df09 100644 +--- a/virt-what-cvm.c ++++ b/virt-what-cvm.c +@@ -26,10 +26,6 @@ + #include + #include + #include +-#ifdef HAVE_TPM2_TSS +-#include +-#include +-#endif + + static bool dodebug = false; + +@@ -97,121 +93,8 @@ static bool dodebug = false; + #define CPUID_HYPERV_ISOLATION_TYPE_MASK 0xf + #define CPUID_HYPERV_ISOLATION_TYPE_SNP 2 + +-/* +- * This TPM NV data format is not explicitly documented anywhere, +- * but the header definition is present in code at: +- * +- * https://github.com/kinvolk/azure-cvm-tooling/blob/main/az-snp-vtpm/src/hcl.rs +- */ +-#define TPM_AZURE_HCLA_REPORT_INDEX 0x01400001 +- +-struct TPMAzureHCLAHeader { +- uint32_t signature; +- uint32_t version; +- uint32_t report_len; +- uint32_t report_type; +- uint32_t unknown[4]; +-}; +- +-/* The bytes for "HCLA" */ +-#define TPM_AZURE_HCLA_SIGNATURE 0x414C4348 +-#define TPM_AZURE_HCLA_VERSION 0x1 +-#define TPM_AZURE_HCLA_REPORT_TYPE_SNP 0x2 +- + #if defined(__x86_64__) + +-#ifdef HAVE_TPM2_TSS +-static char * +-tpm_nvread(uint32_t nvindex, size_t *retlen) +-{ +- TSS2_RC rc; +- ESYS_CONTEXT *ctx = NULL; +- ESYS_TR primary = ESYS_TR_NONE; +- ESYS_TR session = ESYS_TR_NONE; +- ESYS_TR nvobj = ESYS_TR_NONE; +- TPM2B_NV_PUBLIC *pubData = NULL; +- TPMT_SYM_DEF sym = { +- .algorithm = TPM2_ALG_AES, +- .keyBits = { .aes = 128 }, +- .mode = { .aes = TPM2_ALG_CFB } +- }; +- char *ret; +- size_t retwant; +- +- rc = Esys_Initialize(&ctx, NULL, NULL); +- if (rc != TSS2_RC_SUCCESS) +- return NULL; +- +- rc = Esys_Startup(ctx, TPM2_SU_CLEAR); +- debug("tpm startup %d\n", rc); +- if (rc != TSS2_RC_SUCCESS) +- goto error; +- +- rc = Esys_StartAuthSession(ctx, ESYS_TR_NONE, ESYS_TR_NONE, +- ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, +- NULL, 0, +- &sym, TPM2_ALG_SHA256, &session); +- debug("tpm auth session %d\n", rc); +- if (rc != TSS2_RC_SUCCESS) +- goto error; +- +- rc = Esys_TR_FromTPMPublic(ctx, nvindex, ESYS_TR_NONE, +- ESYS_TR_NONE, ESYS_TR_NONE, &nvobj); +- debug("tpm from public %d\n", rc); +- if (rc != TSS2_RC_SUCCESS) +- goto error; +- +- rc = Esys_NV_ReadPublic(ctx, nvobj, ESYS_TR_NONE, +- ESYS_TR_NONE, ESYS_TR_NONE, +- &pubData, NULL); +- debug("tpm read public %d\n", rc); +- if (rc != TPM2_RC_SUCCESS) +- goto error; +- +- retwant = pubData->nvPublic.dataSize; +- free(pubData); +- *retlen = 0; +- ret = malloc(retwant); +- assert(ret); +- while (*retlen < retwant) { +- size_t want = retwant - *retlen; +- TPM2B_MAX_NV_BUFFER *data = NULL; +- if (want > 1024) +- want = 1024; +- rc = Esys_NV_Read(ctx, ESYS_TR_RH_OWNER, nvobj, session, ESYS_TR_NONE, ESYS_TR_NONE, +- want, *retlen, &data); +- debug("tpm nv read %d\n", rc); +- if (rc != TPM2_RC_SUCCESS) { +- free(ret); +- goto error; +- } +- +- memcpy(ret + *retlen, data->buffer, data->size); +- *retlen += data->size; +- free(data); +- } +- +- return ret; +- +- error: +- if (nvobj != ESYS_TR_NONE) +- Esys_FlushContext(ctx, nvobj); +- if (session != ESYS_TR_NONE) +- Esys_FlushContext(ctx, session); +- if (primary != ESYS_TR_NONE) +- Esys_FlushContext(ctx, primary); +- Esys_Finalize(&ctx); +- *retlen = 0; +- return NULL; +-} +-#else /* ! HAVE_TPM2_TSS */ +-static char * +-tpm_nvread(uint32_t nvindex, size_t *retlen) +-{ +- return NULL; +-} +-#endif /* ! HAVE_TPM2_TSS */ +- + /* Copied from the Linux kernel definition in + * arch/x86/include/asm/processor.h + */ +@@ -263,34 +146,6 @@ msr (off_t index) + return ret; + } + +-bool +-cpu_sig_amd_azure (void) +-{ +- size_t datalen = 0; +- char *data = tpm_nvread(TPM_AZURE_HCLA_REPORT_INDEX, &datalen); +- struct TPMAzureHCLAHeader *header = (struct TPMAzureHCLAHeader *)data; +- bool ret; +- +- if (!data) +- return false; +- +- if (datalen < sizeof(struct TPMAzureHCLAHeader)) { +- debug ("TPM data len is too small to be an Azure HCLA report"); +- return false; +- } +- +- debug ("Azure TPM HCLA report header sig %x ver %x type %x\n", +- header->signature, header->version, header->report_type); +- +- ret = (header->signature == TPM_AZURE_HCLA_SIGNATURE && +- header->version == TPM_AZURE_HCLA_VERSION && +- header->report_type == TPM_AZURE_HCLA_REPORT_TYPE_SNP); +- debug ("Azure TPM HCLA report present ? %d\n", ret); +- +- free(data); +- return ret; +-} +- + static bool + cpu_sig_amd_hyperv (void) + { +@@ -350,19 +205,18 @@ cpu_sig_amd (void) + + /* bit 1 == CPU supports SEV feature + * +- * Note, Azure blocks this CPUID leaf from its SEV-SNP +- * guests, so we must fallback to probing the TPM which +- * exposes a SEV-SNP attestation report as evidence. ++ * Note, HyperV/Azure blocks this CPUID leaf from its SEV-SNP ++ * guests. We already did an alternative detection mechanism ++ * in such VMs, so should not even be running this code. + */ + if (!(eax & (1 << 1))) { +- debug ("No sev in CPUID, try hyperv CPUID/azure TPM NV\n"); ++ debug ("No sev in CPUID, try hyperv CPUID\n"); + +- if (cpu_sig_amd_hyperv () || +- cpu_sig_amd_azure()) { ++ if (cpu_sig_amd_hyperv ()) { + puts ("amd-sev-snp"); + puts ("azure-hcl"); + } else { +- debug("No azure TPM NV\n"); ++ debug("No hyperv CPUID\n"); + } + return; + } +@@ -483,9 +337,6 @@ main(int argc, char **argv) + } + } + +- if (!dodebug) +- setenv("TSS2_LOG", "all+none", 1); +- + cpu_sig (); + + exit(EXIT_SUCCESS); +-- +2.43.0 + diff --git a/0015-virt-what-cvm-rename-azure-hcl-fact-to-hyperv-hcl.patch b/0015-virt-what-cvm-rename-azure-hcl-fact-to-hyperv-hcl.patch new file mode 100644 index 0000000..8c67662 --- /dev/null +++ b/0015-virt-what-cvm-rename-azure-hcl-fact-to-hyperv-hcl.patch @@ -0,0 +1,53 @@ +From fc766c6db5305effdaaaa843d6a2c2b4623c8b99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 29 Jun 2023 17:51:06 +0100 +Subject: [PATCH] virt-what-cvm: rename 'azure-hcl' fact to 'hyperv-hcl' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Azure is a cloud service that uses the HyperV platform, so we +should refer to the fact as 'hyperv-hcl', not 'azure-hcl'. + +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 94773022f76f994d7a9b37f59ba978bd28f30d1d) +--- + virt-what-cvm.c | 2 +- + virt-what-cvm.pod | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/virt-what-cvm.c b/virt-what-cvm.c +index 8b8a4df09..52b3426bc 100644 +--- a/virt-what-cvm.c ++++ b/virt-what-cvm.c +@@ -214,7 +214,7 @@ cpu_sig_amd (void) + + if (cpu_sig_amd_hyperv ()) { + puts ("amd-sev-snp"); +- puts ("azure-hcl"); ++ puts ("hyperv-hcl"); + } else { + debug("No hyperv CPUID\n"); + } +diff --git a/virt-what-cvm.pod b/virt-what-cvm.pod +index 12cfc6a96..0f9076569 100644 +--- a/virt-what-cvm.pod ++++ b/virt-what-cvm.pod +@@ -52,11 +52,11 @@ This is a confidential guest running with Intel TDX technology + + Status: tested on Microsoft Azure TDX CVM (preview) + +-=item B ++=item B + + This is a confidential guest running unenlightened under the +-Azure HCL (Host Compatibility Layer). This will be paired with +-B. ++HyperV (Azure) HCL (Host Compatibility Layer). This will be ++paired with B. + + Status: tested on Microsoft Azure SEV-SNP CVM + +-- +2.43.0 + diff --git a/0016-Add-virt-what-cvm.pod-to-EXTRA_DIST.patch b/0016-Add-virt-what-cvm.pod-to-EXTRA_DIST.patch new file mode 100644 index 0000000..1f80123 --- /dev/null +++ b/0016-Add-virt-what-cvm.pod-to-EXTRA_DIST.patch @@ -0,0 +1,26 @@ +From c8daee800cbe22e622306f78a71188ec5639d4a1 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 26 Jul 2024 16:05:12 +0100 +Subject: [PATCH] Add virt-what-cvm.pod to EXTRA_DIST + +(Single hunk cherry pick from commit 6d1455766b) +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index b68540f39..ba5185741 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -19,7 +19,7 @@ AM_CPPFLAGS = -Wall + + CLEANFILES = virt-what *~ + +-EXTRA_DIST = .gitignore virt-what.in virt-what.pod ++EXTRA_DIST = .gitignore virt-what.in virt-what.pod virt-what-cvm.pod + + SUBDIRS = . tests + +-- +2.43.0 + diff --git a/virt-what.spec b/virt-what.spec index a134881..35967d4 100644 --- a/virt-what.spec +++ b/virt-what.spec @@ -1,6 +1,6 @@ Name: virt-what Version: 1.25 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Detect if we are running in a virtual machine License: GPLv2+ @@ -22,6 +22,14 @@ Patch0005: 0005-Add-support-for-Alibaba-cloud-on-aarch64.patch Patch0006: 0006-nutanix-Don-t-match-Nutanix-based-baremetal-systems.patch Patch0007: 0007-Add-support-for-CRI-O-containers.patch Patch0008: 0008-Fix-support-for-Hyper-V-on-Arm.patch +Patch0009: 0009-Introduce-virt-what-cvm-program.patch +Patch0010: 0010-docs-Add-cross-reference-to-virt-what-cvm-1-to-virt-.patch +Patch0011: 0011-virt-what-cvm-check-if-hypervisor-bit-is-set.patch +Patch0012: 0012-virt-what-cvm-support-alternative-cpuid-leaf-orderin.patch +Patch0013: 0013-virt-what-cvm-probe-for-SNP-HCL-on-HyperV-Azure-via-.patch +Patch0014: 0014-virt-what-cvm-drop-TPM-logic-for-detecting-SNP-on-Hy.patch +Patch0015: 0015-virt-what-cvm-rename-azure-hcl-fact-to-hyperv-hcl.patch +Patch0016: 0016-Add-virt-what-cvm.pod-to-EXTRA_DIST.patch BuildRequires: make BuildRequires: git @@ -123,11 +131,16 @@ fi %files %doc README COPYING %{_sbindir}/virt-what +%{_sbindir}/virt-what-cvm %{_libexecdir}/virt-what-cpuid-helper %{_mandir}/man1/*.1* %changelog +* Fri Jul 26 2024 Richard W.M. Jones - 1.25-7 +- Add virt-what-cvm tool + resolves: RHEL-50659 + * Tue Jul 02 2024 Richard W.M. Jones - 1.25-6 - Add support for Azure VMs on ARM resolves: RHEL-45834