]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
virt: Improve detection of EC2 metal instances
authorBenjamin Herrenschmidt <benh@amazon.com>
Fri, 3 Sep 2021 01:36:46 +0000 (11:36 +1000)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 13 Sep 2021 16:44:20 +0000 (01:44 +0900)
The current detection code relies on /sys/firmware/dmi/entries/0-0/raw
to disambiguate Amazon EC2 virtualized from metal instances.

Unfortunately this file is root only. Thus on a c6g.metal instance
(aarch64), we observe something like this:

$ systemd-detect-virt
amazon
$ sudo systemd-detect-virt
none

Only the latter is correct.

The right long term fix is to extend the kernel to expose the SMBIOS BIOS
Characteristics properly via /sys/class/dmi, but until this happens (and
for backwards compatibility when it does), we need a plan B.

This change implements such a workaround by falling back to using the
instance type from DMI and looking at the ".metal" string present on
metal instances.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
src/basic/virt.c

index 7e88f09b485885ffe457fb842ed235c729a44ce3..c9c4416ef78c8759eb85a8cb120ac9a8a6737b5e 100644 (file)
@@ -235,8 +235,36 @@ static int detect_vm_dmi(void) {
 
         /* The DMI vendor tables in /sys/class/dmi/id don't help us distinguish between Amazon EC2
          * virtual machines and bare-metal instances, so we need to look at SMBIOS. */
-        if (r == VIRTUALIZATION_AMAZON && detect_vm_smbios() == SMBIOS_VM_BIT_UNSET)
-                return VIRTUALIZATION_NONE;
+        if (r == VIRTUALIZATION_AMAZON) {
+                switch (detect_vm_smbios()) {
+                case SMBIOS_VM_BIT_SET:
+                        return VIRTUALIZATION_AMAZON;
+                case SMBIOS_VM_BIT_UNSET:
+                        return VIRTUALIZATION_NONE;
+                case SMBIOS_VM_BIT_UNKNOWN: {
+                        /* The DMI information we are after is only accessible to the root user,
+                         * so we fallback to using the product name which is less restricted
+                         * to distinguish metal systems from virtualized instances */
+                        _cleanup_free_ char *s = NULL;
+
+                        r = read_full_virtual_file("/sys/class/dmi/id/product_name", &s, NULL);
+                        /* In EC2, virtualized is much more common than metal, so if for some reason
+                         * we fail to read the DMI data, assume we are virtualized. */
+                        if (r < 0) {
+                                log_debug_errno(r, "Can't read /sys/class/dmi/id/product_name,"
+                                                " assuming virtualized: %m");
+                                return VIRTUALIZATION_AMAZON;
+                        }
+                        if (endswith(truncate_nl(s), ".metal")) {
+                                log_debug("DMI product name ends with '.metal', assuming no virtualization");
+                                return VIRTUALIZATION_NONE;
+                        } else
+                                return VIRTUALIZATION_AMAZON;
+                }
+                default:
+                        assert_not_reached();
+              }
+        }
 
         /* If we haven't identified a VM, but the firmware indicates that there is one, indicate as much. We
          * have no further information about what it is. */