From efa2cdb699df3e5d5d7180e50f3ebfff74788c5c Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 7 Jan 2020 11:49:39 +0900
Subject: [PATCH] virt: use string table to detect VM or container

(cherry picked from commit 735ea55f5cd87a82757a8911edd80fba799b46ee)

Related: #2117948
---
 src/basic/virt.c | 73 ++++++++++++++++++++++--------------------------
 1 file changed, 33 insertions(+), 40 deletions(-)

diff --git a/src/basic/virt.c b/src/basic/virt.c
index 78c68d66e0..6e4c702051 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -22,27 +22,26 @@
 #include "string-util.h"
 #include "virt.h"
 
+static const char *const vm_table[_VIRTUALIZATION_MAX] = {
+        [VIRTUALIZATION_XEN]       = "XenVMMXenVMM",
+        [VIRTUALIZATION_KVM]       = "KVMKVMKVM",
+        [VIRTUALIZATION_QEMU]      = "TCGTCGTCGTCG",
+        /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+        [VIRTUALIZATION_VMWARE]    = "VMwareVMware",
+        /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
+        [VIRTUALIZATION_MICROSOFT] = "Microsoft Hv",
+        /* https://wiki.freebsd.org/bhyve */
+        [VIRTUALIZATION_BHYVE]     = "bhyve bhyve ",
+        [VIRTUALIZATION_QNX]       = "QNXQVMBSQG",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(vm, int);
+
 static int detect_vm_cpuid(void) {
 
         /* CPUID is an x86 specific interface. */
 #if defined(__i386__) || defined(__x86_64__)
 
-        static const struct {
-                const char *cpuid;
-                int id;
-        } cpuid_vendor_table[] = {
-                { "XenVMMXenVMM", VIRTUALIZATION_XEN       },
-                { "KVMKVMKVM",    VIRTUALIZATION_KVM       },
-                { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU      },
-                /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
-                { "VMwareVMware", VIRTUALIZATION_VMWARE    },
-                /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
-                { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
-                /* https://wiki.freebsd.org/bhyve */
-                { "bhyve bhyve ", VIRTUALIZATION_BHYVE     },
-                { "QNXQVMBSQG",   VIRTUALIZATION_QNX       },
-        };
-
         uint32_t eax, ebx, ecx, edx;
         bool hypervisor;
 
@@ -59,7 +58,7 @@ static int detect_vm_cpuid(void) {
                         uint32_t sig32[3];
                         char text[13];
                 } sig = {};
-                unsigned j;
+                int v;
 
                 /* There is a hypervisor, see what it is */
                 __cpuid(0x40000000U, eax, ebx, ecx, edx);
@@ -70,11 +69,11 @@ static int detect_vm_cpuid(void) {
 
                 log_debug("Virtualization found, CPUID=%s", sig.text);
 
-                for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
-                        if (streq(sig.text, cpuid_vendor_table[j].cpuid))
-                                return cpuid_vendor_table[j].id;
+                v = vm_from_string(sig.text);
+                if (v < 0)
+                        return VIRTUALIZATION_VM_OTHER;
 
-                return VIRTUALIZATION_VM_OTHER;
+                return v;
         }
 #endif
         log_debug("No virtualization found in CPUID");
@@ -434,22 +433,20 @@ finish:
         return r;
 }
 
-int detect_container(void) {
-        static const struct {
-                const char *value;
-                int id;
-        } value_table[] = {
-                { "lxc",            VIRTUALIZATION_LXC            },
-                { "lxc-libvirt",    VIRTUALIZATION_LXC_LIBVIRT    },
-                { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
-                { "docker",         VIRTUALIZATION_DOCKER         },
-                { "rkt",            VIRTUALIZATION_RKT            },
-        };
+static const char *const container_table[_VIRTUALIZATION_MAX] = {
+        [VIRTUALIZATION_LXC]            = "lxc",
+        [VIRTUALIZATION_LXC_LIBVIRT]    = "lxc-libvirt",
+        [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
+        [VIRTUALIZATION_DOCKER]         = "docker",
+        [VIRTUALIZATION_RKT]            = "rkt",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
 
+int detect_container(void) {
         static thread_local int cached_found = _VIRTUALIZATION_INVALID;
         _cleanup_free_ char *m = NULL;
         const char *e = NULL;
-        unsigned j;
         int r;
 
         if (cached_found >= 0)
@@ -522,13 +519,9 @@ int detect_container(void) {
         goto finish;
 
 translate_name:
-        for (j = 0; j < ELEMENTSOF(value_table); j++)
-                if (streq(e, value_table[j].value)) {
-                        r = value_table[j].id;
-                        goto finish;
-                }
-
-        r = VIRTUALIZATION_CONTAINER_OTHER;
+        r = container_from_string(e);
+        if (r < 0)
+                r = VIRTUALIZATION_CONTAINER_OTHER;
 
 finish:
         log_debug("Found container virtualization %s.", virtualization_to_string(r));
