diff options
Diffstat (limited to 'discover/boot.c')
-rw-r--r-- | discover/boot.c | 147 |
1 files changed, 100 insertions, 47 deletions
diff --git a/discover/boot.c b/discover/boot.c index 91fc46d..00507b7 100644 --- a/discover/boot.c +++ b/discover/boot.c @@ -25,6 +25,7 @@ #include "paths.h" #include "resource.h" #include "platform.h" +#include "sysinfo.h" #include <security/security.h> @@ -60,30 +61,50 @@ static void __attribute__((format(__printf__, 4, 5))) update_status( */ static int kexec_load(struct boot_task *boot_task) { + const char *load_args[] = {"-l", "-s"}; + const struct system_info *sysinfo; struct process *process; char *s_initrd = NULL; char *s_args = NULL; const char *argv[8]; char *s_dtb = NULL; const char **p; + char *err_buf; int result; + size_t i; + sysinfo = system_info_get(); boot_task->local_initrd_override = NULL; boot_task->local_dtb_override = NULL; boot_task->local_image_override = NULL; - if ((result = validate_boot_files(boot_task))) { - if (result == KEXEC_LOAD_DECRYPTION_FALURE) { - pb_log("%s: Aborting kexec due to" - " decryption failure\n", __func__); - } - if (result == KEXEC_LOAD_SIGNATURE_FAILURE) { - pb_log("%s: Aborting kexec due to signature" - " verification failure\n", __func__); + result = validate_boot_files(boot_task); + if (result) { + const char *msg; + + switch (result) { + case KEXEC_LOAD_DECRYPTION_FALURE: + msg = _("decryption failed"); + break; + case KEXEC_LOAD_SIGNATURE_FAILURE: + msg = _("signature verification failed"); + break; + case KEXEC_LOAD_SIG_SETUP_INVALID: + msg = _("invalid signature configuration"); + break; + default: + msg = _("unknown verification failure"); } - goto abort_kexec; + update_status(boot_task->status_fn, boot_task->status_arg, + STATUS_ERROR, + _("Boot verification failure: %s"), msg); + pb_log_fn("Aborting kexec due to verification failure: %s", + msg); + + validate_boot_files_cleanup(boot_task); + return result; } const char* local_initrd = (boot_task->local_initrd_override) ? @@ -93,20 +114,10 @@ static int kexec_load(struct boot_task *boot_task) const char* local_image = (boot_task->local_image_override) ? boot_task->local_image_override : boot_task->local_image; - process = process_create(boot_task); - if (!process) { - pb_log_fn("failed to create process\n"); - return -1; - } - - process->path = pb_system_apps.kexec; - process->argv = argv; - process->keep_stdout = true; - process->add_stderr = true; - + /* set up process arguments */ p = argv; *p++ = pb_system_apps.kexec; /* 1 */ - *p++ = "-l"; /* 2 */ + *p++ = NULL; /* 2; modified below */ if (pb_log_get_debug()) { *p++ = "--debug"; /* 3 */ @@ -134,21 +145,57 @@ static int kexec_load(struct boot_task *boot_task) *p++ = local_image; /* 7 */ *p++ = NULL; /* 8 */ - result = process_run_sync(process); - if (result) { - pb_log_fn("failed to run process\n"); - goto abort_kexec; - } + err_buf = NULL; - result = process->exit_status; + for (i = 0; i < ARRAY_SIZE(load_args); i++) { + /* our first argument is the action: -s or -l */ + argv[1] = load_args[i]; - if (result) { - pb_log_fn("failed: (%d)\n", result); - update_status(boot_task->status_fn, boot_task->status_arg, - STATUS_ERROR, "%s", process->stdout_buf); + /* if we're enforcing, we know a -l load will fail; skip */ + if (sysinfo->stb_os_enforcing && argv[1][1] == 'l') + continue; + + process = process_create(boot_task); + if (!process) { + result = -1; + pb_log_fn("failed to create process\n"); + continue; + } + + process->path = pb_system_apps.kexec; + process->argv = argv; + process->keep_stdout = true; + process->add_stderr = true; + + result = process_run_sync(process); + if (result) { + pb_log_fn("failed to run process\n"); + continue; + } + + result = 0; + + if (process_exit_ok(process)) + break; + + result = -1; + + if (process->stdout_len) + err_buf = talloc_strndup(boot_task, process->stdout_buf, + process->stdout_len); + + pb_log_fn("kexec load (%s) failed (rc %d): %s\n", argv[1], + WEXITSTATUS(process->exit_status), + err_buf ?: ""); + + process_release(process); } -abort_kexec: + if (result) + update_status(boot_task->status_fn, boot_task->status_arg, + STATUS_ERROR, _("kexec load failed: %s"), + err_buf ?: "(no output)"); + validate_boot_files_cleanup(boot_task); return result; @@ -401,6 +448,24 @@ static void cleanup_cancellations(struct boot_task *task, talloc_free(task); } +static bool preboot_check(struct boot_task *task) +{ + const char *local_image = (task->local_image_override) ? + task->local_image_override : task->local_image; + + char *preboot_check_err_msg = NULL; + bool preboot_check_ret = platform_preboot_check(local_image, + &preboot_check_err_msg); + + if (preboot_check_err_msg) { + update_status(task->status_fn, task->status_arg, + STATUS_ERROR, "%s", preboot_check_err_msg); + talloc_free(preboot_check_err_msg); + } + + return preboot_check_ret; +} + static void boot_process(struct load_url_result *result, void *data) { struct boot_task *task = data; @@ -424,25 +489,13 @@ static void boot_process(struct load_url_result *result, void *data) run_boot_hooks(task); + if (!preboot_check(task)) + return; + update_status(task->status_fn, task->status_arg, STATUS_INFO, _("Performing kexec load")); rc = kexec_load(task); - pb_log_fn("kexec_load returned %d\n", rc); - if (rc == KEXEC_LOAD_DECRYPTION_FALURE) { - update_status(task->status_fn, task->status_arg, - STATUS_ERROR, _("Decryption failed")); - } - else if (rc == KEXEC_LOAD_SIGNATURE_FAILURE) { - update_status(task->status_fn, task->status_arg, - STATUS_ERROR, - _("Signature verification failed")); - } - else if (rc == KEXEC_LOAD_SIG_SETUP_INVALID) { - update_status(task->status_fn, task->status_arg, - STATUS_ERROR, - _("Invalid signature configuration")); - } no_load: list_for_each_entry(&task->resources, resource, list) |