efi: introduce PeSectionVector structure, and use it for referencing PE sections
This commit is contained in:
+25
-13
@@ -1855,23 +1855,24 @@ static void generate_boot_entry_titles(Config *config) {
|
||||
}
|
||||
|
||||
static bool is_sd_boot(EFI_FILE *root_dir, const char16_t *loader_path) {
|
||||
EFI_STATUS err;
|
||||
static const char * const sections[] = {
|
||||
".sdmagic",
|
||||
NULL
|
||||
};
|
||||
size_t offset = 0, size = 0, read;
|
||||
_cleanup_free_ char *content = NULL;
|
||||
PeSectionVector vector = {};
|
||||
EFI_STATUS err;
|
||||
size_t read;
|
||||
|
||||
assert(root_dir);
|
||||
assert(loader_path);
|
||||
|
||||
err = pe_file_locate_sections(root_dir, loader_path, sections, &offset, &size);
|
||||
if (err != EFI_SUCCESS || size != sizeof(SD_MAGIC))
|
||||
err = pe_file_locate_sections(root_dir, loader_path, sections, &vector);
|
||||
if (err != EFI_SUCCESS || vector.size != sizeof(SD_MAGIC))
|
||||
return false;
|
||||
|
||||
err = file_read(root_dir, loader_path, offset, size, &content, &read);
|
||||
if (err != EFI_SUCCESS || size != read)
|
||||
err = file_read(root_dir, loader_path, vector.file_offset, vector.size, &content, &read);
|
||||
if (err != EFI_SUCCESS || vector.size != read)
|
||||
return false;
|
||||
|
||||
return memcmp(content, SD_MAGIC, sizeof(SD_MAGIC)) == 0;
|
||||
@@ -2104,7 +2105,7 @@ static void config_load_type2_entries(
|
||||
_SECTION_MAX,
|
||||
};
|
||||
|
||||
static const char * const sections[_SECTION_MAX + 1] = {
|
||||
static const char * const section_names[_SECTION_MAX + 1] = {
|
||||
[SECTION_CMDLINE] = ".cmdline",
|
||||
[SECTION_OSREL] = ".osrel",
|
||||
NULL,
|
||||
@@ -2114,8 +2115,9 @@ static void config_load_type2_entries(
|
||||
*os_image_version = NULL, *os_version = NULL, *os_version_id = NULL, *os_build_id = NULL;
|
||||
const char16_t *good_name, *good_version, *good_sort_key;
|
||||
_cleanup_free_ char *content = NULL;
|
||||
size_t offs[_SECTION_MAX] = {}, szs[_SECTION_MAX] = {}, pos = 0;
|
||||
PeSectionVector sections[_SECTION_MAX] = {};
|
||||
char *line, *key, *value;
|
||||
size_t pos = 0;
|
||||
|
||||
err = readdir(linux_dir, &f, &f_size);
|
||||
if (err != EFI_SUCCESS || !f)
|
||||
@@ -2131,11 +2133,16 @@ static void config_load_type2_entries(
|
||||
continue;
|
||||
|
||||
/* look for .osrel and .cmdline sections in the .efi binary */
|
||||
err = pe_file_locate_sections(linux_dir, f->FileName, sections, offs, szs);
|
||||
if (err != EFI_SUCCESS || szs[SECTION_OSREL] == 0)
|
||||
err = pe_file_locate_sections(linux_dir, f->FileName, section_names, sections);
|
||||
if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + SECTION_OSREL))
|
||||
continue;
|
||||
|
||||
err = file_read(linux_dir, f->FileName, offs[SECTION_OSREL], szs[SECTION_OSREL], &content, NULL);
|
||||
err = file_read(linux_dir,
|
||||
f->FileName,
|
||||
sections[SECTION_OSREL].file_offset,
|
||||
sections[SECTION_OSREL].size,
|
||||
&content,
|
||||
NULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
@@ -2206,14 +2213,19 @@ static void config_load_type2_entries(
|
||||
config_add_entry(config, entry);
|
||||
boot_entry_parse_tries(entry, u"\\EFI\\Linux", f->FileName, u".efi");
|
||||
|
||||
if (szs[SECTION_CMDLINE] == 0)
|
||||
if (!PE_SECTION_VECTOR_IS_SET(sections + SECTION_CMDLINE))
|
||||
continue;
|
||||
|
||||
content = mfree(content);
|
||||
|
||||
/* read the embedded cmdline file */
|
||||
size_t cmdline_len;
|
||||
err = file_read(linux_dir, f->FileName, offs[SECTION_CMDLINE], szs[SECTION_CMDLINE], &content, &cmdline_len);
|
||||
err = file_read(linux_dir,
|
||||
f->FileName,
|
||||
sections[SECTION_CMDLINE].file_offset,
|
||||
sections[SECTION_CMDLINE].size,
|
||||
&content,
|
||||
&cmdline_len);
|
||||
if (err == EFI_SUCCESS) {
|
||||
entry->options = xstrn8_to_16(content, cmdline_len);
|
||||
mangle_stub_cmdline(entry->options);
|
||||
|
||||
+72
-35
@@ -101,7 +101,7 @@ typedef struct PeOptionalHeader {
|
||||
} _packed_ PeOptionalHeader;
|
||||
|
||||
typedef struct PeFileHeader {
|
||||
uint8_t Magic[4];
|
||||
uint8_t Magic[4];
|
||||
CoffFileHeader FileHeader;
|
||||
PeOptionalHeader OptionalHeader;
|
||||
} _packed_ PeFileHeader;
|
||||
@@ -175,48 +175,78 @@ static bool pe_section_name_equal(const char *a, const char *b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void locate_sections(
|
||||
static void pe_locate_sections(
|
||||
const PeSectionHeader section_table[],
|
||||
size_t n_table,
|
||||
size_t n_section_table,
|
||||
const char * const sections[],
|
||||
size_t *offsets,
|
||||
size_t *sizes,
|
||||
bool in_memory) {
|
||||
size_t validate_base,
|
||||
PeSectionVector *ret_sections) {
|
||||
|
||||
assert(section_table);
|
||||
assert(section_table || n_section_table == 0);
|
||||
assert(sections);
|
||||
assert(offsets);
|
||||
assert(sizes);
|
||||
assert(ret_sections);
|
||||
|
||||
for (size_t i = 0; i < n_table; i++) {
|
||||
const PeSectionHeader *sect = section_table + i;
|
||||
/* Searches for the sections listed in 'sections[]' within the section table. Validates the resulted
|
||||
* data. If 'validate_base' is non-zero also takes base offset when loaded into memory into account for
|
||||
* qchecking for overflows. */
|
||||
|
||||
for (size_t j = 0; sections[j]; j++) {
|
||||
if (!pe_section_name_equal((const char*) sect->Name, sections[j]))
|
||||
for (size_t i = 0; sections[i]; i++)
|
||||
FOREACH_ARRAY(j, section_table, n_section_table) {
|
||||
|
||||
if (!pe_section_name_equal((const char*) j->Name, sections[i]))
|
||||
continue;
|
||||
|
||||
offsets[j] = in_memory ? sect->VirtualAddress : sect->PointerToRawData;
|
||||
sizes[j] = sect->VirtualSize;
|
||||
/* Overflow check: ignore sections that are impossibly large, relative to the file
|
||||
* address for the section. */
|
||||
size_t size_max = SIZE_MAX - j->PointerToRawData;
|
||||
if ((size_t) j->VirtualSize > size_max)
|
||||
continue;
|
||||
|
||||
/* Overflow check: ignore sections that are impossibly large, given the virtual
|
||||
* address for the section */
|
||||
size_max = SIZE_MAX - j->VirtualAddress;
|
||||
if (j->VirtualSize > size_max)
|
||||
continue;
|
||||
|
||||
/* 2nd overflow check: ignore sections that are impossibly large also taking the
|
||||
* loaded base into account. */
|
||||
if (validate_base != 0) {
|
||||
if (validate_base > size_max)
|
||||
continue;
|
||||
size_max -= validate_base;
|
||||
|
||||
if (j->VirtualAddress > size_max)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this time, the sizes and offsets have been validated. Store them away */
|
||||
ret_sections[i] = (PeSectionVector) {
|
||||
.size = j->VirtualSize,
|
||||
.file_offset = j->PointerToRawData,
|
||||
.memory_offset = j->VirtualAddress,
|
||||
};
|
||||
|
||||
/* First matching section wins, ignore the rest */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) {
|
||||
size_t addr = 0, size = 0;
|
||||
static const char *sections[] = { ".compat", NULL };
|
||||
PeSectionVector vector = {};
|
||||
|
||||
/* The kernel may provide alternative PE entry points for different PE architectures. This allows
|
||||
* booting a 64-bit kernel on 32-bit EFI that is otherwise running on a 64-bit CPU. The locations of any
|
||||
* such compat entry points are located in a special PE section. */
|
||||
|
||||
locate_sections((const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)),
|
||||
pe_locate_sections(
|
||||
(const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)),
|
||||
pe->FileHeader.NumberOfSections,
|
||||
sections,
|
||||
&addr,
|
||||
&size,
|
||||
/*in_memory=*/true);
|
||||
PTR_TO_SIZE(dos),
|
||||
&vector);
|
||||
|
||||
if (size == 0)
|
||||
if (vector.size == 0) /* not found */
|
||||
return 0;
|
||||
|
||||
typedef struct {
|
||||
@@ -226,6 +256,8 @@ static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const
|
||||
uint32_t entry_point;
|
||||
} _packed_ LinuxPeCompat1;
|
||||
|
||||
size_t addr = vector.memory_offset, size = vector.size;
|
||||
|
||||
while (size >= sizeof(LinuxPeCompat1) && addr % alignof(LinuxPeCompat1) == 0) {
|
||||
LinuxPeCompat1 *compat = (LinuxPeCompat1 *) ((uint8_t *) dos + addr);
|
||||
|
||||
@@ -274,15 +306,18 @@ EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS pe_memory_locate_sections(const void *base, const char * const sections[], size_t *addrs, size_t *sizes) {
|
||||
EFI_STATUS pe_memory_locate_sections(
|
||||
const void *base,
|
||||
const char* const sections[],
|
||||
PeSectionVector *ret_sections) {
|
||||
|
||||
const DosFileHeader *dos;
|
||||
const PeFileHeader *pe;
|
||||
size_t offset;
|
||||
|
||||
assert(base);
|
||||
assert(sections);
|
||||
assert(addrs);
|
||||
assert(sizes);
|
||||
assert(ret_sections);
|
||||
|
||||
dos = (const DosFileHeader *) base;
|
||||
if (!verify_dos(dos))
|
||||
@@ -293,12 +328,12 @@ EFI_STATUS pe_memory_locate_sections(const void *base, const char * const sectio
|
||||
return EFI_LOAD_ERROR;
|
||||
|
||||
offset = section_table_offset(dos, pe);
|
||||
locate_sections((PeSectionHeader *) ((uint8_t *) base + offset),
|
||||
pe_locate_sections(
|
||||
(const PeSectionHeader *) ((const uint8_t *) base + offset),
|
||||
pe->FileHeader.NumberOfSections,
|
||||
sections,
|
||||
addrs,
|
||||
sizes,
|
||||
/*in_memory=*/true);
|
||||
PTR_TO_SIZE(base),
|
||||
ret_sections);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -307,8 +342,7 @@ EFI_STATUS pe_file_locate_sections(
|
||||
EFI_FILE *dir,
|
||||
const char16_t *path,
|
||||
const char * const sections[],
|
||||
size_t *offsets,
|
||||
size_t *sizes) {
|
||||
PeSectionVector *ret_sections) {
|
||||
_cleanup_free_ PeSectionHeader *section_table = NULL;
|
||||
_cleanup_(file_closep) EFI_FILE *handle = NULL;
|
||||
DosFileHeader dos;
|
||||
@@ -319,8 +353,7 @@ EFI_STATUS pe_file_locate_sections(
|
||||
assert(dir);
|
||||
assert(path);
|
||||
assert(sections);
|
||||
assert(offsets);
|
||||
assert(sizes);
|
||||
assert(ret_sections);
|
||||
|
||||
err = dir->Open(dir, &handle, (char16_t *) path, EFI_FILE_MODE_READ, 0ULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
@@ -366,8 +399,12 @@ EFI_STATUS pe_file_locate_sections(
|
||||
if (len != section_table_len)
|
||||
return EFI_LOAD_ERROR;
|
||||
|
||||
locate_sections(section_table, pe.FileHeader.NumberOfSections,
|
||||
sections, offsets, sizes, /*in_memory=*/false);
|
||||
pe_locate_sections(
|
||||
section_table,
|
||||
pe.FileHeader.NumberOfSections,
|
||||
sections,
|
||||
/* validate_base= */ 0, /* don't validate base */
|
||||
ret_sections);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
+14
-4
@@ -3,17 +3,27 @@
|
||||
|
||||
#include "efi.h"
|
||||
|
||||
/* This is a subset of the full PE section header structure, with validated values, and without
|
||||
* the noise. */
|
||||
typedef struct PeSectionVector {
|
||||
size_t size;
|
||||
size_t memory_offset; /* Offset in memory, relative to base address */
|
||||
uint64_t file_offset; /* Offset on disk, relative to beginning of file */
|
||||
} PeSectionVector;
|
||||
|
||||
static inline bool PE_SECTION_VECTOR_IS_SET(const PeSectionVector *v) {
|
||||
return v && v->size != 0;
|
||||
}
|
||||
|
||||
EFI_STATUS pe_memory_locate_sections(
|
||||
const void *base,
|
||||
const char * const sections[],
|
||||
size_t *addrs,
|
||||
size_t *sizes);
|
||||
PeSectionVector *ret_sections);
|
||||
|
||||
EFI_STATUS pe_file_locate_sections(
|
||||
EFI_FILE *dir,
|
||||
const char16_t *path,
|
||||
const char * const sections[],
|
||||
size_t *offsets,
|
||||
size_t *sizes);
|
||||
PeSectionVector *ret_sections);
|
||||
|
||||
EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address);
|
||||
|
||||
+53
-45
@@ -413,7 +413,7 @@ static EFI_STATUS load_addons(
|
||||
sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) strcmp16);
|
||||
|
||||
for (size_t i = 0; i < n_items; i++) {
|
||||
size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
|
||||
PeSectionVector sections[ELEMENTSOF(unified_sections)] = {};
|
||||
_cleanup_free_ EFI_DEVICE_PATH *addon_path = NULL;
|
||||
_cleanup_(unload_imagep) EFI_HANDLE addon = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_addon = NULL;
|
||||
@@ -441,9 +441,10 @@ static EFI_STATUS load_addons(
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Failed to find protocol in %ls: %m", items[i]);
|
||||
|
||||
err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, addrs, szs);
|
||||
err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, sections);
|
||||
if (err != EFI_SUCCESS ||
|
||||
(szs[UNIFIED_SECTION_CMDLINE] == 0 && szs[UNIFIED_SECTION_DTB] == 0)) {
|
||||
(!PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE) &&
|
||||
!PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB))) {
|
||||
if (err == EFI_SUCCESS)
|
||||
err = EFI_NOT_FOUND;
|
||||
log_error_status(err,
|
||||
@@ -453,38 +454,38 @@ static EFI_STATUS load_addons(
|
||||
}
|
||||
|
||||
/* We want to enforce that addons are not UKIs, i.e.: they must not embed a kernel. */
|
||||
if (szs[UNIFIED_SECTION_LINUX] > 0) {
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_LINUX)) {
|
||||
log_error_status(EFI_INVALID_PARAMETER, "%ls is a UKI, not an addon, ignoring: %m", items[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Also enforce that, in case it is specified, .uname matches as a quick way to allow
|
||||
* enforcing compatibility with a specific UKI only */
|
||||
if (uname && szs[UNIFIED_SECTION_UNAME] > 0 &&
|
||||
if (uname && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UNAME) &&
|
||||
!strneq8(uname,
|
||||
(char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_UNAME],
|
||||
szs[UNIFIED_SECTION_UNAME])) {
|
||||
(char *)loaded_addon->ImageBase + sections[UNIFIED_SECTION_UNAME].memory_offset,
|
||||
sections[UNIFIED_SECTION_UNAME].size)) {
|
||||
log_error(".uname mismatch between %ls and UKI, ignoring", items[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret_cmdline && szs[UNIFIED_SECTION_CMDLINE] > 0) {
|
||||
if (ret_cmdline && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE)) {
|
||||
_cleanup_free_ char16_t *tmp = TAKE_PTR(cmdline),
|
||||
*extra16 = xstrn8_to_16((char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_CMDLINE],
|
||||
szs[UNIFIED_SECTION_CMDLINE]);
|
||||
*extra16 = xstrn8_to_16((char *)loaded_addon->ImageBase + sections[UNIFIED_SECTION_CMDLINE].memory_offset,
|
||||
sections[UNIFIED_SECTION_CMDLINE].size);
|
||||
cmdline = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", extra16);
|
||||
}
|
||||
|
||||
if (ret_dt_bases && szs[UNIFIED_SECTION_DTB] > 0) {
|
||||
if (ret_dt_bases && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) {
|
||||
dt_sizes = xrealloc(dt_sizes,
|
||||
n_dt * sizeof(size_t),
|
||||
(n_dt + 1) * sizeof(size_t));
|
||||
dt_sizes[n_dt] = szs[UNIFIED_SECTION_DTB];
|
||||
dt_sizes[n_dt] = sections[UNIFIED_SECTION_DTB].size;
|
||||
|
||||
dt_bases = xrealloc(dt_bases,
|
||||
n_dt * sizeof(void *),
|
||||
(n_dt + 1) * sizeof(void *));
|
||||
dt_bases[n_dt] = xmemdup((uint8_t*)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_DTB],
|
||||
dt_bases[n_dt] = xmemdup((uint8_t*)loaded_addon->ImageBase + sections[UNIFIED_SECTION_DTB].memory_offset,
|
||||
dt_sizes[n_dt]);
|
||||
|
||||
dt_filenames = xrealloc(dt_filenames,
|
||||
@@ -515,11 +516,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
|
||||
char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
|
||||
_cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
|
||||
size_t linux_size, initrd_size, ucode_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0;
|
||||
EFI_PHYSICAL_ADDRESS linux_base, initrd_base, ucode_base, dt_base;
|
||||
size_t linux_size, initrd_size = 0, ucode_size = 0, dt_size = 0, n_dts_addons_global = 0, n_dts_addons_uki = 0;
|
||||
EFI_PHYSICAL_ADDRESS linux_base, initrd_base = 0, ucode_base = 0, dt_base = 0;
|
||||
_cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
|
||||
PeSectionVector sections[ELEMENTSOF(unified_sections)] = {};
|
||||
_cleanup_free_ char16_t *cmdline = NULL, *cmdline_addons_global = NULL, *cmdline_addons_uki = NULL;
|
||||
int sections_measured = -1, parameters_measured = -1, sysext_measured = -1, confext_measured = -1;
|
||||
_cleanup_free_ char *uname = NULL;
|
||||
@@ -541,8 +542,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
(void) process_random_seed(esp_dir);
|
||||
}
|
||||
|
||||
err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, addrs, szs);
|
||||
if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) {
|
||||
err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, sections);
|
||||
if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_LINUX)) {
|
||||
if (err == EFI_SUCCESS)
|
||||
err = EFI_NOT_FOUND;
|
||||
return log_error_status(err, "Unable to locate embedded .linux section: %m");
|
||||
@@ -553,9 +554,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
CLEANUP_ARRAY(dt_filenames_addons_global, n_dts_addons_global, dt_filenames_free);
|
||||
CLEANUP_ARRAY(dt_filenames_addons_uki, n_dts_addons_uki, dt_filenames_free);
|
||||
|
||||
if (szs[UNIFIED_SECTION_UNAME] > 0)
|
||||
uname = xstrndup8((char *)loaded_image->ImageBase + addrs[UNIFIED_SECTION_UNAME],
|
||||
szs[UNIFIED_SECTION_UNAME]);
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UNAME))
|
||||
uname = xstrndup8((char *)loaded_image->ImageBase + sections[UNIFIED_SECTION_UNAME].memory_offset,
|
||||
sections[UNIFIED_SECTION_UNAME].size);
|
||||
|
||||
/* Now that we have the UKI sections loaded, also load global first and then local (per-UKI)
|
||||
* addons. The data is loaded at once, and then used later. */
|
||||
@@ -597,7 +598,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
if (!unified_section_measure(section)) /* shall not measure? */
|
||||
continue;
|
||||
|
||||
if (szs[section] == 0) /* not found */
|
||||
if (!PE_SECTION_VECTOR_IS_SET(sections + section)) /* not found */
|
||||
continue;
|
||||
|
||||
/* First measure the name of the section */
|
||||
@@ -614,11 +615,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
m = false;
|
||||
(void) tpm_log_ipl_event_ascii(
|
||||
TPM2_PCR_KERNEL_BOOT,
|
||||
POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[section],
|
||||
szs[section],
|
||||
POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[section].memory_offset,
|
||||
sections[section].size,
|
||||
unified_sections[section],
|
||||
&m);
|
||||
|
||||
combine_measured_flag(§ions_measured, m);
|
||||
}
|
||||
|
||||
@@ -628,9 +628,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelImage", TPM2_PCR_KERNEL_BOOT, 0);
|
||||
|
||||
/* Show splash screen as early as possible */
|
||||
graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH]);
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_SPLASH))
|
||||
graphics_splash((const uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_SPLASH].memory_offset, sections[UNIFIED_SECTION_SPLASH].size);
|
||||
|
||||
if (use_load_options(image, loaded_image, szs[UNIFIED_SECTION_CMDLINE] > 0, &cmdline)) {
|
||||
if (use_load_options(image, loaded_image, /* have_cmdline= */ PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE), &cmdline)) {
|
||||
/* Let's measure the passed kernel command line into the TPM. Note that this possibly
|
||||
* duplicates what we already did in the boot menu, if that was already used. However, since
|
||||
* we want the boot menu to support an EFI binary, and want to this stub to be usable from
|
||||
@@ -638,10 +639,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
m = false;
|
||||
(void) tpm_log_load_options(cmdline, &m);
|
||||
combine_measured_flag(¶meters_measured, m);
|
||||
} else if (szs[UNIFIED_SECTION_CMDLINE] > 0) {
|
||||
} else if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE)) {
|
||||
cmdline = xstrn8_to_16(
|
||||
(char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE],
|
||||
szs[UNIFIED_SECTION_CMDLINE]);
|
||||
(char *) loaded_image->ImageBase + sections[UNIFIED_SECTION_CMDLINE].memory_offset,
|
||||
sections[UNIFIED_SECTION_CMDLINE].size);
|
||||
mangle_stub_cmdline(cmdline);
|
||||
}
|
||||
|
||||
@@ -727,8 +728,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
&m) == EFI_SUCCESS)
|
||||
combine_measured_flag(&confext_measured, m);
|
||||
|
||||
dt_size = szs[UNIFIED_SECTION_DTB];
|
||||
dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0;
|
||||
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) {
|
||||
dt_size = sections[UNIFIED_SECTION_DTB].size;
|
||||
dt_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_DTB].memory_offset;
|
||||
}
|
||||
|
||||
/* First load the base device tree, then fix it up using addons - global first, then per-UKI. */
|
||||
if (dt_size > 0) {
|
||||
@@ -767,10 +771,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
* is not measured, neither as raw section (see above), nor as cpio (here), because it is the
|
||||
* signature of expected PCR values, i.e. its input are PCR measurements, and hence it shouldn't
|
||||
* itself be input for PCR measurements. */
|
||||
if (szs[UNIFIED_SECTION_PCRSIG] > 0)
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_PCRSIG))
|
||||
(void) pack_cpio_literal(
|
||||
(uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRSIG],
|
||||
szs[UNIFIED_SECTION_PCRSIG],
|
||||
(uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_PCRSIG].memory_offset,
|
||||
sections[UNIFIED_SECTION_PCRSIG].size,
|
||||
".extra",
|
||||
u"tpm2-pcr-signature.json",
|
||||
/* dir_mode= */ 0555,
|
||||
@@ -785,10 +789,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
* a cpio and also pass it to the kernel, so that it can be read from
|
||||
* /.extra/tpm2-pcr-public-key.pem. This section is already measure above, hence we won't measure the
|
||||
* cpio. */
|
||||
if (szs[UNIFIED_SECTION_PCRPKEY] > 0)
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_PCRPKEY))
|
||||
(void) pack_cpio_literal(
|
||||
(uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRPKEY],
|
||||
szs[UNIFIED_SECTION_PCRPKEY],
|
||||
(uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_PCRPKEY].memory_offset,
|
||||
sections[UNIFIED_SECTION_PCRPKEY].size,
|
||||
".extra",
|
||||
u"tpm2-pcr-public-key.pem",
|
||||
/* dir_mode= */ 0555,
|
||||
@@ -799,14 +803,18 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
&pcrpkey_initrd_size,
|
||||
/* ret_measured= */ NULL);
|
||||
|
||||
linux_size = szs[UNIFIED_SECTION_LINUX];
|
||||
linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_LINUX];
|
||||
linux_size = sections[UNIFIED_SECTION_LINUX].size;
|
||||
linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_LINUX].memory_offset;
|
||||
|
||||
initrd_size = szs[UNIFIED_SECTION_INITRD];
|
||||
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0;
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_INITRD)) {
|
||||
initrd_size = sections[UNIFIED_SECTION_INITRD].size;
|
||||
initrd_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_INITRD].memory_offset;
|
||||
}
|
||||
|
||||
ucode_size = szs[UNIFIED_SECTION_UCODE];
|
||||
ucode_base = ucode_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_UCODE] : 0;
|
||||
if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UCODE)) {
|
||||
ucode_size = sections[UNIFIED_SECTION_UCODE].size;
|
||||
ucode_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_UCODE].memory_offset;
|
||||
}
|
||||
|
||||
_cleanup_pages_ Pages initrd_pages = {};
|
||||
if (ucode_base || credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
|
||||
@@ -857,4 +865,4 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
return err;
|
||||
}
|
||||
|
||||
DEFINE_EFI_MAIN_FUNCTION(run, "systemd-stub", /*wait_for_debugger=*/false);
|
||||
DEFINE_EFI_MAIN_FUNCTION(run, "systemd-stub", /* wait_for_debugger= */ false);
|
||||
|
||||
Reference in New Issue
Block a user