mirror of
https://github.com/systemd/systemd
synced 2024-10-06 16:21:34 +00:00
Merge pull request #28242 from berrange/cond-sec-cvm
Detect and expose the confidential virtualization technology in various places
This commit is contained in:
commit
f00022eb86
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
293
src/basic/confidential-virt.c
Normal file
293
src/basic/confidential-virt.c
Normal 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 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 UINT32_C(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 UINT32_C(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 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);
|
25
src/basic/confidential-virt.h
Normal file
25
src/basic/confidential-virt.h
Normal 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_;
|
|
@ -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',
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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("-------------------------------------------");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue