Runtime relocation entries are not guaranteed to be sorted by target
address. The existing code skips every entry whose address is below the
previous one, leaving it unrelocated.

Check that each relocation target lies within the image instead. Apply
the same correction to the 32-bit and 64-bit paths.

Fixes: b50b1633c022 ("x86: Add support for 64-bit relocation")
Fixes: 62f7970a5a06 ("x86: Add error checking to x86 relocation code")
Signed-off-by: Jerome Forissier <[email protected]>
---
 arch/x86/lib/relocate.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

I am proposing this patch as a prerequisite to merging the series "net:
lwip: restore TFTP client and command parity" by James H. [1] which would
otherwise introduce a CI error [2]. The error is fixed in pipeline 1762
[3].

[1] 
https://lore.kernel.org/u-boot/20261024-submit-lwip-tftp-combined-v1-v2-0-0f663f735...@gmail.com/
[2] 
https://git.u-boot-project.org/u-boot/custodians/u-boot-net/-/jobs/127971/artifacts/raw/test-log.html
[3] https://git.u-boot-project.org/u-boot/custodians/u-boot-net/-/pipelines/1762

diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index 9ce56062d247..2bb6b843fdd5 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -52,7 +52,7 @@ int clear_bss(void)
 static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size,
                                  Elf64_Rela *re_src, Elf64_Rela *re_end)
 {
-       Elf64_Addr *offset_ptr_rom, *last_offset = NULL;
+       Elf64_Addr *offset_ptr_rom;
        Elf64_Addr *offset_ptr_ram;
 
        do {
@@ -70,7 +70,7 @@ static void do_elf_reloc_fixups64(unsigned int text_base, 
uintptr_t size,
 
                /* Check that the location of the relocation is in .text */
                if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base &&
-                   offset_ptr_rom > last_offset) {
+                   offset_ptr_rom < (Elf64_Addr *)(text_base + size)) {
                        /* Switch to the in-RAM version */
                        offset_ptr_ram = (Elf64_Addr *)((ulong)offset_ptr_rom +
                                                        gd->reloc_off);
@@ -87,11 +87,9 @@ static void do_elf_reloc_fixups64(unsigned int text_base, 
uintptr_t size,
                                      (ulong)*offset_ptr_ram, text_base + size);
                        }
                } else {
-                       debug("   %p: %lx: rom reloc %lx, last %p\n", re_src,
-                             (ulong)re_src->r_info, (ulong)re_src->r_offset,
-                             last_offset);
+                       debug("   %p: %lx: rom reloc %lx outside image\n", 
re_src,
+                             (ulong)re_src->r_info, (ulong)re_src->r_offset);
                }
-               last_offset = offset_ptr_rom;
 
        } while (++re_src < re_end);
 }
@@ -99,7 +97,7 @@ static void do_elf_reloc_fixups64(unsigned int text_base, 
uintptr_t size,
 static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size,
                                  Elf32_Rel *re_src, Elf32_Rel *re_end)
 {
-       Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
+       Elf32_Addr *offset_ptr_rom;
        Elf32_Addr *offset_ptr_ram;
 
        do {
@@ -117,7 +115,7 @@ static void do_elf_reloc_fixups32(unsigned int text_base, 
uintptr_t size,
 
                /* Check that the location of the relocation is in .text */
                if (offset_ptr_rom >= (Elf32_Addr *)(uintptr_t)text_base &&
-                   offset_ptr_rom > last_offset) {
+                   offset_ptr_rom < (Elf32_Addr *)(text_base + size)) {
 
                        /* Switch to the in-RAM version */
                        offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
@@ -133,10 +131,9 @@ static void do_elf_reloc_fixups32(unsigned int text_base, 
uintptr_t size,
                                      *offset_ptr_ram, text_base + size);
                        }
                } else {
-                       debug("   %p: rom reloc %x, last %p\n", re_src,
-                              re_src->r_offset, last_offset);
+                       debug("   %p: rom reloc %x outside image\n", re_src,
+                             re_src->r_offset);
                }
-               last_offset = offset_ptr_rom;
 
        } while (++re_src < re_end);
 }
-- 
2.48.1

Reply via email to