qga/commands-win32.c | 437 +++++++++++++++++++++++++++++++++++++++++++ qga/qapi-schema.json | 134 ++++++++++++- 2 files changed, 570 insertions(+), 1 deletion(-)
Extend guest-get-osinfo to include security features status
(VBS, Secure Boot, TPM) in a nested 'security' field.
OS-specific data (e.g. Windows DeviceGuard) is separated
using a union to allow future per-OS extensions.
TPM and Secure Boot information are represented as dedicated
structs (GuestSecurityTPMInfo and GuestSecuritySecureBootInfo).
The implementation queries Win32_DeviceGuard and Win32_Tpm via
WMI, and reads UEFI variables (SecureBoot, SetupMode, AuditMode,
DeployedMode) through GetFirmwareEnvironmentVariable().
Signed-off-by: Elizabeth Ashurov <eashurov@redhat.com>
---
qga/commands-win32.c | 437 +++++++++++++++++++++++++++++++++++++++++++
qga/qapi-schema.json | 134 ++++++++++++-
2 files changed, 570 insertions(+), 1 deletion(-)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index c0bf3467bd..0c8ab5af1b 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -28,6 +28,7 @@
#include <wtsapi32.h>
#include <wininet.h>
#include <pdh.h>
+#include <wbemidl.h>
#include "guest-agent-core.h"
#include "vss-win32.h"
@@ -2252,6 +2253,8 @@ static char *ga_get_current_arch(void)
return result;
}
+static void populate_security_info(GuestOSInfo *osinfo);
+
GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
{
Error *local_err = NULL;
@@ -2289,6 +2292,8 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
info->variant = g_strdup(server ? "server" : "client");
info->variant_id = g_strdup(server ? "server" : "client");
+ populate_security_info(info);
+
return info;
}
@@ -2764,3 +2769,435 @@ GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
g_hash_table_destroy(interface_metric_cache);
return head;
}
+
+/*
+ * WMI GUIDs
+ */
+static const GUID qga_CLSID_WbemLocator = {
+ 0x4590f811, 0x1d3a, 0x11d0,
+ {0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}
+};
+static const GUID qga_IID_IWbemLocator = {
+ 0xdc12a687, 0x737f, 0x11cf,
+ {0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}
+};
+
+static IWbemServices *wmi_connect_to_namespace(const wchar_t *namespace_path,
+ Error **errp)
+{
+ HRESULT hr;
+ IWbemLocator *locator = NULL;
+ IWbemServices *services = NULL;
+ BSTR bstr_ns = SysAllocString(namespace_path);
+
+ if (!bstr_ns) {
+ error_setg(errp, "failed to allocate WMI namespace string");
+ return NULL;
+ }
+
+ hr = CoCreateInstance(&qga_CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
+ &qga_IID_IWbemLocator, (LPVOID *)&locator);
+ if (FAILED(hr)) {
+ error_setg_win32(errp, hr, "failed to create IWbemLocator");
+ goto out;
+ }
+
+ hr = locator->lpVtbl->ConnectServer(locator, bstr_ns, NULL, NULL, NULL,
+ 0, NULL, NULL, &services);
+ if (FAILED(hr)) {
+ error_setg_win32(errp, hr, "failed to connect to WMI namespace");
+ goto out;
+ }
+
+ hr = CoSetProxyBlanket((IUnknown *)services,
+ RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_CALL,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ NULL, EOAC_NONE);
+ if (FAILED(hr)) {
+ error_setg_win32(errp, hr, "failed to set WMI proxy blanket");
+ services->lpVtbl->Release(services);
+ services = NULL;
+ }
+
+out:
+ SysFreeString(bstr_ns);
+ if (locator) {
+ locator->lpVtbl->Release(locator);
+ }
+ return services;
+}
+
+static IEnumWbemClassObject *wmi_exec_query(IWbemServices *services,
+ const wchar_t *query,
+ Error **errp)
+{
+ HRESULT hr;
+ IEnumWbemClassObject *enumerator = NULL;
+ BSTR bstr_wql = SysAllocString(L"WQL");
+ BSTR bstr_query = SysAllocString(query);
+
+ if (!bstr_wql || !bstr_query) {
+ error_setg(errp, "failed to allocate WMI query strings");
+ goto out;
+ }
+
+ hr = services->lpVtbl->ExecQuery(services, bstr_wql, bstr_query,
+ WBEM_FLAG_RETURN_IMMEDIATELY |
+ WBEM_FLAG_FORWARD_ONLY,
+ NULL, &enumerator);
+ if (FAILED(hr)) {
+ error_setg_win32(errp, hr, "WMI query failed");
+ }
+
+out:
+ SysFreeString(bstr_wql);
+ SysFreeString(bstr_query);
+ return enumerator;
+}
+
+static HRESULT wmi_get_property(IWbemClassObject *obj, const wchar_t *name,
+ VARIANT *var)
+{
+ return obj->lpVtbl->Get(obj, name, 0, var, NULL, NULL);
+}
+
+/* Read a WMI integer property (VT_I4 or VT_UI4). */
+static bool wmi_get_int_property(IWbemClassObject *obj,
+ const wchar_t *name,
+ int64_t *out)
+{
+ VARIANT var;
+ bool ret = false;
+
+ VariantInit(&var);
+ if (SUCCEEDED(wmi_get_property(obj, name, &var))) {
+ if (V_VT(&var) == VT_I4) {
+ *out = V_I4(&var);
+ ret = true;
+ } else if (V_VT(&var) == VT_UI4) {
+ *out = V_UI4(&var);
+ ret = true;
+ }
+ }
+ VariantClear(&var);
+ return ret;
+}
+
+/* Read an integer SAFEARRAY WMI property into a QAPI intList. */
+static bool wmi_safearray_to_int_list(IWbemClassObject *obj,
+ const wchar_t *prop_name,
+ intList **list)
+{
+ VARIANT var;
+ HRESULT hr;
+ LONG lb, ub, i;
+ uint32_t *data = NULL;
+
+ VariantInit(&var);
+ hr = wmi_get_property(obj, prop_name, &var);
+ if (FAILED(hr) || V_VT(&var) == VT_NULL) {
+ VariantClear(&var);
+ return false;
+ }
+
+ if (!(V_VT(&var) & VT_ARRAY)) {
+ VariantClear(&var);
+ return false;
+ }
+
+ SAFEARRAY *sa = V_ARRAY(&var);
+ if (FAILED(SafeArrayGetLBound(sa, 1, &lb)) ||
+ FAILED(SafeArrayGetUBound(sa, 1, &ub))) {
+ VariantClear(&var);
+ return false;
+ }
+
+ if (FAILED(SafeArrayAccessData(sa, (void **)&data))) {
+ VariantClear(&var);
+ return false;
+ }
+
+ intList **tail = list;
+ for (i = 0; i <= ub - lb; i++) {
+ QAPI_LIST_APPEND(tail, (int64_t)data[i]);
+ }
+
+ SafeArrayUnaccessData(sa);
+ VariantClear(&var);
+ return true;
+}
+
+/*
+ * Query Win32_DeviceGuard WMI class for VBS and related properties.
+ */
+static void get_device_guard_info(GuestSecurityInfoWindows *info,
+ Error **errp)
+{
+ Error *local_err = NULL;
+ IWbemServices *services = NULL;
+ IEnumWbemClassObject *enumerator = NULL;
+ IWbemClassObject *obj = NULL;
+ ULONG count = 0;
+ HRESULT hr;
+ int64_t val;
+
+ services = wmi_connect_to_namespace(
+ L"ROOT\\Microsoft\\Windows\\DeviceGuard", &local_err);
+ if (!services) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ enumerator = wmi_exec_query(services,
+ L"SELECT * FROM Win32_DeviceGuard", &local_err);
+ if (!enumerator) {
+ error_propagate(errp, local_err);
+ goto out;
+ }
+
+ hr = enumerator->lpVtbl->Next(enumerator, WBEM_INFINITE, 1,
+ &obj, &count);
+ if (FAILED(hr)) {
+ error_setg_win32(errp, hr, "failed to enumerate Win32_DeviceGuard");
+ goto out;
+ }
+ if (count == 0) {
+ error_setg(errp, "no Win32_DeviceGuard instance found");
+ goto out;
+ }
+
+ if (wmi_get_int_property(obj, L"VirtualizationBasedSecurityStatus",
+ &val)) {
+ info->has_vbs_status = true;
+ info->vbs_status = val;
+ }
+
+ if (wmi_get_int_property(obj, L"CodeIntegrityPolicyEnforcementStatus",
+ &val)) {
+ info->has_code_integrity_policy_enforcement_status = true;
+ info->code_integrity_policy_enforcement_status = val;
+ }
+
+ if (wmi_get_int_property(obj,
+ L"UsermodeCodeIntegrityPolicyEnforcementStatus",
+ &val)) {
+ info->has_usr_cfg_code_integrity_policy_enforcement_status = true;
+ info->usr_cfg_code_integrity_policy_enforcement_status = val;
+ }
+
+ if (wmi_safearray_to_int_list(obj, L"AvailableSecurityProperties",
+ &info->available_security_properties)) {
+ info->has_available_security_properties = true;
+ }
+
+ if (wmi_safearray_to_int_list(obj, L"RequiredSecurityProperties",
+ &info->required_security_properties)) {
+ info->has_required_security_properties = true;
+ }
+
+ if (wmi_safearray_to_int_list(obj, L"SecurityServicesConfigured",
+ &info->security_services_configured)) {
+ info->has_security_services_configured = true;
+ }
+
+ if (wmi_safearray_to_int_list(obj, L"SecurityServicesRunning",
+ &info->security_services_running)) {
+ info->has_security_services_running = true;
+ }
+
+ obj->lpVtbl->Release(obj);
+ obj = NULL;
+
+ /* Drain remaining results */
+ while (true) {
+ hr = enumerator->lpVtbl->Next(enumerator, WBEM_INFINITE, 1,
+ &obj, &count);
+ if (FAILED(hr) || count == 0) {
+ break;
+ }
+ obj->lpVtbl->Release(obj);
+ obj = NULL;
+ }
+
+out:
+ if (obj) {
+ obj->lpVtbl->Release(obj);
+ }
+ if (enumerator) {
+ enumerator->lpVtbl->Release(enumerator);
+ }
+ if (services) {
+ services->lpVtbl->Release(services);
+ }
+}
+
+#define EFI_GLOBAL_VARIABLE_GUID \
+ "{8be4df61-93ca-11d2-aa0d-00e098032b8c}"
+
+/*
+ * Read a single-byte UEFI variable. Returns true on success and
+ * stores the value in *out. Returns false on failure.
+ */
+static bool read_efi_var(const char *name, BYTE *out)
+{
+ DWORD ret = GetFirmwareEnvironmentVariableA(
+ name, EFI_GLOBAL_VARIABLE_GUID, out, sizeof(*out));
+ return ret != 0;
+}
+
+/*
+ * Read UEFI Secure Boot variables. Returns NULL on legacy BIOS
+ * systems or when the information is unavailable.
+ */
+static GuestSecuritySecureBootInfo *get_secure_boot_info(void)
+{
+ Error *local_err = NULL;
+ GuestSecuritySecureBootInfo *sb;
+ BYTE value = 0;
+
+ acquire_privilege(SE_SYSTEM_ENVIRONMENT_NAME, &local_err);
+ if (local_err) {
+ g_warning("SecureBoot privilege failed: %s",
+ error_get_pretty(local_err));
+ error_free(local_err);
+ return NULL;
+ }
+
+ if (!read_efi_var("SecureBoot", &value)) {
+ DWORD err = GetLastError();
+ if (err == ERROR_INVALID_FUNCTION) {
+ return NULL;
+ }
+ if (err == ERROR_ENVVAR_NOT_FOUND) {
+ sb = g_new0(GuestSecuritySecureBootInfo, 1);
+ sb->enabled = false;
+ return sb;
+ }
+ g_warning("failed to read SecureBoot UEFI variable: 0x%lx", err);
+ return NULL;
+ }
+
+ sb = g_new0(GuestSecuritySecureBootInfo, 1);
+ sb->enabled = (value == 1);
+
+ if (read_efi_var("SetupMode", &value)) {
+ sb->has_setup_mode = true;
+ sb->setup_mode = (value == 1);
+ }
+
+ if (read_efi_var("AuditMode", &value)) {
+ sb->has_audit_mode = true;
+ sb->audit_mode = (value == 1);
+ }
+
+ if (read_efi_var("DeployedMode", &value)) {
+ sb->has_deployed_mode = true;
+ sb->deployed_mode = (value == 1);
+ }
+
+ return sb;
+}
+
+/*
+ * Query Win32_Tpm WMI class for TPM presence and version.
+ * Returns a GuestSecurityTPMInfo on success, or NULL if no TPM
+ * is found or the namespace is unavailable.
+ */
+static GuestSecurityTPMInfo *get_tpm_info(void)
+{
+ Error *local_err = NULL;
+ IWbemServices *services = NULL;
+ IEnumWbemClassObject *enumerator = NULL;
+ IWbemClassObject *obj = NULL;
+ ULONG count = 0;
+ HRESULT hr;
+ VARIANT var;
+ GuestSecurityTPMInfo *tpm = NULL;
+
+ services = wmi_connect_to_namespace(
+ L"ROOT\\CIMV2\\Security\\MicrosoftTpm", &local_err);
+ if (!services) {
+ error_free(local_err);
+ return NULL;
+ }
+
+ enumerator = wmi_exec_query(services,
+ L"SELECT * FROM Win32_Tpm", &local_err);
+ if (!enumerator) {
+ error_free(local_err);
+ goto out;
+ }
+
+ hr = enumerator->lpVtbl->Next(enumerator, WBEM_INFINITE, 1,
+ &obj, &count);
+ if (FAILED(hr) || count == 0) {
+ goto out;
+ }
+
+ tpm = g_new0(GuestSecurityTPMInfo, 1);
+
+ /* SpecVersion is "major.minor, revision, errata" e.g. "2.0, 0, 1.59" */
+ VariantInit(&var);
+ if (SUCCEEDED(wmi_get_property(obj, L"SpecVersion", &var)) &&
+ V_VT(&var) == VT_BSTR && V_BSTR(&var)) {
+ g_autofree char *version = g_utf16_to_utf8(
+ (const gunichar2 *)V_BSTR(&var), -1, NULL, NULL, NULL);
+ if (version) {
+ char *dot = strchr(version, '.');
+ if (dot) {
+ *dot = '\0';
+ }
+ tpm->major_version = g_ascii_strtoll(version, NULL, 10);
+ }
+ }
+ VariantClear(&var);
+
+ obj->lpVtbl->Release(obj);
+ obj = NULL;
+
+ /* Drain remaining results */
+ while (true) {
+ hr = enumerator->lpVtbl->Next(enumerator, WBEM_INFINITE, 1,
+ &obj, &count);
+ if (FAILED(hr) || count == 0) {
+ break;
+ }
+ obj->lpVtbl->Release(obj);
+ obj = NULL;
+ }
+
+out:
+ if (obj) {
+ obj->lpVtbl->Release(obj);
+ }
+ if (enumerator) {
+ enumerator->lpVtbl->Release(enumerator);
+ }
+ if (services) {
+ services->lpVtbl->Release(services);
+ }
+ return tpm;
+}
+
+static void populate_security_info(GuestOSInfo *osinfo)
+{
+ Error *local_err = NULL;
+ GuestSecurityInfo *info = g_new0(GuestSecurityInfo, 1);
+
+ info->os = g_new0(GuestSecurityInfoOs, 1);
+ info->os->type = GUEST_SECURITY_INFO_TYPE_WINDOWS;
+
+ get_device_guard_info(&info->os->u.windows, &local_err);
+ if (local_err) {
+ g_warning("DeviceGuard query failed: %s",
+ error_get_pretty(local_err));
+ error_free(local_err);
+ local_err = NULL;
+ }
+
+ info->secure_boot = get_secure_boot_info();
+ info->tpm = get_tpm_info();
+
+ osinfo->security = info;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index c57bc9a02f..6f4b61355b 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1490,6 +1490,10 @@
# * POSIX: as defined by os-release(5)
# * Windows: contains string "server" or "client"
#
+# @security: Security features status. Present if any security
+# information (TPM, Secure Boot, etc.) could be retrieved.
+# Currently populated on Windows guests only (since 11.1)
+#
# .. note:: On POSIX systems the fields @id, @name, @pretty-name,
# @version, @version-id, @variant and @variant-id follow the
# definition specified in os-release(5). Refer to the manual page
@@ -1508,7 +1512,8 @@
'*kernel-release': 'str', '*kernel-version': 'str',
'*machine': 'str', '*id': 'str', '*name': 'str',
'*pretty-name': 'str', '*version': 'str', '*version-id': 'str',
- '*variant': 'str', '*variant-id': 'str' } }
+ '*variant': 'str', '*variant-id': 'str',
+ '*security': 'GuestSecurityInfo' } }
##
# @guest-get-osinfo:
@@ -1952,3 +1957,130 @@
'returns': ['GuestNetworkRoute'],
'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32'] }
}
+
+##
+# @GuestSecurityInfoWindows:
+#
+# Windows-specific security features from the Win32_DeviceGuard
+# WMI class. All values are raw integers as provided by the
+# Windows API. See
+# https://learn.microsoft.com/en-us/windows/security/hardware-security/enable-virtualization-based-protection-of-code-integrity
+# for the meaning of each value.
+#
+# @vbs-status: Whether VBS is enabled and running.
+#
+# @available-security-properties: Relevant security properties
+# available for VBS and memory integrity.
+#
+# @code-integrity-policy-enforcement-status: Code integrity
+# policy enforcement status.
+#
+# @required-security-properties: Required security properties
+# to enable VBS.
+#
+# @security-services-configured: Whether Credential Guard or
+# memory integrity is configured.
+#
+# @security-services-running: Whether Credential Guard or
+# memory integrity is running.
+#
+# @usr-cfg-code-integrity-policy-enforcement-status: User-mode
+# code integrity policy enforcement status.
+#
+# Since: 11.1
+##
+{ 'struct': 'GuestSecurityInfoWindows',
+ 'data': {
+ '*vbs-status': 'int',
+ '*available-security-properties': ['int'],
+ '*code-integrity-policy-enforcement-status': 'int',
+ '*required-security-properties': ['int'],
+ '*security-services-configured': ['int'],
+ '*security-services-running': ['int'],
+ '*usr-cfg-code-integrity-policy-enforcement-status': 'int' } }
+
+##
+# @GuestSecurityInfoType:
+#
+# Guest operating system type for security info.
+#
+# @windows: Microsoft Windows
+#
+# Since: 11.1
+##
+{ 'enum': 'GuestSecurityInfoType',
+ 'data': ['windows'] }
+
+##
+# @GuestSecurityInfoOs:
+#
+# OS-specific security information.
+#
+# @type: guest operating system type
+#
+# Since: 11.1
+##
+{ 'union': 'GuestSecurityInfoOs',
+ 'base': { 'type': 'GuestSecurityInfoType' },
+ 'discriminator': 'type',
+ 'data': {
+ 'windows': 'GuestSecurityInfoWindows' } }
+
+##
+# @GuestSecurityTPMInfo:
+#
+# TPM device information. The presence of this struct indicates
+# that a TPM device exists on the guest.
+#
+# @major-version: TPM specification major version (e.g. 1 or 2)
+#
+# Since: 11.1
+##
+{ 'struct': 'GuestSecurityTPMInfo',
+ 'data': {
+ 'major-version': 'int' } }
+
+##
+# @GuestSecuritySecureBootInfo:
+#
+# UEFI Secure Boot information. The presence of this struct
+# indicates that the guest supports UEFI Secure Boot.
+#
+# @enabled: Whether Secure Boot is currently enabled
+#
+# @audit-mode: Whether Secure Boot is in audit mode
+#
+# @deployed-mode: Whether Secure Boot is in deployed mode
+#
+# @setup-mode: Whether Secure Boot is in setup mode
+#
+# Since: 11.1
+##
+{ 'struct': 'GuestSecuritySecureBootInfo',
+ 'data': {
+ 'enabled': 'bool',
+ '*audit-mode': 'bool',
+ '*deployed-mode': 'bool',
+ '*setup-mode': 'bool' } }
+
+##
+# @GuestSecurityInfo:
+#
+# Guest security features status. Fields are optional; a missing
+# field means the information is not available on this guest OS.
+#
+# @tpm: TPM device information. Absent if no TPM is present
+# or the information is unavailable.
+#
+# @secure-boot: UEFI Secure Boot information. Absent on
+# legacy BIOS systems or if unavailable.
+#
+# @os: OS-specific security information
+#
+# Since: 11.1
+##
+{ 'struct': 'GuestSecurityInfo',
+ 'data': {
+ '*tpm': 'GuestSecurityTPMInfo',
+ '*secure-boot': 'GuestSecuritySecureBootInfo',
+ '*os': 'GuestSecurityInfoOs' } }
--
2.51.0
Elizabeth Ashurov <eashurov@redhat.com> writes:
> Extend guest-get-osinfo to include security features status
> (VBS, Secure Boot, TPM) in a nested 'security' field.
> OS-specific data (e.g. Windows DeviceGuard) is separated
> using a union to allow future per-OS extensions.
>
> TPM and Secure Boot information are represented as dedicated
> structs (GuestSecurityTPMInfo and GuestSecuritySecureBootInfo).
>
> The implementation queries Win32_DeviceGuard and Win32_Tpm via
> WMI, and reads UEFI variables (SecureBoot, SetupMode, AuditMode,
> DeployedMode) through GetFirmwareEnvironmentVariable().
>
> Signed-off-by: Elizabeth Ashurov <eashurov@redhat.com>
[...]
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index c57bc9a02f..6f4b61355b 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -1490,6 +1490,10 @@
> # * POSIX: as defined by os-release(5)
> # * Windows: contains string "server" or "client"
> #
> +# @security: Security features status. Present if any security
> +# information (TPM, Secure Boot, etc.) could be retrieved.
> +# Currently populated on Windows guests only (since 11.1)
> +#
> # .. note:: On POSIX systems the fields @id, @name, @pretty-name,
> # @version, @version-id, @variant and @variant-id follow the
> # definition specified in os-release(5). Refer to the manual page
> @@ -1508,7 +1512,8 @@
> '*kernel-release': 'str', '*kernel-version': 'str',
> '*machine': 'str', '*id': 'str', '*name': 'str',
> '*pretty-name': 'str', '*version': 'str', '*version-id': 'str',
> - '*variant': 'str', '*variant-id': 'str' } }
> + '*variant': 'str', '*variant-id': 'str',
> + '*security': 'GuestSecurityInfo' } }
>
> ##
> # @guest-get-osinfo:
> @@ -1952,3 +1957,130 @@
> 'returns': ['GuestNetworkRoute'],
> 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32'] }
> }
> +
> +##
> +# @GuestSecurityInfoWindows:
> +#
> +# Windows-specific security features from the Win32_DeviceGuard
> +# WMI class. All values are raw integers as provided by the
> +# Windows API. See
> +# https://learn.microsoft.com/en-us/windows/security/hardware-security/enable-virtualization-based-protection-of-code-integrity
> +# for the meaning of each value.
> +#
> +# @vbs-status: Whether VBS is enabled and running.
> +#
> +# @available-security-properties: Relevant security properties
> +# available for VBS and memory integrity.
> +#
> +# @code-integrity-policy-enforcement-status: Code integrity
> +# policy enforcement status.
> +#
> +# @required-security-properties: Required security properties
> +# to enable VBS.
What about "Security properties required to enable VBS"?
> +#
> +# @security-services-configured: Whether Credential Guard or
> +# memory integrity is configured.
> +#
> +# @security-services-running: Whether Credential Guard or
> +# memory integrity is running.
> +#
> +# @usr-cfg-code-integrity-policy-enforcement-status: User-mode
> +# code integrity policy enforcement status.
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'GuestSecurityInfoWindows',
> + 'data': {
> + '*vbs-status': 'int',
> + '*available-security-properties': ['int'],
> + '*code-integrity-policy-enforcement-status': 'int',
> + '*required-security-properties': ['int'],
> + '*security-services-configured': ['int'],
> + '*security-services-running': ['int'],
> + '*usr-cfg-code-integrity-policy-enforcement-status': 'int' } }
> +
> +##
> +# @GuestSecurityInfoType:
> +#
> +# Guest operating system type for security info.
> +#
> +# @windows: Microsoft Windows
> +#
> +# Since: 11.1
> +##
> +{ 'enum': 'GuestSecurityInfoType',
> + 'data': ['windows'] }
> +
> +##
> +# @GuestSecurityInfoOs:
> +#
> +# OS-specific security information.
> +#
> +# @type: guest operating system type
> +#
> +# Since: 11.1
> +##
> +{ 'union': 'GuestSecurityInfoOs',
> + 'base': { 'type': 'GuestSecurityInfoType' },
> + 'discriminator': 'type',
> + 'data': {
> + 'windows': 'GuestSecurityInfoWindows' } }
> +
> +##
> +# @GuestSecurityTPMInfo:
> +#
> +# TPM device information. The presence of this struct indicates
> +# that a TPM device exists on the guest.
> +#
> +# @major-version: TPM specification major version (e.g. 1 or 2)
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'GuestSecurityTPMInfo',
> + 'data': {
> + 'major-version': 'int' } }
> +
> +##
> +# @GuestSecuritySecureBootInfo:
> +#
> +# UEFI Secure Boot information. The presence of this struct
> +# indicates that the guest supports UEFI Secure Boot.
> +#
> +# @enabled: Whether Secure Boot is currently enabled
> +#
> +# @audit-mode: Whether Secure Boot is in audit mode
> +#
> +# @deployed-mode: Whether Secure Boot is in deployed mode
> +#
> +# @setup-mode: Whether Secure Boot is in setup mode
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'GuestSecuritySecureBootInfo',
> + 'data': {
> + 'enabled': 'bool',
> + '*audit-mode': 'bool',
> + '*deployed-mode': 'bool',
> + '*setup-mode': 'bool' } }
> +
> +##
> +# @GuestSecurityInfo:
> +#
> +# Guest security features status. Fields are optional; a missing
> +# field means the information is not available on this guest OS.
> +#
> +# @tpm: TPM device information. Absent if no TPM is present
> +# or the information is unavailable.
> +#
> +# @secure-boot: UEFI Secure Boot information. Absent on
> +# legacy BIOS systems or if unavailable.
> +#
> +# @os: OS-specific security information
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'GuestSecurityInfo',
> + 'data': {
> + '*tpm': 'GuestSecurityTPMInfo',
> + '*secure-boot': 'GuestSecuritySecureBootInfo',
> + '*os': 'GuestSecurityInfoOs' } }
No real issues, just a doc phrasing suggestion. Thus, QAPI schema
Acked-by: Markus Armbruster <armbru@redhat.com>
© 2016 - 2026 Red Hat, Inc.