1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

virt: Fix Xen PV detection when nested inside another hypervisor

Currently, when Xen PV domains are nested within a hypervisor which is
detected through CPUID (such as VMware), the detected hypervisor might
not be Xen, because we don't check for Xen until after the CPUID check.

This change moves the Xen check before CPUID checks to fix the issue,
and moves Dom0 checking to detect_vm_xen so that we keep ignoring Xen
when we are in Dom0.
This commit is contained in:
Bogdan Seniuc 2021-10-09 15:00:36 +03:00 committed by Lennart Poettering
parent a6089431d5
commit 599be274c1

View File

@ -276,19 +276,6 @@ static int detect_vm_dmi(void) {
#endif
}
static int detect_vm_xen(void) {
/* Check for Dom0 will be executed later in detect_vm_xen_dom0
The presence of /proc/xen indicates some form of a Xen domain */
if (access("/proc/xen", F_OK) < 0) {
log_debug("Virtualization XEN not found, /proc/xen does not exist");
return VIRTUALIZATION_NONE;
}
log_debug("Virtualization XEN found (/proc/xen exists)");
return VIRTUALIZATION_XEN;
}
#define XENFEAT_dom0 11 /* xen/include/public/features.h */
#define PATH_FEATURES "/sys/hypervisor/properties/features"
/* Returns -errno, or 0 for domU, or 1 for dom0 */
@ -342,6 +329,26 @@ static int detect_vm_xen_dom0(void) {
}
}
static int detect_vm_xen(void) {
int r;
/* The presence of /proc/xen indicates some form of a Xen domain */
if (access("/proc/xen", F_OK) < 0) {
log_debug("Virtualization XEN not found, /proc/xen does not exist");
return VIRTUALIZATION_NONE;
}
log_debug("Virtualization XEN found (/proc/xen exists)");
/* Ignore the Xen hypervisor if we are in Dom0 */
r = detect_vm_xen_dom0();
if (r < 0)
return r;
if (r > 0)
return VIRTUALIZATION_NONE;
return VIRTUALIZATION_XEN;
}
static int detect_vm_hypervisor(void) {
_cleanup_free_ char *hvtype = NULL;
int r;
@ -435,7 +442,8 @@ int detect_vm(void) {
*
* First, try to detect Oracle Virtualbox and Amazon EC2 Nitro, even if they use KVM, as well as Xen even if
* it cloaks as Microsoft Hyper-V. Attempt to detect uml at this stage also since it runs as a user-process
* nested inside other VMs.
* nested inside other VMs. Also check for Xen now, because Xen PV mode does not override CPUID when nested
* inside another hypervisor.
*
* Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is
* overwritten.
@ -457,6 +465,15 @@ int detect_vm(void) {
else if (r != VIRTUALIZATION_NONE)
goto finish;
/* Detect Xen */
r = detect_vm_xen();
if (r < 0)
return r;
if (r == VIRTUALIZATION_VM_OTHER)
other = true;
else if (r != VIRTUALIZATION_NONE)
goto finish;
/* Detect from CPUID */
r = detect_vm_cpuid();
if (r < 0)
@ -476,20 +493,7 @@ int detect_vm(void) {
goto finish;
}
/* x86 xen will most likely be detected by cpuid. If not (most likely
* because we're not an x86 guest), then we should try the /proc/xen
* directory next. If that's not found, then we check for the high-level
* hypervisor sysfs file.
*/
r = detect_vm_xen();
if (r < 0)
return r;
if (r == VIRTUALIZATION_VM_OTHER)
other = true;
else if (r != VIRTUALIZATION_NONE)
goto finish;
/* Check high-level hypervisor sysfs file */
r = detect_vm_hypervisor();
if (r < 0)
return r;
@ -511,18 +515,7 @@ int detect_vm(void) {
return r;
finish:
/* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
* In order to detect the Dom0 as not virtualization we need to
* double-check it */
if (r == VIRTUALIZATION_XEN) {
int dom0;
dom0 = detect_vm_xen_dom0();
if (dom0 < 0)
return dom0;
if (dom0 > 0)
r = VIRTUALIZATION_NONE;
} else if (r == VIRTUALIZATION_NONE && other)
if (r == VIRTUALIZATION_NONE && other)
r = VIRTUALIZATION_VM_OTHER;
cached_found = r;