qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Fix PVH entrypoint parsing
@ 2024-09-29 18:06 Ard Biesheuvel
  2024-09-29 18:06 ` [PATCH v2 1/2] hw/elf_ops: Implement missing endian swabbing for ELF notes Ard Biesheuvel
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2024-09-29 18:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, Ard Biesheuvel

Fix the handling of the ELF note that describes the PVH entrypoint

v2: fix broken ELF note handling on big endian hosts

Ard Biesheuvel (2):
  hw/elf_ops: Implement missing endian swabbing for ELF notes
  hw/x86: Always treat the PVH entrypoint as a 32-bit LE field

 hw/i386/x86-common.c     |  7 ++-----
 include/hw/elf_ops.h.inc | 19 +++++++++++++++++--
 2 files changed, 19 insertions(+), 7 deletions(-)

-- 
2.39.5



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] hw/elf_ops: Implement missing endian swabbing for ELF notes
  2024-09-29 18:06 [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
@ 2024-09-29 18:06 ` Ard Biesheuvel
  2024-09-29 18:06 ` [PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field Ard Biesheuvel
  2024-11-21  8:08 ` [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
  2 siblings, 0 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2024-09-29 18:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, Ard Biesheuvel

ELF notes have type and size fields in the elf_note header that need to
be swabbed before use if the host endianness differs from the endianness
of the ELF binary.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 include/hw/elf_ops.h.inc | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/hw/elf_ops.h.inc b/include/hw/elf_ops.h.inc
index 9c35d1b9da..8b563db2a3 100644
--- a/include/hw/elf_ops.h.inc
+++ b/include/hw/elf_ops.h.inc
@@ -41,6 +41,13 @@ static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
     bswapSZs(&shdr->sh_entsize);
 }
 
+static void glue(bswap_nhdr, SZ)(struct elf_note *nhdr)
+{
+    bswap32s(&nhdr->n_namesz);
+    bswap32s(&nhdr->n_descsz);
+    bswap32s(&nhdr->n_type);
+}
+
 static void glue(bswap_sym, SZ)(struct elf_sym *sym)
 {
     bswap32s(&sym->st_name);
@@ -275,7 +282,8 @@ fail:
 static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
                                                     elf_word note_size,
                                                     elf_word phdr_align,
-                                                    elf_word elf_note_type)
+                                                    elf_word elf_note_type,
+                                                    int must_swab)
 {
     elf_word nhdr_size = sizeof(struct elf_note);
     elf_word elf_note_entry_offset = 0;
@@ -287,6 +295,9 @@ static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
         return NULL;
     }
 
+    if (must_swab) {
+        glue(bswap_nhdr, SZ)(nhdr);
+    }
     note_type = nhdr->n_type;
     while (note_type != elf_note_type) {
         nhdr_namesz = nhdr->n_namesz;
@@ -306,6 +317,9 @@ static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
 
         /* skip to the next ELF Note entry */
         nhdr = (void *)nhdr + elf_note_entry_offset;
+        if (must_swab) {
+            glue(bswap_nhdr, SZ)(nhdr);
+        }
         note_type = nhdr->n_type;
     }
 
@@ -603,7 +617,8 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
             nhdr = (struct elf_note *)data;
             assert(translate_opaque != NULL);
             nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
-                                               *(uint64_t *)translate_opaque);
+                                               *(uint64_t *)translate_opaque,
+                                               must_swab);
             if (nhdr != NULL) {
                 elf_note_fn((void *)nhdr, (void *)&ph->p_align, SZ == 64);
             }
-- 
2.39.5



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field
  2024-09-29 18:06 [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
  2024-09-29 18:06 ` [PATCH v2 1/2] hw/elf_ops: Implement missing endian swabbing for ELF notes Ard Biesheuvel
@ 2024-09-29 18:06 ` Ard Biesheuvel
  2024-11-21  8:08 ` [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
  2 siblings, 0 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2024-09-29 18:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, Ard Biesheuvel

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



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 0/2] Fix PVH entrypoint parsing
  2024-09-29 18:06 [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
  2024-09-29 18:06 ` [PATCH v2 1/2] hw/elf_ops: Implement missing endian swabbing for ELF notes Ard Biesheuvel
  2024-09-29 18:06 ` [PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field Ard Biesheuvel
@ 2024-11-21  8:08 ` Ard Biesheuvel
  2 siblings, 0 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2024-11-21  8:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini

On Sun, 29 Sept 2024 at 20:07, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> Fix the handling of the ELF note that describes the PVH entrypoint
>
> v2: fix broken ELF note handling on big endian hosts
>
> Ard Biesheuvel (2):
>   hw/elf_ops: Implement missing endian swabbing for ELF notes
>   hw/x86: Always treat the PVH entrypoint as a 32-bit LE field
>
>  hw/i386/x86-common.c     |  7 ++-----
>  include/hw/elf_ops.h.inc | 19 +++++++++++++++++--
>  2 files changed, 19 insertions(+), 7 deletions(-)
>

Ping?


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-11-21  8:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-29 18:06 [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel
2024-09-29 18:06 ` [PATCH v2 1/2] hw/elf_ops: Implement missing endian swabbing for ELF notes Ard Biesheuvel
2024-09-29 18:06 ` [PATCH v2 2/2] hw/x86: Always treat the PVH entrypoint as a 32-bit LE field Ard Biesheuvel
2024-11-21  8:08 ` [PATCH v2 0/2] Fix PVH entrypoint parsing Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).