X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fvirt.c;h=1299a75ed54d242ef9b93964b7a24dfe302fff9c;hp=4e18638bc9e421ce842b8bbc2322bc7b1d5d81c3;hb=8eb444001b790b0c16369ceb1420afde4c1e5b24;hpb=bdb628eec6f5d5111251bd1a4d68516cef33d7d0 diff --git a/src/shared/virt.c b/src/shared/virt.c index 4e18638bc..1299a75ed 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -24,6 +24,7 @@ #include #include "util.h" +#include "process-util.h" #include "virt.h" #include "fileio.h" @@ -101,6 +102,42 @@ static int detect_vm_cpuid(const char **_id) { return 0; } +static int detect_vm_devicetree(const char **_id) { +#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) + _cleanup_free_ char *hvtype = NULL; + int r; + + r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype); + if (r >= 0) { + if (streq(hvtype, "linux,kvm")) { + *_id = "kvm"; + return 1; + } else if (strstr(hvtype, "xen")) { + *_id = "xen"; + return 1; + } + } else if (r == -ENOENT) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + + dir = opendir("/proc/device-tree"); + if (!dir) { + if (errno == ENOENT) + return 0; + return -errno; + } + + FOREACH_DIRENT(dent, dir, return -errno) { + if (strstr(dent->d_name, "fw-cfg")) { + *_id = "qemu"; + return 1; + } + } + } +#endif + return 0; +} + static int detect_vm_dmi(const char **_id) { /* Both CPUID and DMI are x86 specific interfaces... */ @@ -117,7 +154,6 @@ static int detect_vm_dmi(const char **_id) { /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ "VMware\0" "vmware\0" "VMW\0" "vmware\0" - "Microsoft Corporation\0" "microsoft\0" "innotek GmbH\0" "oracle\0" "Xen\0" "xen\0" "Bochs\0" "bochs\0"; @@ -149,9 +185,9 @@ static int detect_vm_dmi(const char **_id) { /* Returns a short identifier for the various VM implementations */ int detect_vm(const char **id) { - _cleanup_free_ char *hvtype = NULL, *cpuinfo_contents = NULL; - static __thread int cached_found = -1; - static __thread const char *cached_id = NULL; + _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL; + static thread_local int cached_found = -1; + static thread_local const char *cached_id = NULL; const char *_id = NULL; int r; @@ -163,17 +199,37 @@ int detect_vm(const char **id) { return cached_found; } - /* Try high-level hypervisor sysfs file first: + /* Try xen capabilities file first, if not found try high-level hypervisor sysfs file: * - * https://bugs.freedesktop.org/show_bug.cgi?id=61491 */ - r = read_one_line_file("/sys/hypervisor/type", &hvtype); + * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */ + r = read_one_line_file("/proc/xen/capabilities", &domcap); if (r >= 0) { - if (streq(hvtype, "xen")) { + char *cap, *i = domcap; + + while ((cap = strsep(&i, ","))) + if (streq(cap, "control_d")) + break; + + if (!cap) { _id = "xen"; r = 1; - goto finish; } - } else if (r != -ENOENT) + + goto finish; + + } else if (r == -ENOENT) { + _cleanup_free_ char *hvtype = NULL; + + r = read_one_line_file("/sys/hypervisor/type", &hvtype); + if (r >= 0) { + if (streq(hvtype, "xen")) { + _id = "xen"; + r = 1; + goto finish; + } + } else if (r != -ENOENT) + return r; + } else return r; /* this will set _id to "other" and return 0 for unknown hypervisors */ @@ -185,6 +241,10 @@ int detect_vm(const char **id) { if (r != 0) goto finish; + r = detect_vm_devicetree(&_id); + if (r != 0) + goto finish; + if (_id) { /* "other" */ r = 1; @@ -201,6 +261,23 @@ int detect_vm(const char **id) { goto finish; } +#if defined(__s390__) + { + _cleanup_free_ char *t = NULL; + + r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t); + if (r >= 0) { + if (streq(t, "z/VM")) + _id = "zvm"; + else + _id = "kvm"; + r = 1; + + goto finish; + } + } +#endif + r = 0; finish: @@ -215,11 +292,11 @@ finish: int detect_container(const char **id) { - static __thread int cached_found = -1; - static __thread const char *cached_id = NULL; + static thread_local int cached_found = -1; + static thread_local const char *cached_id = NULL; - _cleanup_free_ char *e = NULL; - const char *_id = NULL; + _cleanup_free_ char *m = NULL; + const char *_id = NULL, *e = NULL; int r; if (_likely_(cached_found >= 0)) { @@ -230,17 +307,6 @@ int detect_container(const char **id) { return cached_found; } - /* Unfortunately many of these operations require root access - * in one way or another */ - - r = running_in_chroot(); - if (r < 0) - return r; - if (r > 0) { - _id = "chroot"; - goto finish; - } - /* /proc/vz exists in container and outside of the container, * /proc/bc only outside of the container. */ if (access("/proc/vz", F_OK) >= 0 && @@ -250,11 +316,50 @@ int detect_container(const char **id) { goto finish; } - r = getenv_for_pid(1, "container", &e); - if (r < 0) - return r; - if (r == 0) - goto finish; + if (getpid() == 1) { + /* If we are PID 1 we can just check our own + * environment variable */ + + e = getenv("container"); + if (isempty(e)) { + r = 0; + goto finish; + } + } else { + + /* Otherwise, PID 1 dropped this information into a + * file in /run. This is better than accessing + * /proc/1/environ, since we don't need CAP_SYS_PTRACE + * for that. */ + + r = read_one_line_file("/run/systemd/container", &m); + if (r == -ENOENT) { + + /* Fallback for cases where PID 1 was not + * systemd (for example, cases where + * init=/bin/sh is used. */ + + r = getenv_for_pid(1, "container", &m); + if (r <= 0) { + + /* If that didn't work, give up, + * assume no container manager. + * + * Note: This means we still cannot + * detect containers if init=/bin/sh + * is passed but privileges dropped, + * as /proc/1/environ is only readable + * with privileges. */ + + r = 0; + goto finish; + } + } + if (r < 0) + return r; + + e = m; + } /* We only recognize a selected few here, since we want to * enforce a redacted namespace */ @@ -264,9 +369,13 @@ int detect_container(const char **id) { _id = "lxc-libvirt"; else if (streq(e, "systemd-nspawn")) _id = "systemd-nspawn"; + else if (streq(e, "docker")) + _id = "docker"; else _id = "other"; + r = 1; + finish: cached_found = r; @@ -278,7 +387,7 @@ finish: } /* Returns a short identifier for the various VM/container implementations */ -Virtualization detect_virtualization(const char **id) { +int detect_virtualization(const char **id) { int r; r = detect_container(id);