1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-01 00:51:24 +03:00

virt: detect Docker and Podman containers

Docker doesn't set $container, so it cannot be detected that way. Instead, we
check for presence of /.dockerinit, which it creates. Podman does set
$container, but some Red Hat images (in particular, Fedora images) override
$container to equal "oci". So to correctly detect Podman containers, we check
for presence of /run/.containerenv, which is created by Podman and is now the
official way to get information about the container from within the container.

Fixes https://github.com/systemd/systemd/issues/15393
This commit is contained in:
Sergey Bugaev 2020-12-19 21:00:22 +03:00
parent 46a906f414
commit a4a9a6f7c6

View File

@ -453,6 +453,34 @@ static const char *const container_table[_VIRTUALIZATION_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int); DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
static int detect_container_files(void) {
unsigned i;
static const struct {
const char *file_path;
int id;
} container_file_table[] = {
/* https://github.com/containers/podman/issues/6192 */
/* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */
{ "/run/.containerenv", VIRTUALIZATION_PODMAN },
/* https://github.com/moby/moby/issues/18355 */
/* Docker must be the last in this table, see below. */
{ "/.dockerenv", VIRTUALIZATION_DOCKER },
};
for (i = 0; i < ELEMENTSOF(container_file_table); i++) {
if (access(container_file_table[i].file_path, F_OK) >= 0)
return container_file_table[i].id;
if (errno != ENOENT)
log_debug_errno(errno,
"Checking if %s exists failed, ignoring: %m",
container_file_table[i].file_path);
}
return VIRTUALIZATION_NONE;
}
int detect_container(void) { int detect_container(void) {
static thread_local int cached_found = _VIRTUALIZATION_INVALID; static thread_local int cached_found = _VIRTUALIZATION_INVALID;
_cleanup_free_ char *m = NULL, *o = NULL, *p = NULL; _cleanup_free_ char *m = NULL, *o = NULL, *p = NULL;
@ -530,7 +558,7 @@ int detect_container(void) {
*/ */
e = getenv("container"); e = getenv("container");
if (!e) if (!e)
goto none; goto check_files;
if (isempty(e)) { if (isempty(e)) {
r = VIRTUALIZATION_NONE; r = VIRTUALIZATION_NONE;
goto finish; goto finish;
@ -558,12 +586,28 @@ int detect_container(void) {
if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */ if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m"); log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
none: check_files:
/* If that didn't work, give up, assume no container manager. */ /* Check for existence of some well-known files. We only do this after checking
* for other specific container managers, otherwise we risk mistaking another
* container manager for Docker: the /.dockerenv file could inadvertently end up
* in a file system image. */
r = detect_container_files();
if (r)
goto finish;
/* If none of that worked, give up, assume no container manager. */
r = VIRTUALIZATION_NONE; r = VIRTUALIZATION_NONE;
goto finish; goto finish;
translate_name: translate_name:
if (streq(e, "oci")) {
/* Some images hardcode container=oci, but OCI is not a specific container manager.
* Try to detect one based on well-known files. */
r = detect_container_files();
if (!r)
r = VIRTUALIZATION_CONTAINER_OTHER;
goto finish;
}
r = container_from_string(e); r = container_from_string(e);
if (r < 0) if (r < 0)
r = VIRTUALIZATION_CONTAINER_OTHER; r = VIRTUALIZATION_CONTAINER_OTHER;