[PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field

Ard Biesheuvel posted 2 patches 1 month, 3 weeks ago
[PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field
Posted by Ard Biesheuvel 1 month, 3 weeks ago
The PVH entrypoint is entered in 32-bit mode, and is documented as being
a 32-bit field. Linux happens to widen the field in the ELF note to 64
bits so treating it as a 64-bit field works for booting the kernel.

However, Xen documents the ELF note with the following example

  ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long, xen_start32)

and uses .long in the code as well, and so reading more than 32 bits
here is risky. And dereferencing a size_t* in portable code is just
bizarre, so let's use a uint32_t specifically in all cases here.

While at it, read the field as little-endian explicitly, so things work
as expected on big endian hosts too.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 hw/i386/x86-common.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
index 992ea1f25e..44e5c365f1 100644
--- a/hw/i386/x86-common.c
+++ b/hw/i386/x86-common.c
@@ -539,7 +539,7 @@ DeviceState *ioapic_init_secondary(GSIState *gsi_state)
  */
 static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
 {
-    size_t *elf_note_data_addr;
+    void *elf_note_data_addr;
 
     /* Check if ELF Note header passed in is valid */
     if (arg1 == NULL) {
@@ -555,8 +555,6 @@ static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
         elf_note_data_addr =
             ((void *)nhdr64) + nhdr_size64 +
             QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
-
-        pvh_start_addr = *elf_note_data_addr;
     } else {
         struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
         uint32_t nhdr_size32 = sizeof(struct elf32_note);
@@ -566,10 +564,9 @@ static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
         elf_note_data_addr =
             ((void *)nhdr32) + nhdr_size32 +
             QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
-
-        pvh_start_addr = *(uint32_t *)elf_note_data_addr;
     }
 
+    pvh_start_addr = ldl_le_p(elf_note_data_addr);
     return pvh_start_addr;
 }
 
-- 
2.39.5