]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/virt.c
Merge pull request #7551 from poettering/resolved-unknown-scope
[thirdparty/systemd.git] / src / basic / virt.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b52aae1d
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
b52aae1d
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
b52aae1d 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
b52aae1d
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b52aae1d 21#include <errno.h>
11c3a366
TA
22#include <stdint.h>
23#include <stdlib.h>
07630cea 24#include <string.h>
b52aae1d
LP
25#include <unistd.h>
26
b5efdb8a 27#include "alloc-util.h"
ade61d3b 28#include "dirent-util.h"
295ee984 29#include "env-util.h"
ade61d3b 30#include "fd-util.h"
07630cea 31#include "fileio.h"
11c3a366 32#include "macro.h"
93cc7779 33#include "process-util.h"
b5efdb8a 34#include "stat-util.h"
8b43440b 35#include "string-table.h"
07630cea 36#include "string-util.h"
b52aae1d
LP
37#include "virt.h"
38
75f86906 39static int detect_vm_cpuid(void) {
b52aae1d 40
2ef8a4c4 41 /* CPUID is an x86 specific interface. */
bdb628ee 42#if defined(__i386__) || defined(__x86_64__)
b52aae1d 43
75f86906
LP
44 static const struct {
45 const char *cpuid;
46 int id;
47 } cpuid_vendor_table[] = {
48 { "XenVMMXenVMM", VIRTUALIZATION_XEN },
49 { "KVMKVMKVM", VIRTUALIZATION_KVM },
5588612e 50 { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU },
b52aae1d 51 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
75f86906 52 { "VMwareVMware", VIRTUALIZATION_VMWARE },
ff85f271 53 /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
75f86906 54 { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
aa0c3427
LBS
55 /* https://wiki.freebsd.org/bhyve */
56 { "bhyve bhyve ", VIRTUALIZATION_BHYVE },
75f86906 57 };
b52aae1d
LP
58
59 uint32_t eax, ecx;
b52aae1d
LP
60 bool hypervisor;
61
62 /* http://lwn.net/Articles/301888/ */
b52aae1d
LP
63
64#if defined (__i386__)
65#define REG_a "eax"
66#define REG_b "ebx"
67#elif defined (__amd64__)
68#define REG_a "rax"
69#define REG_b "rbx"
70#endif
71
72 /* First detect whether there is a hypervisor */
73 eax = 1;
74 __asm__ __volatile__ (
75 /* ebx/rbx is being used for PIC! */
76 " push %%"REG_b" \n\t"
77 " cpuid \n\t"
78 " pop %%"REG_b" \n\t"
79
80 : "=a" (eax), "=c" (ecx)
81 : "0" (eax)
82 );
83
84 hypervisor = !!(ecx & 0x80000000U);
85
86 if (hypervisor) {
75f86906
LP
87 union {
88 uint32_t sig32[3];
89 char text[13];
90 } sig = {};
91 unsigned j;
b52aae1d
LP
92
93 /* There is a hypervisor, see what it is */
94 eax = 0x40000000U;
95 __asm__ __volatile__ (
96 /* ebx/rbx is being used for PIC! */
97 " push %%"REG_b" \n\t"
98 " cpuid \n\t"
99 " mov %%ebx, %1 \n\t"
100 " pop %%"REG_b" \n\t"
101
102 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
103 : "0" (eax)
104 );
105
9f63a08d
SS
106 log_debug("Virtualization found, CPUID=%s", sig.text);
107
75f86906
LP
108 for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
109 if (streq(sig.text, cpuid_vendor_table[j].cpuid))
110 return cpuid_vendor_table[j].id;
bdb628ee 111
75f86906 112 return VIRTUALIZATION_VM_OTHER;
b52aae1d 113 }
bdb628ee 114#endif
9f63a08d 115 log_debug("No virtualization found in CPUID");
bdb628ee 116
75f86906 117 return VIRTUALIZATION_NONE;
bdb628ee
ZJS
118}
119
75f86906 120static int detect_vm_device_tree(void) {
db6a8689 121#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
d831deb5
CA
122 _cleanup_free_ char *hvtype = NULL;
123 int r;
124
b8f1df82 125 r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype);
75f86906 126 if (r == -ENOENT) {
ce09c71d
AJ
127 _cleanup_closedir_ DIR *dir = NULL;
128 struct dirent *dent;
129
130 dir = opendir("/proc/device-tree");
131 if (!dir) {
9f63a08d
SS
132 if (errno == ENOENT) {
133 log_debug_errno(errno, "/proc/device-tree: %m");
75f86906 134 return VIRTUALIZATION_NONE;
9f63a08d 135 }
ce09c71d
AJ
136 return -errno;
137 }
138
75f86906 139 FOREACH_DIRENT(dent, dir, return -errno)
9f63a08d
SS
140 if (strstr(dent->d_name, "fw-cfg")) {
141 log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
75f86906 142 return VIRTUALIZATION_QEMU;
9f63a08d 143 }
75f86906 144
9f63a08d 145 log_debug("No virtualization found in /proc/device-tree/*");
75f86906
LP
146 return VIRTUALIZATION_NONE;
147 } else if (r < 0)
148 return r;
149
9f63a08d 150 log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
75f86906
LP
151 if (streq(hvtype, "linux,kvm"))
152 return VIRTUALIZATION_KVM;
153 else if (strstr(hvtype, "xen"))
154 return VIRTUALIZATION_XEN;
155 else
156 return VIRTUALIZATION_VM_OTHER;
157#else
9f63a08d 158 log_debug("This platform does not support /proc/device-tree");
75f86906 159 return VIRTUALIZATION_NONE;
d831deb5 160#endif
d831deb5
CA
161}
162
75f86906 163static int detect_vm_dmi(void) {
2ef8a4c4 164#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
bdb628ee
ZJS
165
166 static const char *const dmi_vendors[] = {
3728dcde 167 "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
bdb628ee
ZJS
168 "/sys/class/dmi/id/sys_vendor",
169 "/sys/class/dmi/id/board_vendor",
170 "/sys/class/dmi/id/bios_vendor"
171 };
172
75f86906
LP
173 static const struct {
174 const char *vendor;
175 int id;
176 } dmi_vendor_table[] = {
3728dcde 177 { "KVM", VIRTUALIZATION_KVM },
75f86906 178 { "QEMU", VIRTUALIZATION_QEMU },
bdb628ee 179 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
75f86906
LP
180 { "VMware", VIRTUALIZATION_VMWARE },
181 { "VMW", VIRTUALIZATION_VMWARE },
182 { "innotek GmbH", VIRTUALIZATION_ORACLE },
183 { "Xen", VIRTUALIZATION_XEN },
184 { "Bochs", VIRTUALIZATION_BOCHS },
185 { "Parallels", VIRTUALIZATION_PARALLELS },
aa0c3427
LBS
186 /* https://wiki.freebsd.org/bhyve */
187 { "BHYVE", VIRTUALIZATION_BHYVE },
75f86906 188 };
bdb628ee 189 unsigned i;
75f86906 190 int r;
b52aae1d
LP
191
192 for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
b1b8e816 193 _cleanup_free_ char *s = NULL;
75f86906 194 unsigned j;
b52aae1d 195
b1b8e816
LP
196 r = read_one_line_file(dmi_vendors[i], &s);
197 if (r < 0) {
75f86906
LP
198 if (r == -ENOENT)
199 continue;
b52aae1d 200
75f86906 201 return r;
b52aae1d
LP
202 }
203
9f63a08d
SS
204
205
75f86906 206 for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
9f63a08d
SS
207 if (startswith(s, dmi_vendor_table[j].vendor)) {
208 log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
75f86906 209 return dmi_vendor_table[j].id;
9f63a08d 210 }
b52aae1d 211 }
bdb628ee
ZJS
212#endif
213
9f63a08d
SS
214 log_debug("No virtualization found in DMI");
215
75f86906 216 return VIRTUALIZATION_NONE;
bdb628ee
ZJS
217}
218
75f86906 219static int detect_vm_xen(void) {
45e1c7d5 220
3f61278b 221 /* Check for Dom0 will be executed later in detect_vm_xen_dom0
87dc723a
OH
222 The presence of /proc/xen indicates some form of a Xen domain */
223 if (access("/proc/xen", F_OK) < 0) {
224 log_debug("Virtualization XEN not found, /proc/xen does not exist");
3f61278b
SS
225 return VIRTUALIZATION_NONE;
226 }
227
87dc723a 228 log_debug("Virtualization XEN found (/proc/xen exists)");
45e1c7d5 229 return VIRTUALIZATION_XEN;
3f61278b
SS
230}
231
232static bool detect_vm_xen_dom0(void) {
75f86906
LP
233 _cleanup_free_ char *domcap = NULL;
234 char *cap, *i;
bdb628ee 235 int r;
b52aae1d 236
75f86906 237 r = read_one_line_file("/proc/xen/capabilities", &domcap);
9f63a08d
SS
238 if (r == -ENOENT) {
239 log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
3f61278b 240 return false;
9f63a08d 241 }
d5b687e7
LP
242 if (r < 0)
243 return r;
bdb628ee 244
75f86906
LP
245 i = domcap;
246 while ((cap = strsep(&i, ",")))
247 if (streq(cap, "control_d"))
248 break;
9f63a08d
SS
249 if (!cap) {
250 log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
3f61278b 251 return false;
9f63a08d
SS
252 }
253
254 log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
3f61278b 255 return true;
75f86906 256}
37287585 257
75f86906
LP
258static int detect_vm_hypervisor(void) {
259 _cleanup_free_ char *hvtype = NULL;
260 int r;
37287585 261
75f86906
LP
262 r = read_one_line_file("/sys/hypervisor/type", &hvtype);
263 if (r == -ENOENT)
264 return VIRTUALIZATION_NONE;
265 if (r < 0)
266 return r;
37287585 267
9f63a08d
SS
268 log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
269
75f86906
LP
270 if (streq(hvtype, "xen"))
271 return VIRTUALIZATION_XEN;
272 else
273 return VIRTUALIZATION_VM_OTHER;
274}
37287585 275
75f86906
LP
276static int detect_vm_uml(void) {
277 _cleanup_free_ char *cpuinfo_contents = NULL;
278 int r;
37287585 279
75f86906
LP
280 /* Detect User-Mode Linux by reading /proc/cpuinfo */
281 r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
282 if (r < 0)
bdb628ee 283 return r;
9f63a08d
SS
284
285 if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
286 log_debug("UML virtualization found in /proc/cpuinfo");
75f86906 287 return VIRTUALIZATION_UML;
9f63a08d 288 }
bdb628ee 289
82f8bae2 290 log_debug("No virtualization found in /proc/cpuinfo.");
75f86906
LP
291 return VIRTUALIZATION_NONE;
292}
e32886e0 293
75f86906 294static int detect_vm_zvm(void) {
bdb628ee 295
75f86906
LP
296#if defined(__s390__)
297 _cleanup_free_ char *t = NULL;
298 int r;
e32886e0 299
c4cd1d4d 300 r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t);
75f86906
LP
301 if (r == -ENOENT)
302 return VIRTUALIZATION_NONE;
303 if (r < 0)
304 return r;
e32886e0 305
9f63a08d 306 log_debug("Virtualization %s found in /proc/sysinfo", t);
75f86906
LP
307 if (streq(t, "z/VM"))
308 return VIRTUALIZATION_ZVM;
309 else
310 return VIRTUALIZATION_KVM;
311#else
9f63a08d 312 log_debug("This platform does not support /proc/sysinfo");
75f86906
LP
313 return VIRTUALIZATION_NONE;
314#endif
315}
e32886e0 316
75f86906
LP
317/* Returns a short identifier for the various VM implementations */
318int detect_vm(void) {
319 static thread_local int cached_found = _VIRTUALIZATION_INVALID;
28b1a3ea 320 int r, dmi;
530c1c30 321 bool other = false;
e32886e0 322
75f86906
LP
323 if (cached_found >= 0)
324 return cached_found;
bdb628ee 325
f6875b0a 326 /* We have to use the correct order here:
f6875b0a 327 *
28b1a3ea
CH
328 * -> First try to detect Oracle Virtualbox, even if it uses KVM.
329 * -> Second try to detect from cpuid, this will report KVM for
330 * whatever software is used even if info in dmi is overwritten.
331 * -> Third try to detect from dmi. */
5f1c788c 332
28b1a3ea 333 dmi = detect_vm_dmi();
2f8e375d
BR
334 if (dmi == VIRTUALIZATION_ORACLE) {
335 r = dmi;
336 goto finish;
337 }
5f1c788c 338
28b1a3ea 339 r = detect_vm_cpuid();
75f86906
LP
340 if (r < 0)
341 return r;
530c1c30
RC
342 if (r != VIRTUALIZATION_NONE) {
343 if (r == VIRTUALIZATION_VM_OTHER)
344 other = true;
345 else
346 goto finish;
347 }
d831deb5 348
28b1a3ea 349 r = dmi;
75f86906
LP
350 if (r < 0)
351 return r;
530c1c30
RC
352 if (r != VIRTUALIZATION_NONE) {
353 if (r == VIRTUALIZATION_VM_OTHER)
354 other = true;
355 else
356 goto finish;
357 }
b52aae1d 358
42685451 359 /* x86 xen will most likely be detected by cpuid. If not (most likely
87dc723a
OH
360 * because we're not an x86 guest), then we should try the /proc/xen
361 * directory next. If that's not found, then we check for the high-level
362 * hypervisor sysfs file.
363 */
42685451
AJ
364
365 r = detect_vm_xen();
7080ea16
RR
366 if (r < 0)
367 return r;
530c1c30
RC
368 if (r != VIRTUALIZATION_NONE) {
369 if (r == VIRTUALIZATION_VM_OTHER)
370 other = true;
371 else
372 goto finish;
373 }
7080ea16 374
75f86906
LP
375 r = detect_vm_hypervisor();
376 if (r < 0)
377 return r;
530c1c30
RC
378 if (r != VIRTUALIZATION_NONE) {
379 if (r == VIRTUALIZATION_VM_OTHER)
380 other = true;
381 else
382 goto finish;
383 }
f41925b4 384
75f86906
LP
385 r = detect_vm_device_tree();
386 if (r < 0)
387 return r;
530c1c30
RC
388 if (r != VIRTUALIZATION_NONE) {
389 if (r == VIRTUALIZATION_VM_OTHER)
390 other = true;
391 else
392 goto finish;
393 }
f41925b4 394
75f86906
LP
395 r = detect_vm_uml();
396 if (r < 0)
397 return r;
530c1c30
RC
398 if (r != VIRTUALIZATION_NONE) {
399 if (r == VIRTUALIZATION_VM_OTHER)
400 other = true;
401 else
402 goto finish;
403 }
f41925b4 404
75f86906
LP
405 r = detect_vm_zvm();
406 if (r < 0)
407 return r;
0fb533a5
LP
408
409finish:
3f61278b
SS
410 /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
411 * In order to detect the Dom0 as not virtualization we need to
412 * double-check it */
413 if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
414 r = VIRTUALIZATION_NONE;
530c1c30
RC
415 else if (r == VIRTUALIZATION_NONE && other)
416 r = VIRTUALIZATION_VM_OTHER;
3f61278b 417
0fb533a5 418 cached_found = r;
9f63a08d 419 log_debug("Found VM virtualization %s", virtualization_to_string(r));
0fb533a5 420 return r;
b52aae1d
LP
421}
422
75f86906 423int detect_container(void) {
0fb533a5 424
75f86906
LP
425 static const struct {
426 const char *value;
427 int id;
428 } value_table[] = {
429 { "lxc", VIRTUALIZATION_LXC },
430 { "lxc-libvirt", VIRTUALIZATION_LXC_LIBVIRT },
431 { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
432 { "docker", VIRTUALIZATION_DOCKER },
9fb16425 433 { "rkt", VIRTUALIZATION_RKT },
75f86906 434 };
0fb533a5 435
75f86906 436 static thread_local int cached_found = _VIRTUALIZATION_INVALID;
fdd25311 437 _cleanup_free_ char *m = NULL;
75f86906
LP
438 const char *e = NULL;
439 unsigned j;
ab94af92 440 int r;
b52aae1d 441
75f86906 442 if (cached_found >= 0)
0fb533a5 443 return cached_found;
0fb533a5 444
8d6e8034 445 /* /proc/vz exists in container and outside of the container, /proc/bc only outside of the container. */
b52aae1d
LP
446 if (access("/proc/vz", F_OK) >= 0 &&
447 access("/proc/bc", F_OK) < 0) {
75f86906 448 r = VIRTUALIZATION_OPENVZ;
0fb533a5 449 goto finish;
b52aae1d
LP
450 }
451
df0ff127 452 if (getpid_cached() == 1) {
8d6e8034 453 /* If we are PID 1 we can just check our own environment variable, and that's authoritative. */
fdd25311
LP
454
455 e = getenv("container");
456 if (isempty(e)) {
75f86906 457 r = VIRTUALIZATION_NONE;
fdd25311
LP
458 goto finish;
459 }
fdd25311 460
8d6e8034
LP
461 goto translate_name;
462 }
463
464 /* Otherwise, PID 1 might have dropped this information into a file in /run. This is better than accessing
465 * /proc/1/environ, since we don't need CAP_SYS_PTRACE for that. */
466 r = read_one_line_file("/run/systemd/container", &m);
467 if (r >= 0) {
468 e = m;
469 goto translate_name;
470 }
471 if (r != -ENOENT)
472 return log_debug_errno(r, "Failed to read /run/systemd/container: %m");
473
474 /* Fallback for cases where PID 1 was not systemd (for example, cases where init=/bin/sh is used. */
475 r = getenv_for_pid(1, "container", &m);
476 if (r > 0) {
fdd25311 477 e = m;
8d6e8034 478 goto translate_name;
fdd25311 479 }
8d6e8034
LP
480 if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
481 log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
482
483 /* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. Hence, if the PID shown
484 * there is not 1, we know we are in a PID namespace. and hence a container. */
485 r = read_one_line_file("/proc/1/sched", &m);
486 if (r >= 0) {
487 const char *t;
488
489 t = strrchr(m, '(');
490 if (!t)
491 return -EIO;
492
493 if (!startswith(t, "(1,")) {
494 r = VIRTUALIZATION_CONTAINER_OTHER;
495 goto finish;
496 }
497 } else if (r != -ENOENT)
498 return r;
499
500 /* If that didn't work, give up, assume no container manager. */
501 r = VIRTUALIZATION_NONE;
502 goto finish;
b52aae1d 503
8d6e8034 504translate_name:
75f86906
LP
505 for (j = 0; j < ELEMENTSOF(value_table); j++)
506 if (streq(e, value_table[j].value)) {
507 r = value_table[j].id;
508 goto finish;
509 }
0fb533a5 510
f499daf4 511 r = VIRTUALIZATION_CONTAINER_OTHER;
fdd25311 512
0fb533a5 513finish:
8d6e8034 514 log_debug("Found container virtualization %s.", virtualization_to_string(r));
0fb533a5 515 cached_found = r;
ab94af92 516 return r;
b52aae1d
LP
517}
518
75f86906 519int detect_virtualization(void) {
b52aae1d 520 int r;
b52aae1d 521
75f86906 522 r = detect_container();
9f63a08d
SS
523 if (r == 0)
524 r = detect_vm();
b52aae1d 525
9f63a08d 526 return r;
b52aae1d 527}
75f86906 528
299a34c1
ZJS
529static int userns_has_mapping(const char *name) {
530 _cleanup_fclose_ FILE *f = NULL;
531 _cleanup_free_ char *buf = NULL;
532 size_t n_allocated = 0;
533 ssize_t n;
534 uint32_t a, b, c;
535 int r;
536
537 f = fopen(name, "re");
538 if (!f) {
539 log_debug_errno(errno, "Failed to open %s: %m", name);
abd67ce7 540 return errno == ENOENT ? false : -errno;
299a34c1
ZJS
541 }
542
543 n = getline(&buf, &n_allocated, f);
544 if (n < 0) {
545 if (feof(f)) {
546 log_debug("%s is empty, we're in an uninitialized user namespace", name);
547 return true;
548 }
549
550 return log_debug_errno(errno, "Failed to read %s: %m", name);
551 }
552
553 r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c);
554 if (r < 3)
555 return log_debug_errno(errno, "Failed to parse %s: %m", name);
556
557 if (a == 0 && b == 0 && c == UINT32_MAX) {
558 /* The kernel calls mappings_overlap() and does not allow overlaps */
559 log_debug("%s has a full 1:1 mapping", name);
560 return false;
561 }
562
563 /* Anything else implies that we are in a user namespace */
564 log_debug("Mapping found in %s, we're in a user namespace", name);
565 return true;
566}
567
568int running_in_userns(void) {
569 _cleanup_free_ char *line = NULL;
570 int r;
571
572 r = userns_has_mapping("/proc/self/uid_map");
573 if (r != 0)
574 return r;
575
576 r = userns_has_mapping("/proc/self/gid_map");
577 if (r != 0)
578 return r;
579
580 /* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also
581 * possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups"
582 * also does not exist. We cannot distinguish those two cases, so assume that
583 * we're running on a stripped-down recent kernel, rather than on an old one,
584 * and if the file is not found, return false.
585 */
586 r = read_one_line_file("/proc/self/setgroups", &line);
587 if (r < 0) {
588 log_debug_errno(r, "/proc/self/setgroups: %m");
589 return r == -ENOENT ? false : r;
590 }
591
592 truncate_nl(line);
593 r = streq(line, "deny");
594 /* See user_namespaces(7) for a description of this "setgroups" contents. */
595 log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in");
596 return r;
597}
598
7f4b3c5e 599int running_in_chroot(void) {
d6d0473d 600 int ret;
7f4b3c5e 601
08a28eec
LN
602 if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
603 return 0;
604
e3f791a2 605 ret = files_same("/proc/1/root", "/", 0);
d6d0473d
LP
606 if (ret < 0)
607 return ret;
7f4b3c5e 608
d6d0473d 609 return ret == 0;
7f4b3c5e
LP
610}
611
75f86906
LP
612static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
613 [VIRTUALIZATION_NONE] = "none",
614 [VIRTUALIZATION_KVM] = "kvm",
615 [VIRTUALIZATION_QEMU] = "qemu",
616 [VIRTUALIZATION_BOCHS] = "bochs",
617 [VIRTUALIZATION_XEN] = "xen",
618 [VIRTUALIZATION_UML] = "uml",
619 [VIRTUALIZATION_VMWARE] = "vmware",
620 [VIRTUALIZATION_ORACLE] = "oracle",
621 [VIRTUALIZATION_MICROSOFT] = "microsoft",
622 [VIRTUALIZATION_ZVM] = "zvm",
623 [VIRTUALIZATION_PARALLELS] = "parallels",
aa0c3427 624 [VIRTUALIZATION_BHYVE] = "bhyve",
75f86906
LP
625 [VIRTUALIZATION_VM_OTHER] = "vm-other",
626
627 [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
628 [VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt",
629 [VIRTUALIZATION_LXC] = "lxc",
630 [VIRTUALIZATION_OPENVZ] = "openvz",
631 [VIRTUALIZATION_DOCKER] = "docker",
9fb16425 632 [VIRTUALIZATION_RKT] = "rkt",
75f86906
LP
633 [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
634};
635
636DEFINE_STRING_TABLE_LOOKUP(virtualization, int);