xref: /third_party/eudev/src/shared/virt.c (revision 99ca880a)
1/***
2  This file is part of eudev, forked from systemd.
3
4  Copyright 2011 Lennart Poettering
5
6  systemd is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation; either version 2.1 of the License, or
9  (at your option) any later version.
10
11  systemd is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public License
17  along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <string.h>
21#include <errno.h>
22#include <unistd.h>
23
24#include "util.h"
25#include "process-util.h"
26#include "virt.h"
27#include "fileio.h"
28
29int detect_container(const char **id) {
30
31        static thread_local int cached_found = -1;
32        static thread_local const char *cached_id = NULL;
33
34        _cleanup_free_ char *m = NULL;
35        const char *_id = NULL, *e = NULL;
36        int r;
37
38        if (_likely_(cached_found >= 0)) {
39
40                if (id)
41                        *id = cached_id;
42
43                return cached_found;
44        }
45
46        /* /proc/vz exists in container and outside of the container,
47         * /proc/bc only outside of the container. */
48        if (access("/proc/vz", F_OK) >= 0 &&
49            access("/proc/bc", F_OK) < 0) {
50                _id = "openvz";
51                r = 1;
52                goto finish;
53        }
54
55        if (getpid() == 1) {
56                /* If we are PID 1 we can just check our own
57                 * environment variable */
58
59                e = getenv("container");
60                if (isempty(e)) {
61                        r = 0;
62                        goto finish;
63                }
64        } else {
65
66                /* Otherwise, PID 1 dropped this information into a
67                 * file in UDEV_ROOT_RUN. This is better than accessing
68                 * /proc/1/environ, since we don't need CAP_SYS_PTRACE
69                 * for that. */
70
71                r = read_one_line_file(UDEV_ROOT_RUN "/systemd/container", &m);
72                if (r == -ENOENT) {
73                        r = 0;
74                        goto finish;
75                }
76                if (r < 0)
77                        return r;
78
79                e = m;
80        }
81
82        /* We only recognize a selected few here, since we want to
83         * enforce a redacted namespace */
84        if (streq(e, "lxc"))
85                _id ="lxc";
86        else if (streq(e, "lxc-libvirt"))
87                _id = "lxc-libvirt";
88        else if (streq(e, "systemd-nspawn"))
89                _id = "systemd-nspawn";
90        else if (streq(e, "docker"))
91                _id = "docker";
92        else
93                _id = "other";
94
95        r = 1;
96
97finish:
98        cached_found = r;
99
100        cached_id = _id;
101        if (id)
102                *id = _id;
103
104        return r;
105}
106