diff options
Diffstat (limited to 'src/kernel-install')
-rwxr-xr-x | src/kernel-install/60-ukify.install.in | 41 | ||||
-rwxr-xr-x | src/kernel-install/90-loaderentry.install.in | 2 | ||||
-rw-r--r-- | src/kernel-install/kernel-install.c | 157 | ||||
-rwxr-xr-x | src/kernel-install/test-kernel-install.sh | 5 |
4 files changed, 78 insertions, 127 deletions
diff --git a/src/kernel-install/60-ukify.install.in b/src/kernel-install/60-ukify.install.in index 0f7a0db..54a5daf 100755 --- a/src/kernel-install/60-ukify.install.in +++ b/src/kernel-install/60-ukify.install.in @@ -21,13 +21,13 @@ import argparse import os -import runpy import shlex +import types from shutil import which from pathlib import Path from typing import Optional -__version__ = '{{PROJECT_VERSION}} ({{GIT_VERSION}})' +__version__ = '{{PROJECT_VERSION_FULL}} ({{VERSION_TAG}})' try: VERBOSE = int(os.environ['KERNEL_INSTALL_VERBOSE']) > 0 @@ -151,7 +151,10 @@ def input_file_location( def uki_conf_location() -> Optional[Path]: return input_file_location('uki.conf', - '/etc/kernel') + '/etc/kernel', + '/run/kernel', + '/usr/local/lib/kernel', + '/usr/lib/kernel') def devicetree_config_location() -> Optional[Path]: @@ -216,22 +219,20 @@ def initrd_list(opts) -> list[Path]: return [*microcode, *opts.initrd, *initrd] -def call_ukify(opts): - # Punish me harder. - # We want this: - # ukify = importlib.machinery.SourceFileLoader('ukify', UKIFY).load_module() - # but it throws a DeprecationWarning. - # https://stackoverflow.com/questions/67631/how-can-i-import-a-module-dynamically-given-the-full-path - # https://github.com/python/cpython/issues/65635 - # offer "explanations", but to actually load a python file without a .py extension, - # the "solution" is 4+ incomprehensible lines. - # The solution with runpy gives a dictionary, which isn't great, but will do. - ukify = runpy.run_path(UKIFY, run_name='ukify') +def load_module(name: str, path: str) -> types.ModuleType: + module = types.ModuleType(name) + text = open(path).read() + exec(compile(text, path, 'exec'), module.__dict__) + return module + + +def call_ukify(opts) -> None: + ukify = load_module('ukify', UKIFY) # Create "empty" namespace. We want to override just a few settings, so it # doesn't make sense to configure everything. We pretend to parse an empty # argument set to prepopulate the namespace with the defaults. - opts2 = ukify['create_parser']().parse_args(['build']) + opts2 = ukify.create_parser().parse_args(['build']) opts2.config = uki_conf_location() opts2.uname = opts.kernel_version @@ -247,12 +248,10 @@ def call_ukify(opts): if BOOT_STUB: opts2.stub = BOOT_STUB - # opts2.summary = True - - ukify['apply_config'](opts2) - ukify['finalize_options'](opts2) - ukify['check_inputs'](opts2) - ukify['make_uki'](opts2) + ukify.apply_config(opts2) + ukify.finalize_options(opts2) + ukify.check_inputs(opts2) + ukify.make_uki(opts2) log(f'{opts2.output} has been created') diff --git a/src/kernel-install/90-loaderentry.install.in b/src/kernel-install/90-loaderentry.install.in index a52dd81..766d321 100755 --- a/src/kernel-install/90-loaderentry.install.in +++ b/src/kernel-install/90-loaderentry.install.in @@ -181,7 +181,7 @@ mkdir -p "${LOADER_ENTRY%/*}" || { [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Creating $LOADER_ENTRY" { echo "# Boot Loader Specification type#1 entry" - echo "# File created by $0 (systemd {{GIT_VERSION}})" + echo "# File created by $0 (systemd {{VERSION_TAG}})" echo "title $PRETTY_NAME" echo "version $KERNEL_VERSION" if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ]; then diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index 14ae1a8..5d559a9 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -19,6 +19,7 @@ #include "fs-util.h" #include "id128-util.h" #include "image-policy.h" +#include "kernel-config.h" #include "kernel-image.h" #include "main-func.h" #include "mkdir.h" @@ -49,6 +50,7 @@ static bool arg_legend = true; STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); +STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); typedef enum Action { @@ -150,37 +152,37 @@ static int context_copy(const Context *source, Context *ret) { return copy.rfd; } - r = strdup_or_null(source->layout_other, ©.layout_other); + r = strdup_to(©.layout_other, source->layout_other); if (r < 0) return r; - r = strdup_or_null(source->conf_root, ©.conf_root); + r = strdup_to(©.conf_root, source->conf_root); if (r < 0) return r; - r = strdup_or_null(source->boot_root, ©.boot_root); + r = strdup_to(©.boot_root, source->boot_root); if (r < 0) return r; - r = strdup_or_null(source->entry_token, ©.entry_token); + r = strdup_to(©.entry_token, source->entry_token); if (r < 0) return r; - r = strdup_or_null(source->entry_dir, ©.entry_dir); + r = strdup_to(©.entry_dir, source->entry_dir); if (r < 0) return r; - r = strdup_or_null(source->version, ©.version); + r = strdup_to(©.version, source->version); if (r < 0) return r; - r = strdup_or_null(source->kernel, ©.kernel); + r = strdup_to(©.kernel, source->kernel); if (r < 0) return r; r = strv_copy_unless_empty(source->initrds, ©.initrds); if (r < 0) return r; - r = strdup_or_null(source->initrd_generator, ©.initrd_generator); + r = strdup_to(©.initrd_generator, source->initrd_generator); if (r < 0) return r; - r = strdup_or_null(source->uki_generator, ©.uki_generator); + r = strdup_to(©.uki_generator, source->uki_generator); if (r < 0) return r; - r = strdup_or_null(source->staging_area, ©.staging_area); + r = strdup_to(©.staging_area, source->staging_area); if (r < 0) return r; r = strv_copy_unless_empty(source->plugins, ©.plugins); @@ -430,79 +432,30 @@ static int context_load_environment(Context *c) { return 0; } -static int context_ensure_conf_root(Context *c) { - int r; - - assert(c); - - if (c->conf_root) - return 0; - - r = chaseat(c->rfd, "/etc/kernel", CHASE_AT_RESOLVE_IN_ROOT, &c->conf_root, /* ret_fd = */ NULL); - if (r < 0) - log_debug_errno(r, "Failed to chase /etc/kernel, ignoring: %m"); - - return 0; -} - -static int context_load_install_conf_one(Context *c, const char *path) { - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char - *conf = NULL, *machine_id = NULL, *boot_root = NULL, *layout = NULL, - *initrd_generator = NULL, *uki_generator = NULL; - int r; - - assert(c); - assert(path); - - conf = path_join(path, "install.conf"); - if (!conf) - return log_oom(); - - r = chase_and_fopenat_unlocked(c->rfd, conf, CHASE_AT_RESOLVE_IN_ROOT, "re", NULL, &f); - if (r == -ENOENT) - return 0; - if (r < 0) - return log_error_errno(r, "Failed to chase %s: %m", conf); - - log_debug("Loading %s…", conf); - - r = parse_env_file(f, conf, - "MACHINE_ID", &machine_id, - "BOOT_ROOT", &boot_root, - "layout", &layout, - "initrd_generator", &initrd_generator, - "uki_generator", &uki_generator); - if (r < 0) - return log_error_errno(r, "Failed to parse '%s': %m", conf); - - (void) context_set_machine_id(c, machine_id, conf); - (void) context_set_boot_root(c, boot_root, conf); - (void) context_set_layout(c, layout, conf); - (void) context_set_initrd_generator(c, initrd_generator, conf); - (void) context_set_uki_generator(c, uki_generator, conf); - - log_debug("Loaded %s.", conf); - return 1; -} - static int context_load_install_conf(Context *c) { + _cleanup_free_ char *machine_id = NULL, *boot_root = NULL, *layout = NULL, + *initrd_generator = NULL, *uki_generator = NULL; int r; assert(c); - if (c->conf_root) { - r = context_load_install_conf_one(c, c->conf_root); - if (r != 0) - return r; - } + r = load_kernel_install_conf(arg_root, + c->conf_root, + &machine_id, + &boot_root, + &layout, + &initrd_generator, + &uki_generator); + if (r <= 0) + return r; - STRV_FOREACH(p, STRV_MAKE("/etc/kernel", "/usr/lib/kernel")) { - r = context_load_install_conf_one(c, *p); - if (r != 0) - return r; - } + (void) context_set_machine_id(c, machine_id, "config"); + (void) context_set_boot_root(c, boot_root, "config"); + (void) context_set_layout(c, layout, "config"); + (void) context_set_initrd_generator(c, initrd_generator, "config"); + (void) context_set_uki_generator(c, uki_generator, "config"); + log_debug("Loaded config."); return 0; } @@ -525,7 +478,7 @@ static int context_load_machine_info(Context *c) { if (r < 0 && r != -ENXIO) log_warning_errno(r, "Failed to read $KERNEL_INSTALL_READ_MACHINE_INFO, assuming yes: %m"); if (r == 0) { - log_debug("Skipping to read /etc/machine-info."); + log_debug("Skipping reading of /etc/machine-info."); return 0; } @@ -732,10 +685,6 @@ static int context_init(Context *c) { if (r < 0) return r; - r = context_ensure_conf_root(c); - if (r < 0) - return r; - r = context_load_install_conf(c); if (r < 0) return r; @@ -819,7 +768,7 @@ static int context_ensure_layout(Context *c) { if (!entry_token_path) return log_oom(); - r = is_dir_full(c->rfd, entry_token_path, /* follow = */ false); + r = is_dir_at(c->rfd, entry_token_path, /* follow = */ false); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to check if '%s' is a directory: %m", entry_token_path); if (r > 0) { @@ -996,11 +945,10 @@ static int context_build_arguments(Context *c) { return log_oom(); } else if (c->action == ACTION_INSPECT) { - r = strv_extend(&a, c->kernel ?: "[KERNEL_IMAGE]"); - if (r < 0) - return log_oom(); - - r = strv_extend(&a, "[INITRD...]"); + r = strv_extend_many( + &a, + c->kernel ?: "[KERNEL_IMAGE]", + "[INITRD...]"); if (r < 0) return log_oom(); } @@ -1184,7 +1132,7 @@ static int verb_add(int argc, char *argv[], void *userdata) { assert(argv); if (arg_root) - return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "'add' does not support --root=."); + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "'add' does not support --root= or --image=."); if (bypass()) return 0; @@ -1223,14 +1171,17 @@ static int verb_add_all(int argc, char *argv[], void *userdata) { assert(argv); + if (arg_root) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "'add-all' does not support --root= or --image=."); + if (bypass()) return 0; c->action = ACTION_ADD; - fd = open("/usr/lib/modules", O_DIRECTORY|O_RDONLY|O_CLOEXEC); + fd = chase_and_openat(c->rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL); if (fd < 0) - return log_error_errno(fd, "Failed to open /usr/lib/modules/: %m"); + return log_error_errno(fd, "Failed to open %s/usr/lib/modules/: %m", strempty(arg_root)); _cleanup_free_ DirectoryEntries *de = NULL; r = readdir_all(fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT, &de); @@ -1238,15 +1189,10 @@ static int verb_add_all(int argc, char *argv[], void *userdata) { return log_error_errno(r, "Failed to numerate /usr/lib/modules/ contents: %m"); FOREACH_ARRAY(d, de->entries, de->n_entries) { - - _cleanup_free_ char *j = path_join("/usr/lib/modules/", (*d)->d_name); - if (!j) - return log_oom(); - r = dirent_ensure_type(fd, *d); if (r < 0) { if (r != -ENOENT) /* don't log if just gone by now */ - log_debug_errno(r, "Failed to check if '%s' is a directory, ignoring: %m", j); + log_debug_errno(r, "Failed to check if '%s/usr/lib/modules/%s' is a directory, ignoring: %m", strempty(arg_root), (*d)->d_name); continue; } @@ -1259,7 +1205,7 @@ static int verb_add_all(int argc, char *argv[], void *userdata) { if (faccessat(fd, fn, F_OK, AT_SYMLINK_NOFOLLOW) < 0) { if (errno != ENOENT) - log_debug_errno(errno, "Failed to check if '/usr/lib/modules/%s/vmlinuz' exists, ignoring: %m", (*d)->d_name); + log_debug_errno(errno, "Failed to check if '%s/usr/lib/modules/%s/vmlinuz' exists, ignoring: %m", strempty(arg_root), (*d)->d_name); log_notice("Not adding version '%s', because kernel image not found.", (*d)->d_name); continue; @@ -1271,6 +1217,8 @@ static int verb_add_all(int argc, char *argv[], void *userdata) { if (r < 0) return log_error_errno(r, "Failed to copy execution context: %m"); + /* do_add() will look up the path in the correct root directory so we don't need to prefix it + * with arg_root here. */ _cleanup_free_ char *full = path_join("/usr/lib/modules/", fn); if (!full) return log_oom(); @@ -1311,7 +1259,7 @@ static int verb_remove(int argc, char *argv[], void *userdata) { assert(argv); if (arg_root) - return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "'remove' does not support --root=."); + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "'remove' does not support --root= or --image=."); if (argc > 2) log_debug("Too many arguments specified. 'kernel-install remove' takes only kernel version. " @@ -1449,12 +1397,13 @@ static int verb_inspect(int argc, char *argv[], void *userdata) { } static int verb_list(int argc, char *argv[], void *userdata) { + Context *c = ASSERT_PTR(userdata); _cleanup_close_ int fd = -EBADF; int r; - fd = open("/usr/lib/modules", O_DIRECTORY|O_RDONLY|O_CLOEXEC); + fd = chase_and_openat(c->rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL); if (fd < 0) - return log_error_errno(fd, "Failed to open /usr/lib/modules/: %m"); + return log_error_errno(fd, "Failed to open %s/usr/lib/modules/: %m", strempty(arg_root)); _cleanup_free_ DirectoryEntries *de = NULL; r = readdir_all(fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT, &de); @@ -1470,7 +1419,6 @@ static int verb_list(int argc, char *argv[], void *userdata) { table_set_align_percent(table, table_get_cell(table, 0, 1), 100); FOREACH_ARRAY(d, de->entries, de->n_entries) { - _cleanup_free_ char *j = path_join("/usr/lib/modules/", (*d)->d_name); if (!j) return log_oom(); @@ -1478,7 +1426,7 @@ static int verb_list(int argc, char *argv[], void *userdata) { r = dirent_ensure_type(fd, *d); if (r < 0) { if (r != -ENOENT) /* don't log if just gone by now */ - log_debug_errno(r, "Failed to check if '%s' is a directory, ignoring: %m", j); + log_debug_errno(r, "Failed to check if '%s/%s' is a directory, ignoring: %m", strempty(arg_root), j); continue; } @@ -1492,7 +1440,7 @@ static int verb_list(int argc, char *argv[], void *userdata) { bool exists; if (faccessat(fd, fn, F_OK, AT_SYMLINK_NOFOLLOW) < 0) { if (errno != ENOENT) - log_debug_errno(errno, "Failed to check if '/usr/lib/modules/%s/vmlinuz' exists, ignoring: %m", (*d)->d_name); + log_debug_errno(errno, "Failed to check if '%s/usr/lib/modules/%s/vmlinuz' exists, ignoring: %m", strempty(arg_root), (*d)->d_name); exists = false; } else @@ -1718,7 +1666,8 @@ static int run(int argc, char* argv[]) { DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_REQUIRE_ROOT | DISSECT_IMAGE_RELAX_VAR_CHECK | - DISSECT_IMAGE_VALIDATE_OS, + DISSECT_IMAGE_VALIDATE_OS | + DISSECT_IMAGE_ALLOW_USERSPACE_VERITY, &mounted_dir, /* ret_dir_fd= */ NULL, &loop_device); diff --git a/src/kernel-install/test-kernel-install.sh b/src/kernel-install/test-kernel-install.sh index 338d811..0e41979 100755 --- a/src/kernel-install/test-kernel-install.sh +++ b/src/kernel-install/test-kernel-install.sh @@ -125,7 +125,8 @@ grep -qE 'initrd' "$BOOT_ROOT/the-token/1.1.1/initrd" # Install UKI if [ -f "$ukify" ]; then - cat >>"$D/sources/install.conf" <<EOF + mkdir "$D/sources/install.conf.d" + cat >>"$D/sources/install.conf.d/override.conf" <<EOF layout=uki uki_generator=ukify EOF @@ -146,6 +147,8 @@ EOF "$ukify" inspect "$uki" | grep -qE '^.initrd' "$ukify" inspect "$uki" | grep -qE '^.linux' "$ukify" inspect "$uki" | grep -qE '^.dtb' + + rm "$D/sources/install.conf.d/override.conf" fi # Test bootctl |