199ca880aSopenharmony_ci/***
299ca880aSopenharmony_ci  This file is part of eudev, forked from systemd.
399ca880aSopenharmony_ci
499ca880aSopenharmony_ci  Copyright 2011 Lennart Poettering
599ca880aSopenharmony_ci
699ca880aSopenharmony_ci  systemd is free software; you can redistribute it and/or modify it
799ca880aSopenharmony_ci  under the terms of the GNU Lesser General Public License as published by
899ca880aSopenharmony_ci  the Free Software Foundation; either version 2.1 of the License, or
999ca880aSopenharmony_ci  (at your option) any later version.
1099ca880aSopenharmony_ci
1199ca880aSopenharmony_ci  systemd is distributed in the hope that it will be useful, but
1299ca880aSopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1399ca880aSopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1499ca880aSopenharmony_ci  Lesser General Public License for more details.
1599ca880aSopenharmony_ci
1699ca880aSopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1799ca880aSopenharmony_ci  along with systemd; If not, see <http://www.gnu.org/licenses/>.
1899ca880aSopenharmony_ci***/
1999ca880aSopenharmony_ci
2099ca880aSopenharmony_ci#include <string.h>
2199ca880aSopenharmony_ci#include <errno.h>
2299ca880aSopenharmony_ci#include <unistd.h>
2399ca880aSopenharmony_ci
2499ca880aSopenharmony_ci#include "util.h"
2599ca880aSopenharmony_ci#include "process-util.h"
2699ca880aSopenharmony_ci#include "virt.h"
2799ca880aSopenharmony_ci#include "fileio.h"
2899ca880aSopenharmony_ci
2999ca880aSopenharmony_ciint detect_container(const char **id) {
3099ca880aSopenharmony_ci
3199ca880aSopenharmony_ci        static thread_local int cached_found = -1;
3299ca880aSopenharmony_ci        static thread_local const char *cached_id = NULL;
3399ca880aSopenharmony_ci
3499ca880aSopenharmony_ci        _cleanup_free_ char *m = NULL;
3599ca880aSopenharmony_ci        const char *_id = NULL, *e = NULL;
3699ca880aSopenharmony_ci        int r;
3799ca880aSopenharmony_ci
3899ca880aSopenharmony_ci        if (_likely_(cached_found >= 0)) {
3999ca880aSopenharmony_ci
4099ca880aSopenharmony_ci                if (id)
4199ca880aSopenharmony_ci                        *id = cached_id;
4299ca880aSopenharmony_ci
4399ca880aSopenharmony_ci                return cached_found;
4499ca880aSopenharmony_ci        }
4599ca880aSopenharmony_ci
4699ca880aSopenharmony_ci        /* /proc/vz exists in container and outside of the container,
4799ca880aSopenharmony_ci         * /proc/bc only outside of the container. */
4899ca880aSopenharmony_ci        if (access("/proc/vz", F_OK) >= 0 &&
4999ca880aSopenharmony_ci            access("/proc/bc", F_OK) < 0) {
5099ca880aSopenharmony_ci                _id = "openvz";
5199ca880aSopenharmony_ci                r = 1;
5299ca880aSopenharmony_ci                goto finish;
5399ca880aSopenharmony_ci        }
5499ca880aSopenharmony_ci
5599ca880aSopenharmony_ci        if (getpid() == 1) {
5699ca880aSopenharmony_ci                /* If we are PID 1 we can just check our own
5799ca880aSopenharmony_ci                 * environment variable */
5899ca880aSopenharmony_ci
5999ca880aSopenharmony_ci                e = getenv("container");
6099ca880aSopenharmony_ci                if (isempty(e)) {
6199ca880aSopenharmony_ci                        r = 0;
6299ca880aSopenharmony_ci                        goto finish;
6399ca880aSopenharmony_ci                }
6499ca880aSopenharmony_ci        } else {
6599ca880aSopenharmony_ci
6699ca880aSopenharmony_ci                /* Otherwise, PID 1 dropped this information into a
6799ca880aSopenharmony_ci                 * file in UDEV_ROOT_RUN. This is better than accessing
6899ca880aSopenharmony_ci                 * /proc/1/environ, since we don't need CAP_SYS_PTRACE
6999ca880aSopenharmony_ci                 * for that. */
7099ca880aSopenharmony_ci
7199ca880aSopenharmony_ci                r = read_one_line_file(UDEV_ROOT_RUN "/systemd/container", &m);
7299ca880aSopenharmony_ci                if (r == -ENOENT) {
7399ca880aSopenharmony_ci                        r = 0;
7499ca880aSopenharmony_ci                        goto finish;
7599ca880aSopenharmony_ci                }
7699ca880aSopenharmony_ci                if (r < 0)
7799ca880aSopenharmony_ci                        return r;
7899ca880aSopenharmony_ci
7999ca880aSopenharmony_ci                e = m;
8099ca880aSopenharmony_ci        }
8199ca880aSopenharmony_ci
8299ca880aSopenharmony_ci        /* We only recognize a selected few here, since we want to
8399ca880aSopenharmony_ci         * enforce a redacted namespace */
8499ca880aSopenharmony_ci        if (streq(e, "lxc"))
8599ca880aSopenharmony_ci                _id ="lxc";
8699ca880aSopenharmony_ci        else if (streq(e, "lxc-libvirt"))
8799ca880aSopenharmony_ci                _id = "lxc-libvirt";
8899ca880aSopenharmony_ci        else if (streq(e, "systemd-nspawn"))
8999ca880aSopenharmony_ci                _id = "systemd-nspawn";
9099ca880aSopenharmony_ci        else if (streq(e, "docker"))
9199ca880aSopenharmony_ci                _id = "docker";
9299ca880aSopenharmony_ci        else
9399ca880aSopenharmony_ci                _id = "other";
9499ca880aSopenharmony_ci
9599ca880aSopenharmony_ci        r = 1;
9699ca880aSopenharmony_ci
9799ca880aSopenharmony_cifinish:
9899ca880aSopenharmony_ci        cached_found = r;
9999ca880aSopenharmony_ci
10099ca880aSopenharmony_ci        cached_id = _id;
10199ca880aSopenharmony_ci        if (id)
10299ca880aSopenharmony_ci                *id = _id;
10399ca880aSopenharmony_ci
10499ca880aSopenharmony_ci        return r;
10599ca880aSopenharmony_ci}
106