diff --git a/src/bootloaders/shim-systemd.c b/src/bootloaders/shim-systemd.c index 1503716..84326cb 100644 --- a/src/bootloaders/shim-systemd.c +++ b/src/bootloaders/shim-systemd.c @@ -18,6 +18,7 @@ #include "bootvar.h" #include "config.h" #include "files.h" +#include #include "nica/files.h" #include "systemd-class.h" @@ -183,31 +184,45 @@ static bool make_layout(const BootManager *manager) char *boot_root = boot_manager_get_boot_dir((BootManager *)manager); char path[PATH_MAX]; snprintf(path, PATH_MAX, "%s%s", boot_root, DST_DIR); - if (!nc_mkdir_p(path, 00755)) - return false; + if (!nc_mkdir_p(path, 00755)) { + goto fail; + } snprintf(path, PATH_MAX, "%s%s", boot_root, KERNEL_DST_DIR); - if (!nc_mkdir_p(path, 00755)) - return false; + if (!nc_mkdir_p(path, 00755)) { + goto fail; + } snprintf(path, PATH_MAX, "%s%s", boot_root, SYSTEMD_ENTRIES); - if (!nc_mkdir_p(path, 00755)) - return false; + if (!nc_mkdir_p(path, 00755)) { + goto fail; + } return true; +fail: + LOG_FATAL("Failed to make dir: %s", path); + return false; } static bool shim_systemd_install(const BootManager *manager) { char varname[9]; - if (!make_layout(manager)) + if (!make_layout(manager)) { + LOG_FATAL("Cannot create layout"); return false; + } - if (!copy_file_atomic(shim_src, shim_dst_host, 00644)) + if (!copy_file_atomic(shim_src, shim_dst_host, 00644)) { + LOG_FATAL("Cannot copy %s to %s", shim_src, shim_dst_host); return false; - if (!copy_file_atomic(systemd_src, systemd_dst_host, 00644)) + } + if (!copy_file_atomic(systemd_src, systemd_dst_host, 00644)) { + LOG_FATAL("Cannot copy %s to %s", systemd_src, systemd_dst_host); return false; + } - if (bootvar_create(BOOT_DIRECTORY, shim_dst_esp, varname, 9)) + if (bootvar_create(BOOT_DIRECTORY, shim_dst_esp, varname, 9)) { + LOG_FATAL("Cannot create EFI variable"); return false; + } return true; } @@ -248,9 +263,10 @@ static bool shim_systemd_init(const BootManager *manager) shim_src = string_printf("%s/%s", prefix, SHIM_SRC); systemd_src = string_printf("%s/%s", prefix, SYSTEMD_SRC); - /* SHIM_DST and SYSTEMD_DST are defined with leading '/' */ boot_root = strdup(boot_manager_get_boot_dir((BootManager *)manager)); len = strlen(boot_root); + /* SHIM_DST and SYSTEMD_DST are defined with leading '/', take extra + * care to produce clean paths. */ if (len > 0 && boot_root[len - 1] == '/') boot_root[len - 1] = '\0'; shim_dst_host = string_printf("%s%s", boot_root, SHIM_DST); diff --git a/src/lib/bootvar.c b/src/lib/bootvar.c index 9c8a7b8..ba06816 100644 --- a/src/lib/bootvar.c +++ b/src/lib/bootvar.c @@ -11,6 +11,8 @@ #define _GNU_SOURCE +#include "bootvar.h" + #include /* Workaround for using --std=c11 in CBM. Provide "relaxed" defines which efivar * expects. */ @@ -21,10 +23,12 @@ #include #include #include -#include #include +#include #include #include +#include +#include #include #include #include @@ -107,6 +111,10 @@ static int bootvar_read_boot_recs(void) } i++; } + if (res < 0) { + LOG_FATAL("efi_get_next_variable_name() failed: %s", strerror(errno)); + return -EBOOT_VAR_ERR; + } boot_recs_cnt = i; return 0; } @@ -125,14 +133,16 @@ static int bootvar_push_to_boot_order(boot_rec_t *rec) int found = 0; if (!rec || !rec->name) - return -1; + return -EBOOT_VAR_ERR; if (efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", (uint8_t **)&boot_order, &boot_order_size, - &boot_order_attrs)) - return -1; + &boot_order_attrs)) { + LOG_FATAL("efi_get_variable() failed: %s", strerror(errno)); + return -EBOOT_VAR_ERR; + } sscanf(rec->name, "Boot%04hX", &number); @@ -171,8 +181,10 @@ static int bootvar_push_to_boot_order(boot_rec_t *rec) (uint8_t *)new_boot_order, new_boot_order_size, boot_order_attrs, - 0644)) - return -1; + 0644)) { + LOG_FATAL("efi_set_variable() failed: %s", strerror(errno)); + return -EBOOT_VAR_ERR; + } return 0; } @@ -231,8 +243,10 @@ static boot_rec_t *bootvar_find_boot_rec(uint8_t *data, size_t size) return NULL; do { - if (efi_get_variable(EFI_GLOBAL_GUID, c->name, &cdata, &csize, &cattr) < 0) + if (efi_get_variable(EFI_GLOBAL_GUID, c->name, &cdata, &csize, &cattr) < 0) { + LOG_ERROR("efi_get_variable() failed: %s", strerror(errno)); continue; + } if (csize == size && !memcmp(cdata, data, csize)) { res = c; break; @@ -258,27 +272,55 @@ static int bootvar_get_part_info(const char *path, part_info_t *pi) struct stat st; dev_t disk_dev; char disk_path[PATH_MAX]; + const char *part_type; - if (stat(path, &st)) - return -1; + if (stat(path, &st)) { + LOG_FATAL("stat() failed on %s: %s", path, strerror(errno)); + return -EBOOT_VAR_ERR; + } strcpy(disk_path, "/dev/"); - if (blkid_devno_to_wholedisk(st.st_dev, disk_path + 5, PATH_MAX - 5, &disk_dev)) - return -1; + if (blkid_devno_to_wholedisk(st.st_dev, disk_path + 5, PATH_MAX - 5, &disk_dev)) { + LOG_FATAL("blkid_devno_to_wholedisk() error"); + return -EBOOT_VAR_ERR; + } - if (!(probe = blkid_new_probe_from_filename(disk_path))) - return -1; + if (!(probe = blkid_new_probe_from_filename(disk_path))) { + LOG_FATAL("blkid_new_probe_from_filename() error"); + return -EBOOT_VAR_ERR; + } - if (blkid_probe_enable_partitions(probe, 1)) - return -1; + if (blkid_probe_enable_partitions(probe, 1)) { + LOG_FATAL("blkid_probe_enable_partitions() error"); + return -EBOOT_VAR_ERR; + } - if (!(parts = blkid_probe_get_partitions(probe))) - return -1; - part = blkid_partlist_devno_to_partition(parts, st.st_dev); + if (!(parts = blkid_probe_get_partitions(probe))) { + LOG_FATAL("blkid_probe_get_partitions() error"); + return -EBOOT_VAR_ERR; + } + + if (!(part = blkid_partlist_devno_to_partition(parts, st.st_dev))) { + LOG_FATAL("blkid_partlist_devno_to_partition() error"); + return -EBOOT_VAR_ERR; + } + + if ((pi->part_no = blkid_partition_get_partno(part)) < 0) { + LOG_FATAL("blkid_partition_get_partno() error"); + return -EBOOT_VAR_ERR; + } + + part_type = blkid_partition_get_type_string(part); + if (!part_type) { + LOG_FATAL("blkid_partition_get_type_string() returned NULL"); + return -EBOOT_VAR_ERR; + } else if (strlen(part_type) != 36) { + LOG_FATAL("partition type does not seem to be a GUID: %s", part_type); + return -EBOOT_VAR_ERR; + } snprintf(pi->disk_path, strlen(disk_path) + 1, "%s", disk_path); - pi->part_no = blkid_partition_get_partno(part); - snprintf(pi->part_type, 36 + 1, "%s", blkid_partition_get_type_string(part)); + snprintf(pi->part_type, 36 + 1, "%s", part_type); blkid_free_probe(probe); @@ -302,8 +344,10 @@ static boot_rec_t *bootvar_add_boot_rec(uint8_t *data, size_t len) return NULL; if (snprintf(name, 9, "Boot%04X", slot) > 8) return NULL; - if (efi_set_variable(EFI_GLOBAL_GUID, name, data, len, attr, 0644) < 0) + if (efi_set_variable(EFI_GLOBAL_GUID, name, data, len, attr, 0644) < 0) { + LOG_FATAL("efi_set_variable() failed: %s", strerror(errno)); return NULL; + } /* re-read the records and find the variable that was just created. */ if (bootvar_read_boot_recs() < 0) return NULL; @@ -339,8 +383,10 @@ int bootvar_create(const char *esp_mount_path, const char *bootloader_esp_path, pi.part_no, bootloader_esp_path, EFIBOOT_ABBREV_HD); - if (len < 0) - return -1; + if (len < 0) { + LOG_FATAL("efi_generate_file_device_path_from_esp() failed: %s", strerror(errno)); + return -EBOOT_VAR_ERR; + } len = efi_loadopt_create(data, BOOT_VAR_MAX, @@ -350,20 +396,25 @@ int bootvar_create(const char *esp_mount_path, const char *bootloader_esp_path, (unsigned char *)"Linux bootloader", NULL, 0); - if (len < 0) - return -1; + if (len < 0) { + LOG_FATAL("efi_loadopt_create() failed: %s", strerror(errno)); + return -EBOOT_VAR_ERR; + } rec = bootvar_add_boot_rec(data, (size_t)len); if (!rec) - return -1; + return -EBOOT_VAR_ERR; if (bootvar_push_to_boot_order(rec)) - return -1; + return -EBOOT_VAR_ERR; if (varname && size) { size_t len = strlen(rec->name); - if (len < size) + if (len < size) { snprintf(varname, len + 1, "%s", rec->name); + } else { + LOG_ERROR("%lu bytes is not enough. Need %lu.", size, len); + } } return 0; @@ -372,9 +423,9 @@ int bootvar_create(const char *esp_mount_path, const char *bootloader_esp_path, int bootvar_init(void) { if (efi_variables_supported() < 0) - return -1; + return -EBOOT_VAR_NOSUP; if (bootvar_read_boot_recs() < 0) - return -1; + return -EBOOT_VAR_ERR; return 0; } diff --git a/src/lib/bootvar.h b/src/lib/bootvar.h index 6df8ea7..b245ea4 100644 --- a/src/lib/bootvar.h +++ b/src/lib/bootvar.h @@ -11,6 +11,9 @@ #include +#define EBOOT_VAR_ERR 1 /* general error */ +#define EBOOT_VAR_NOSUP 127 /* EFI vars not supported */ + int bootvar_init(void); void bootvar_destroy(void); int bootvar_create(const char *, const char *, char *, size_t);