]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
virt: Fix Xen Dom0 detection logic to no longer report as VM
authorRichard Neill <richard.neill@arm.com>
Wed, 2 Feb 2022 18:18:46 +0000 (18:18 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 16 Feb 2022 17:05:28 +0000 (18:05 +0100)
Fixes regression introduced in 599be274c13c503806c85073d7beb1a155ac27bd

Moving the Xen check before the CPUID check, in order to handle the case where
a Xen domain is nested within a hypervisor which can be detected by via the
CPUID check, had an unintended consequence of causing Dom0 to report as a Xen
VM when it is not nested.

This patch stops further checks once it has been determined that Dom0 is not
nested within another hypervisor, meaning that the non-nested case matches its
previous logic (where it does not report as a VM).

Also, tidy the conditionals for the Xen and UML checks by removing handling of
a VIRTUALIZATION_VM_OTHER result, which has no code path.

Fixes #22511

src/basic/virt.c

index 156a19ee529add69bb91db7d0bbf62e6990cc0fd..284ad952778a9906dff7264ed8f394aa7c821905 100644 (file)
@@ -331,22 +331,13 @@ 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 */
+        /* The presence of /proc/xen indicates some form of a Xen domain
+           The check for Dom0 is handled outside this function */
         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;
 }
 
@@ -434,7 +425,7 @@ static int detect_vm_zvm(void) {
 int detect_vm(void) {
         static thread_local int cached_found = _VIRTUALIZATION_INVALID;
         bool other = false;
-        int r, dmi;
+        int r, dmi, xen_dom0 = 0;
 
         if (cached_found >= 0)
                 return cached_found;
@@ -461,19 +452,26 @@ int detect_vm(void) {
         r = detect_vm_uml();
         if (r < 0)
                 return r;
-        if (r == VIRTUALIZATION_VM_OTHER)
-                other = true;
-        else if (r != VIRTUALIZATION_NONE)
+        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;
+        if (r == VIRTUALIZATION_XEN) {
+                 /* If we are Dom0, then we expect to not report as a VM. However, as we might be nested
+                  * inside another hypervisor which can be detected via the CPUID check, wait to report this
+                  * until after the CPUID check. */
+                xen_dom0 = detect_vm_xen_dom0();
+                if (xen_dom0 < 0)
+                        return xen_dom0;
+                if (xen_dom0 == 0)
+                        goto finish;
+
+                r = VIRTUALIZATION_NONE;
+        } else if (r != VIRTUALIZATION_NONE)
+                assert_not_reached();
 
         /* Detect from CPUID */
         r = detect_vm_cpuid();
@@ -484,6 +482,10 @@ int detect_vm(void) {
         else if (r != VIRTUALIZATION_NONE)
                 goto finish;
 
+        /* If we are in Dom0 and have not yet finished, finish with the result of detect_vm_cpuid */
+        if (xen_dom0 > 0)
+                goto finish;
+
         /* Now, let's get back to DMI */
         if (dmi < 0)
                 return dmi;