Merge pull request #28242 from berrange/cond-sec-cvm

Detect and expose the confidential virtualization technology in various places
This commit is contained in:
Luca Boccassi 2023-07-06 19:14:26 +01:00 committed by GitHub
commit f00022eb86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 450 additions and 4 deletions

View file

@ -305,6 +305,8 @@ node /org/freedesktop/systemd1 {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Virtualization = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ConfidentialVirtualization = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Architecture = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Tainted = '...';
@ -1010,6 +1012,8 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-property" generated="True" extra-ref="Virtualization"/>
<variablelist class="dbus-property" generated="True" extra-ref="ConfidentialVirtualization"/>
<variablelist class="dbus-property" generated="True" extra-ref="Architecture"/>
<variablelist class="dbus-property" generated="True" extra-ref="Tainted"/>
@ -1765,6 +1769,12 @@ node /org/freedesktop/systemd1 {
Note that only the "innermost" virtualization technology is exported here. This detects both
full-machine virtualizations (VMs) and shared-kernel virtualization (containers).</para>
<para><varname>ConfidentialVirtualization</varname> contains a short ID string describing the confidential
virtualization technology the system runs in. On bare-metal hardware this is the empty string. Otherwise,
it contains an identifier such as <literal>sev</literal>, <literal>sev-es</literal>, <literal>sev-snp</literal>,
<literal>tdx</literal> and so on. For a full list of IDs see
<citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry></para>.
<para><varname>Architecture</varname> contains a short ID string describing the architecture the
systemd instance is running on. This follows the same vocabulary as
<varname>ConditionArchitectures=</varname>.</para>

View file

@ -257,6 +257,16 @@
for more information.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--cvm</option></term>
<listitem><para>Detect whether invoked in a confidential virtual machine.
The result of this detection may be used to disable features that should
not be used in confidential VMs. It must not be used to release security
sensitive information. The latter must only be released after attestation
of the confidential environment.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-q</option></term>
<term><option>--quiet</option></term>
@ -271,6 +281,12 @@
<listitem><para>Output all currently known and detectable container and VM environments.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--list-cvm</option></term>
<listitem><para>Output all currently known and detectable confidential virtualization technologies.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>

View file

@ -204,6 +204,17 @@
<command>systemd-creds --system cat</command> command.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$SYSTEMD_CONFIDENTIAL_VIRTUALIZATION</varname></term>
<listitem><para>If the service manager is run in a confidential virtualized environment,
<varname>$SYSTEMD_CONFIDENTIAL_VIRTUALIZATION</varname> is set to a string that identifies
the confidential virtualization hardware technology. If no confidential virtualization is
detected this variable will not be set. This data is identical to what
<citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry>
detects and reports, and uses the same vocabulary of confidential virtualization
technology identifiers.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -1404,8 +1404,8 @@
security technology is enabled on the system. Currently, the recognized values are
<literal>selinux</literal>, <literal>apparmor</literal>, <literal>tomoyo</literal>,
<literal>ima</literal>, <literal>smack</literal>, <literal>audit</literal>,
<literal>uefi-secureboot</literal> and <literal>tpm2</literal>. The test may be negated by prepending
an exclamation mark.</para>
<literal>uefi-secureboot</literal>, <literal>tpm2</literal> and <literal>cvm</literal>.
The test may be negated by prepending an exclamation mark.</para>
</listitem>
</varlistentry>

View file

@ -279,6 +279,14 @@
for possible values.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>cvm</literal></term>
<listitem>
<para>System's confidential virtualization technology. See
<citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible values.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Unknown keys will never match.</para>
</listitem>

View file

@ -28,8 +28,8 @@ _systemd_detect_virt() {
local i verb comps
local -A OPTS=(
[STANDALONE]='-h --help --version -c --container -v --vm -q --quiet
--private-users'
[STANDALONE]='-h --help --version -c --container -v --vm -q --quiet --cvm
--private-users --list --list-cvm'
)
_init_completion || return

View file

@ -0,0 +1,293 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#if defined(__i386__) || defined(__x86_64__)
#include <cpuid.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include "confidential-virt.h"
#include "fd-util.h"
#include "missing_threads.h"
#include "string-table.h"
#include "utf8.h"
#define CPUID_PROCESSOR_INFO_AND_FEATURE_BITS UINT32_C(0x1)
/*
* AMD64 Architecture Programmers 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 UINT32_C(0x80000000)
/*
* AMD64 Architecture Programmers 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 UINT32_C(0x8000001f)
/*
* AMD64 Architecture Programmers 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 UINT32_C(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 UINT32_C(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 UINT32_C(0x40000000)
#define CPUID_HYPERV_FEATURES UINT32_C(0x40000003)
#define CPUID_HYPERV_ISOLATION_CONFIG UINT32_C(0x4000000C)
#define CPUID_HYPERV_MIN UINT32_C(0x40000005)
#define CPUID_HYPERV_MAX UINT32_C(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 (UINT32_C(1) << 31)
/* Linux include/asm-generic/hyperv-tlfs.h */
#define CPUID_HYPERV_CPU_MANAGEMENT (UINT32_C(1) << 12) /* root partition */
#define CPUID_HYPERV_ISOLATION (UINT32_C(1) << 22) /* confidential VM partition */
#define CPUID_HYPERV_ISOLATION_TYPE_MASK UINT32_C(0xf)
#define CPUID_HYPERV_ISOLATION_TYPE_SNP 2
#define EAX_SEV (UINT32_C(1) << 1)
#define MSR_SEV (UINT64_C(1) << 0)
#define MSR_SEV_ES (UINT64_C(1) << 1)
#define MSR_SEV_SNP (UINT64_C(1) << 2)
#if defined(__x86_64__)
static void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
log_debug("CPUID func %" PRIx32 " %" PRIx32, *eax, *ecx);
__cpuid_count(*eax, *ecx, *eax, *ebx, *ecx, *edx);
log_debug("CPUID result %" PRIx32 " %" PRIx32 " %" PRIx32 " %" PRIx32, *eax, *ebx, *ecx, *edx);
}
static uint32_t cpuid_leaf(uint32_t eax, char ret_sig[static 13], bool swapped) {
/* zero-init as some queries explicitly require subleaf == 0 */
uint32_t sig[3] = {};
if (swapped)
cpuid(&eax, &sig[0], &sig[2], &sig[1]);
else
cpuid(&eax, &sig[0], &sig[1], &sig[2]);
memcpy(ret_sig, sig, sizeof(sig));
ret_sig[12] = 0; /* \0-terminate the string to make string comparison possible */
/* In some CI tests ret_sig doesn't contain valid UTF8 and prints garbage to the console */
log_debug("CPUID sig '%s'", strna(utf8_is_valid(ret_sig)));
return eax;
}
#define MSR_DEVICE "/dev/cpu/0/msr"
static uint64_t msr(uint64_t index) {
uint64_t ret;
ssize_t rv;
_cleanup_close_ int fd = -EBADF;
fd = open(MSR_DEVICE, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
log_debug_errno(errno,
"Cannot open MSR device %s (index %" PRIu64 "), ignoring: %m",
MSR_DEVICE,
index);
return 0;
}
rv = pread(fd, &ret, sizeof(ret), index);
if (rv < 0) {
log_debug_errno(errno,
"Cannot read MSR device %s (index %" PRIu64 "), ignoring: %m",
MSR_DEVICE,
index);
return 0;
} else if (rv != sizeof(ret)) {
log_debug("Short read %ld bytes from MSR device %s (index %" PRIu64 "), ignoring",
rv,
MSR_DEVICE,
index);
return 0;
}
log_debug("MSR %" PRIu64 " result %" PRIu64 "", index, ret);
return ret;
}
static bool detect_hyperv_sev(void) {
uint32_t eax, ebx, ecx, edx, feat;
char sig[13] = {};
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;
log_debug("CPUID is on hyperv");
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 ConfidentialVirtualization detect_sev(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 CONFIDENTIAL_VIRTUALIZATION_NONE;
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 trying some HyperV
* specific CPUID checks.
*/
if (!(eax & EAX_SEV)) {
log_debug("No sev in CPUID, trying hyperv CPUID");
if (detect_hyperv_sev())
return CONFIDENTIAL_VIRTUALIZATION_SEV_SNP;
log_debug("No hyperv CPUID");
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
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 & MSR_SEV_SNP)
return CONFIDENTIAL_VIRTUALIZATION_SEV_SNP;
if (msrval & MSR_SEV_ES)
return CONFIDENTIAL_VIRTUALIZATION_SEV_ES;
if (msrval & MSR_SEV)
return CONFIDENTIAL_VIRTUALIZATION_SEV;
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
static ConfidentialVirtualization detect_tdx(void) {
uint32_t eax, ebx, ecx, edx;
char sig[13] = {};
eax = CPUID_GET_HIGHEST_FUNCTION;
ebx = ecx = edx = 0;
cpuid(&eax, &ebx, &ecx, &edx);
if (eax < CPUID_INTEL_TDX_ENUMERATION)
return CONFIDENTIAL_VIRTUALIZATION_NONE;
cpuid_leaf(CPUID_INTEL_TDX_ENUMERATION, sig, true);
if (memcmp(sig, CPUID_SIG_INTEL_TDX, sizeof(sig)) == 0)
return CONFIDENTIAL_VIRTUALIZATION_TDX;
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
static bool detect_hypervisor(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;
log_debug("CPUID is hypervisor: %s", yes_no(is_hv));
return is_hv;
}
ConfidentialVirtualization detect_confidential_virtualization(void) {
static thread_local ConfidentialVirtualization cached_found = _CONFIDENTIAL_VIRTUALIZATION_INVALID;
char sig[13] = {};
ConfidentialVirtualization cv = CONFIDENTIAL_VIRTUALIZATION_NONE;
if (cached_found >= 0)
return cached_found;
/* Skip everything on bare metal */
if (detect_hypervisor()) {
cpuid_leaf(0, sig, true);
if (memcmp(sig, CPUID_SIG_AMD, sizeof(sig)) == 0)
cv = detect_sev();
else if (memcmp(sig, CPUID_SIG_INTEL, sizeof(sig)) == 0)
cv = detect_tdx();
}
cached_found = cv;
return cv;
}
#else /* ! x86_64 */
ConfidentialVirtualization detect_confidential_virtualization(void) {
log_debug("No confidential virtualization detection on this architecture");
return CONFIDENTIAL_VIRTUALIZATION_NONE;
}
#endif /* ! x86_64 */
static const char *const confidential_virtualization_table[_CONFIDENTIAL_VIRTUALIZATION_MAX] = {
[CONFIDENTIAL_VIRTUALIZATION_NONE] = "none",
[CONFIDENTIAL_VIRTUALIZATION_SEV] = "sev",
[CONFIDENTIAL_VIRTUALIZATION_SEV_ES] = "sev-es",
[CONFIDENTIAL_VIRTUALIZATION_SEV_SNP] = "sev-snp",
[CONFIDENTIAL_VIRTUALIZATION_TDX] = "tdx",
};
DEFINE_STRING_TABLE_LOOKUP(confidential_virtualization, ConfidentialVirtualization);

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include "errno-list.h"
#include "macro.h"
typedef enum ConfidentialVirtualization {
CONFIDENTIAL_VIRTUALIZATION_NONE = 0,
CONFIDENTIAL_VIRTUALIZATION_SEV,
CONFIDENTIAL_VIRTUALIZATION_SEV_ES,
CONFIDENTIAL_VIRTUALIZATION_SEV_SNP,
CONFIDENTIAL_VIRTUALIZATION_TDX,
_CONFIDENTIAL_VIRTUALIZATION_MAX,
_CONFIDENTIAL_VIRTUALIZATION_INVALID = -EINVAL,
_CONFIDENTIAL_VIRTUALIZATION_ERRNO_MAX = -ERRNO_MAX, /* ensure full range of errno fits into this enum */
} ConfidentialVirtualization;
ConfidentialVirtualization detect_confidential_virtualization(void);
const char *confidential_virtualization_to_string(ConfidentialVirtualization v) _const_;
ConfidentialVirtualization confidential_virtualization_from_string(const char *s) _pure_;

View file

@ -16,6 +16,7 @@ basic_sources = files(
'chase.c',
'chattr-util.c',
'conf-files.c',
'confidential-virt.c',
'devnum-util.c',
'dirent-util.c',
'efivars.c',

View file

@ -12,6 +12,7 @@
#include "bus-get-properties.h"
#include "bus-log-control-api.h"
#include "chase.h"
#include "confidential-virt.h"
#include "data-fd-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
@ -91,6 +92,27 @@ static int property_get_virtualization(
v == VIRTUALIZATION_NONE ? NULL : virtualization_to_string(v));
}
static int property_get_confidential_virtualization(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
ConfidentialVirtualization v;
assert(bus);
assert(reply);
v = detect_confidential_virtualization();
return sd_bus_message_append(
reply, "s",
v <= 0 ? NULL : confidential_virtualization_to_string(v));
}
static int property_get_tainted(
sd_bus *bus,
const char *path,
@ -2920,6 +2942,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConfidentialVirtualization", "s", property_get_confidential_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_FIRMWARE]), SD_BUS_VTABLE_PROPERTY_CONST),

View file

@ -34,6 +34,7 @@
#include "chase.h"
#include "clock-util.h"
#include "conf-parser.h"
#include "confidential-virt.h"
#include "cpu-set-util.h"
#include "crash-handler.h"
#include "dbus-manager.h"
@ -2120,6 +2121,10 @@ static void log_execution_mode(bool *ret_first_boot) {
if (v > 0)
log_info("Detected virtualization %s.", virtualization_to_string(v));
v = detect_confidential_virtualization();
if (v > 0)
log_info("Detected confidential virtualization %s.", confidential_virtualization_to_string(v));
log_info("Detected architecture %s.", architecture_to_string(uname_architecture()));
if (in_initrd())

View file

@ -32,6 +32,7 @@
#include "clean-ipc.h"
#include "clock-util.h"
#include "common-signal.h"
#include "confidential-virt.h"
#include "constants.h"
#include "core-varlink.h"
#include "creds-util.h"
@ -3887,6 +3888,7 @@ static int manager_run_environment_generators(Manager *m) {
static int build_generator_environment(Manager *m, char ***ret) {
_cleanup_strv_free_ char **nl = NULL;
Virtualization v;
ConfidentialVirtualization cv;
int r;
assert(m);
@ -3935,6 +3937,15 @@ static int build_generator_environment(Manager *m, char ***ret) {
return r;
}
cv = detect_confidential_virtualization();
if (cv < 0)
log_debug_errno(cv, "Failed to detect confidential virtualization, ignoring: %m");
else if (cv > 0) {
r = strv_env_assign(&nl, "SYSTEMD_CONFIDENTIAL_VIRTUALIZATION", confidential_virtualization_to_string(cv));
if (r < 0)
return r;
}
r = strv_env_assign(&nl, "SYSTEMD_ARCHITECTURE", architecture_to_string(uname_architecture()));
if (r < 0)
return r;

View file

@ -7,6 +7,7 @@
#include "alloc-util.h"
#include "build.h"
#include "confidential-virt.h"
#include "main-func.h"
#include "pretty-print.h"
#include "string-table.h"
@ -19,6 +20,7 @@ static enum {
ONLY_CONTAINER,
ONLY_CHROOT,
ONLY_PRIVATE_USERS,
ONLY_CVM,
} arg_mode = ANY_VIRTUALIZATION;
static int help(void) {
@ -37,8 +39,11 @@ static int help(void) {
" -v --vm Only detect whether we are run in a VM\n"
" -r --chroot Detect whether we are run in a chroot() environment\n"
" --private-users Only detect whether we are running in a user namespace\n"
" --cvm Only detect whether we are run in a confidential VM\n"
" -q --quiet Don't output anything, just set return value\n"
" --list List all known and detectable types of virtualization\n"
" --list-cvm List all known and detectable types of confidential \n"
" virtualization\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
link);
@ -52,6 +57,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_PRIVATE_USERS,
ARG_LIST,
ARG_CVM,
ARG_LIST_CVM,
};
static const struct option options[] = {
@ -62,7 +69,9 @@ static int parse_argv(int argc, char *argv[]) {
{ "chroot", no_argument, NULL, 'r' },
{ "private-users", no_argument, NULL, ARG_PRIVATE_USERS },
{ "quiet", no_argument, NULL, 'q' },
{ "cvm", no_argument, NULL, ARG_CVM },
{ "list", no_argument, NULL, ARG_LIST },
{ "list-cvm", no_argument, NULL, ARG_LIST_CVM },
{}
};
@ -105,6 +114,14 @@ static int parse_argv(int argc, char *argv[]) {
DUMP_STRING_TABLE(virtualization, Virtualization, _VIRTUALIZATION_MAX);
return 0;
case ARG_CVM:
arg_mode = ONLY_CVM;
return 1;
case ARG_LIST_CVM:
DUMP_STRING_TABLE(confidential_virtualization, ConfidentialVirtualization, _CONFIDENTIAL_VIRTUALIZATION_MAX);
return 0;
case '?':
return -EINVAL;
@ -122,6 +139,7 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
Virtualization v;
ConfidentialVirtualization c;
int r;
/* This is mostly intended to be used for scripts which want
@ -159,6 +177,14 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to check for user namespace: %m");
return !r;
case ONLY_CVM:
c = detect_confidential_virtualization();
if (c < 0)
return log_error_errno(c, "Failed to check for confidential virtualization: %m");
if (!arg_quiet)
puts(confidential_virtualization_to_string(c));
return c == CONFIDENTIAL_VIRTUALIZATION_NONE;
case ANY_VIRTUALIZATION:
default:
v = detect_virtualization();

View file

@ -24,6 +24,7 @@
#include "cgroup-util.h"
#include "compare-operator.h"
#include "condition.h"
#include "confidential-virt.h"
#include "cpu-set-util.h"
#include "creds-util.h"
#include "efi-api.h"
@ -689,6 +690,8 @@ static int condition_test_security(Condition *c, char **env) {
return is_efi_secure_boot();
if (streq(c->parameter, "tpm2"))
return has_tpm2();
if (streq(c->parameter, "cvm"))
return detect_confidential_virtualization() > 0;
return false;
}

View file

@ -14,6 +14,7 @@
#include "battery-util.h"
#include "cgroup-util.h"
#include "condition.h"
#include "confidential-virt.h"
#include "cpu-set-util.h"
#include "efi-loader.h"
#include "env-util.h"
@ -784,6 +785,12 @@ TEST(condition_test_security) {
assert_se(condition);
assert_se(condition_test(condition, environ) == is_efi_secure_boot());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "cvm", false, false);
assert_se(condition);
assert_se(condition_test(condition, environ) ==
(detect_confidential_virtualization() != CONFIDENTIAL_VIRTUALIZATION_NONE));
condition_free(condition);
}
TEST(print_securities) {
@ -795,6 +802,8 @@ TEST(print_securities) {
log_info("SMACK: %s", yes_no(mac_smack_use()));
log_info("Audit: %s", yes_no(use_audit()));
log_info("UEFI secure boot: %s", yes_no(is_efi_secure_boot()));
log_info("Confidential VM: %s", yes_no
(detect_confidential_virtualization() != CONFIDENTIAL_VIRTUALIZATION_NONE));
log_info("-------------------------------------------");
}

View file

@ -6,6 +6,7 @@
#include "cgroup-util.h"
#include "compress.h"
#include "condition.h"
#include "confidential-virt.h"
#include "device-private.h"
#include "device.h"
#include "discover-image.h"
@ -49,6 +50,7 @@ int main(int argc, char **argv) {
test_table(collect_mode, COLLECT_MODE);
test_table(condition_result, CONDITION_RESULT);
test_table(condition_type, CONDITION_TYPE);
test_table(confidential_virtualization, CONFIDENTIAL_VIRTUALIZATION);
test_table(device_action, SD_DEVICE_ACTION);
test_table(device_state, DEVICE_STATE);
test_table(dns_over_tls_mode, DNS_OVER_TLS_MODE);

View file

@ -6,6 +6,7 @@
#include "architecture.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "confidential-virt.h"
#include "constants.h"
#include "device-private.h"
#include "device-util.h"
@ -1920,6 +1921,8 @@ static int udev_rule_apply_token_to_event(
val = architecture_to_string(uname_architecture());
else if (streq(k, "virt"))
val = virtualization_to_string(detect_virtualization());
else if (streq(k, "cvm"))
val = confidential_virtualization_to_string(detect_confidential_virtualization());
else
assert_not_reached();
return token_match_string(token, val);