:: commit acb6041c669c45905a9004ccbef08aef89d4d629

mintsuki <mintsuki@protonmail.com> — 2022-03-13 16:22

parents: ff5059f9fb

misc: Bug fixes

Co-authored-by: pitust <piotr@stelmaszek.com>
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(&section, elf + (hdr.shoff + i * sizeof(struct elf64_shdr)),
-                   sizeof(struct elf64_shdr));
+        memcpy(&section, 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(&section, elf + (hdr.shoff + i * sizeof(struct elf32_shdr)),
-                   sizeof(struct elf32_shdr));
+        memcpy(&section, 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;
                 }
tab: 248 wrap: offon