From acb6041c669c45905a9004ccbef08aef89d4d629 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sun, 13 Mar 2022 17:22:04 +0100 Subject: [PATCH] misc: Bug fixes Co-authored-by: pitust --- common/lib/elf.c | 55 +++++++++++++++++++++++----------------- common/protos/stivale2.c | 6 +++-- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/common/lib/elf.c b/common/lib/elf.c index 4eb6e2f0..ceefb352 100644 --- a/common/lib/elf.c +++ b/common/lib/elf.c @@ -120,7 +120,7 @@ static bool elf64_is_relocatable(uint8_t *elf, struct elf64_hdr *hdr) { // Find DYN segment for (uint16_t i = 0; i < hdr->ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr->phoff + i * sizeof(struct elf64_phdr)), + memcpy(&phdr, elf + (hdr->phoff + i * hdr->phdr_size), sizeof(struct elf64_phdr)); if (phdr.p_type == PT_DYNAMIC) @@ -134,7 +134,7 @@ static int elf64_apply_relocations(uint8_t *elf, struct elf64_hdr *hdr, void *bu // Find DYN segment for (uint16_t i = 0; i < hdr->ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr->phoff + i * sizeof(struct elf64_phdr)), + memcpy(&phdr, elf + (hdr->phoff + i * hdr->phdr_size), sizeof(struct elf64_phdr)); if (phdr.p_type != PT_DYNAMIC) @@ -172,7 +172,7 @@ static int elf64_apply_relocations(uint8_t *elf, struct elf64_hdr *hdr, void *bu for (uint16_t j = 0; j < hdr->ph_num; j++) { struct elf64_phdr _phdr; - memcpy(&_phdr, elf + (hdr->phoff + j * sizeof(struct elf64_phdr)), + memcpy(&_phdr, elf + (hdr->phoff + j * hdr->phdr_size), sizeof(struct elf64_phdr)); if (_phdr.p_vaddr <= rela_offset && _phdr.p_vaddr + _phdr.p_filesz > rela_offset) { @@ -236,7 +236,7 @@ int elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limi } struct elf64_shdr shstrtab; - memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * sizeof(struct elf64_shdr)), + memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * hdr.shdr_size), sizeof(struct elf64_shdr)); char *names = ext_mem_alloc(shstrtab.sh_size); @@ -246,8 +246,8 @@ int elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limi for (uint16_t i = 0; i < hdr.sh_num; i++) { struct elf64_shdr section; - memcpy(§ion, elf + (hdr.shoff + i * sizeof(struct elf64_shdr)), - sizeof(struct elf64_shdr)); + memcpy(§ion, elf + (hdr.shoff + i * hdr.shdr_size), + sizeof(struct elf64_shdr)); if (!strcmp(&names[section.sh_name], name)) { if (section.sh_size > limit) { @@ -330,8 +330,8 @@ int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limi } struct elf32_shdr shstrtab; - memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * sizeof(struct elf32_shdr)), - sizeof(struct elf32_shdr)); + memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * hdr.shdr_size), + sizeof(struct elf32_shdr)); char *names = ext_mem_alloc(shstrtab.sh_size); memcpy(names, elf + (shstrtab.sh_offset), shstrtab.sh_size); @@ -340,8 +340,8 @@ int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limi for (uint16_t i = 0; i < hdr.sh_num; i++) { struct elf32_shdr section; - memcpy(§ion, elf + (hdr.shoff + i * sizeof(struct elf32_shdr)), - sizeof(struct elf32_shdr)); + memcpy(§ion, elf + (hdr.shoff + i * hdr.shdr_size), + sizeof(struct elf32_shdr)); if (!strcmp(&names[section.sh_name], name)) { if (section.sh_size > limit) { @@ -374,8 +374,8 @@ static uint64_t elf64_max_align(uint8_t *elf) { for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)), - sizeof(struct elf64_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf64_phdr)); if (phdr.p_type != PT_LOAD) continue; @@ -400,8 +400,8 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, bool use_paddr, struc for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)), - sizeof(struct elf64_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf64_phdr)); if (phdr.p_type != PT_LOAD) continue; @@ -422,8 +422,8 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, bool use_paddr, struc size_t r = 0; for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)), - sizeof(struct elf64_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf64_phdr)); if (phdr.p_type != PT_LOAD) continue; @@ -491,8 +491,8 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl uint64_t max_vaddr = 0; for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)), - sizeof(struct elf64_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf64_phdr)); if (phdr.p_type != PT_LOAD) { continue; @@ -549,12 +549,17 @@ final: for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf64_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)), - sizeof(struct elf64_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf64_phdr)); if (phdr.p_type != PT_LOAD) continue; + // Sanity checks + if (phdr.p_filesz > phdr.p_memsz) { + panic(true, "elf: p_filesz > p_memsz"); + } + uint64_t load_addr = 0; if (use_paddr) { @@ -601,7 +606,7 @@ final: if (!fully_virtual && ((higher_half == true && this_top > 0x80000000) || !memmap_alloc_range((size_t)mem_base, (size_t)mem_size, alloc_type, true, false, simulation, false))) { - if (++try_count == max_simulated_tries || simulation == false) { + if (simulation == false || ++try_count == max_simulated_tries) { panic(true, "elf: Failed to allocate necessary memory range (%X-%X)", mem_base, mem_base + mem_size); } if (!kaslr) { @@ -610,6 +615,10 @@ final: goto again; } + if (simulation) { + continue; + } + memcpy((void *)(uintptr_t)load_addr, elf + (phdr.p_offset), phdr.p_filesz); size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz); @@ -679,8 +688,8 @@ int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t *top, uint32_t allo for (uint16_t i = 0; i < hdr.ph_num; i++) { struct elf32_phdr phdr; - memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf32_phdr)), - sizeof(struct elf32_phdr)); + memcpy(&phdr, elf + (hdr.phoff + i * hdr.phdr_size), + sizeof(struct elf32_phdr)); if (phdr.p_type != PT_LOAD) continue; diff --git a/common/protos/stivale2.c b/common/protos/stivale2.c index 9dc933a6..68d728fb 100644 --- a/common/protos/stivale2.c +++ b/common/protos/stivale2.c @@ -162,6 +162,10 @@ bool stivale2_load(char *config, char *cmdline) { level5pg = true; } + if (loaded_by_anchor && (stivale2_hdr.flags & (1 << 2))) { + panic(true, "stivale2: PMRs are not supported for anchored kernels"); + } + if (!loaded_by_anchor) { ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), 0); @@ -172,8 +176,6 @@ bool stivale2_load(char *config, char *cmdline) { if ((stivale2_hdr.flags & (1 << 2))) { if (bits == 32) { panic(true, "stivale2: PMRs are not supported for 32-bit kernels"); - } else if (loaded_by_anchor) { - panic(true, "stivale2: PMRs are not supported for anchored kernels"); } want_pmrs = true; }