diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-11-19 15:48:41 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-11-23 22:55:11 +0100 |
commit | a4e0d6171318b5f381a1cbdb6de895920d7f15d6 (patch) | |
tree | f6f1bab7657750adfe5edc6fca30010960b7894a /src/shared/dissect-image.c | |
parent | 8570b98b120c8979cb07f7ac06d4df4e24cb90bd (diff) | |
download | systemd-a4e0d6171318b5f381a1cbdb6de895920d7f15d6.tar.gz |
dissect-image: when extracting metadata from image also check if it contains init system
It's good to know whether we can boot the image.
Diffstat (limited to 'src/shared/dissect-image.c')
-rw-r--r-- | src/shared/dissect-image.c | 75 |
1 files changed, 66 insertions, 9 deletions
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 18c7991570..b92df413a9 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -46,6 +46,7 @@ #include "hostname-setup.h" #include "id128-util.h" #include "import-util.h" +#include "io-util.h" #include "mkdir-label.h" #include "mount-util.h" #include "mountpoint-util.h" @@ -748,10 +749,14 @@ int dissect_image( if (r != 0) return errno_or_else(EIO); - m = new0(DissectedImage, 1); + m = new(DissectedImage, 1); if (!m) return -ENOMEM; + *m = (DissectedImage) { + .has_init_system = -1, + }; + r = sd_device_get_sysname(d, &sysname); if (r < 0) return log_debug_errno(r, "Failed to get device sysname: %m"); @@ -3012,6 +3017,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) { META_MACHINE_INFO, META_OS_RELEASE, META_EXTENSION_RELEASE, + META_HAS_INIT_SYSTEM, _META_MAX, }; @@ -3021,7 +3027,8 @@ int dissected_image_acquire_metadata(DissectedImage *m) { [META_MACHINE_INFO] = "/etc/machine-info\0", [META_OS_RELEASE] = ("/etc/os-release\0" "/usr/lib/os-release\0"), - [META_EXTENSION_RELEASE] = "extension-release\0", /* Used only for logging. */ + [META_EXTENSION_RELEASE] = "extension-release\0", /* Used only for logging. */ + [META_HAS_INIT_SYSTEM] = "has-init-system\0", /* ditto */ }; _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **extension_release = NULL; @@ -3032,6 +3039,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) { _cleanup_free_ char *hostname = NULL; unsigned n_meta_initialized = 0; int fds[2 * _META_MAX], r, v; + int has_init_system = -1; ssize_t n; BLOCK_SIGNALS(SIGCHLD); @@ -3063,6 +3071,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) { if (r < 0) goto finish; if (r == 0) { + /* Child in a new mount namespace */ error_pipe[0] = safe_close(error_pipe[0]); r = dissected_image_mount( @@ -3092,7 +3101,9 @@ int dissected_image_acquire_metadata(DissectedImage *m) { fds[2*k] = safe_close(fds[2*k]); - if (k == META_EXTENSION_RELEASE) { + switch (k) { + + case META_EXTENSION_RELEASE: /* As per the os-release spec, if the image is an extension it will have a file * named after the image name in extension-release.d/ - we use the image name * and try to resolve it with the extension-release helpers, as sometimes @@ -3105,12 +3116,42 @@ int dissected_image_acquire_metadata(DissectedImage *m) { r = open_extension_release(t, m->image_name, NULL, &fd); if (r < 0) fd = r; /* Propagate the error. */ - } else + break; + + case META_HAS_INIT_SYSTEM: { + bool found = false; + const char *init; + + FOREACH_STRING(init, + "/usr/lib/systemd/systemd", /* systemd on /usr merged system */ + "/lib/systemd/systemd", /* systemd on /usr non-merged systems */ + "/sbin/init") { /* traditional path the Linux kernel invokes */ + + r = chase_symlinks(init, t, CHASE_PREFIX_ROOT, NULL, NULL); + if (r < 0) { + if (r != -ENOENT) + log_debug_errno(r, "Failed to resolve %s, ignoring: %m", init); + } else { + found = true; + break; + } + } + + r = loop_write(fds[2*k+1], &found, sizeof(found), false); + if (r < 0) + goto inner_fail; + + continue; + } + + default: NULSTR_FOREACH(p, paths[k]) { fd = chase_symlinks_and_open(p, t, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); if (fd >= 0) break; } + } + if (fd < 0) { log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]); fds[2*k+1] = safe_close(fds[2*k+1]); @@ -3118,15 +3159,17 @@ int dissected_image_acquire_metadata(DissectedImage *m) { } r = copy_bytes(fd, fds[2*k+1], UINT64_MAX, 0); - if (r < 0) { - (void) write(error_pipe[1], &r, sizeof(r)); - _exit(EXIT_FAILURE); - } + if (r < 0) + goto inner_fail; fds[2*k+1] = safe_close(fds[2*k+1]); } _exit(EXIT_SUCCESS); + + inner_fail: + (void) write(error_pipe[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); } error_pipe[1] = safe_close(error_pipe[1]); @@ -3194,7 +3237,20 @@ int dissected_image_acquire_metadata(DissectedImage *m) { log_debug_errno(r, "Failed to read extension release file: %m"); break; - } + + case META_HAS_INIT_SYSTEM: { + bool b = false; + size_t nr; + + errno = 0; + nr = fread(&b, 1, sizeof(b), f); + if (nr != sizeof(b)) + log_debug_errno(errno_or_else(EIO), "Failed to read has-init-system boolean: %m"); + else + has_init_system = b; + + break; + }} } r = wait_for_terminate_and_check("(sd-dissect)", child, 0); @@ -3218,6 +3274,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) { strv_free_and_replace(m->machine_info, machine_info); strv_free_and_replace(m->os_release, os_release); strv_free_and_replace(m->extension_release, extension_release); + m->has_init_system = has_init_system; finish: for (unsigned k = 0; k < n_meta_initialized; k++) |