Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/amd64/stand/prekern If we encounter relocations fro...



details:   https://anonhg.NetBSD.org/src/rev/b006865cdfbd
branches:  trunk
changeset: 932433:b006865cdfbd
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu May 07 16:49:59 2020 +0000

description:
If we encounter relocations from a section that the bootloader dropped,
AND if the section is a note, then skip the relocations.

Considering a note that the bootloader dropped, there are two possible
sides for the relocations: (1) the relocations from the note towards the
rest of the binary, and (2) the relocations from the rest of the binary
towards the note.

We skip (1), which is correct, because the notes do not play any role at
run time. If we encounter (2) however then there is a bug in the kernel,
so add a sanity check against that.

This fixes KASLR since the latest Xen changes (which introduced .note.Xen).

diffstat:

 sys/arch/amd64/stand/prekern/elf.c |  63 ++++++++++++++++++++++++++++---------
 1 files changed, 48 insertions(+), 15 deletions(-)

diffs (107 lines):

diff -r d62ad1611818 -r b006865cdfbd sys/arch/amd64/stand/prekern/elf.c
--- a/sys/arch/amd64/stand/prekern/elf.c        Thu May 07 16:20:40 2020 +0000
+++ b/sys/arch/amd64/stand/prekern/elf.c        Thu May 07 16:49:59 2020 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: elf.c,v 1.19 2020/05/05 19:26:47 maxv Exp $    */
+/*     $NetBSD: elf.c,v 1.20 2020/05/07 16:49:59 maxv Exp $    */
 
 /*
- * Copyright (c) 2017 The NetBSD Foundation, Inc. All rights reserved.
+ * Copyright (c) 2017-2020 The NetBSD Foundation, Inc. All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Maxime Villard.
@@ -60,6 +60,40 @@
        return 0;
 }
 
+static bool
+elf_section_mappable(Elf_Shdr *shdr)
+{
+       if (!(shdr->sh_flags & SHF_ALLOC)) {
+               return false;
+       }
+       if (shdr->sh_type != SHT_NOBITS &&
+           shdr->sh_type != SHT_PROGBITS) {
+               return false;
+       }
+       return true;
+}
+
+static bool
+elf_can_drop_unmappable(Elf_Shdr *shdr)
+{
+       /*
+        * We found relocations from the section 'shdr' towards the rest of
+        * the binary, but 'shdr' is not mapped. Decide whether to skip the
+        * relocations from this section.
+        *
+        * We skip only if it is a note. It means that we allow notes to
+        * have relocations towards the rest of the binary, typically with
+        * the ".note.Xen" section. Notes do not play any role at run time.
+        *
+        * Any section other than a note is the sign there is a design
+        * mistake in the kernel (variables stored outside of rodata/data).
+        */
+       if (shdr->sh_type == SHT_NOTE) {
+               return true;
+       }
+       return false;
+}
+
 static vaddr_t
 elf_get_entrypoint(void)
 {
@@ -144,6 +178,12 @@
 
                fatal("elf_sym_lookup: external symbol");
        }
+       if (sym->st_shndx >= eif.ehdr->e_shnum) {
+               fatal("elf_sym_lookup: st_shndx is malformed");
+       }
+       if (!elf_section_mappable(&eif.shdr[sym->st_shndx])) {
+               fatal("elf_sym_lookup: st_shndx not mappable");
+       }
        if (sym->st_value == 0) {
                fatal("elf_sym_lookup: zero value");
        }
@@ -259,19 +299,6 @@
        }
 }
 
-static bool
-elf_section_mappable(Elf_Shdr *shdr)
-{
-       if (!(shdr->sh_flags & SHF_ALLOC)) {
-               return false;
-       }
-       if (shdr->sh_type != SHT_NOBITS &&
-           shdr->sh_type != SHT_PROGBITS) {
-               return false;
-       }
-       return true;
-}
-
 void
 elf_map_sections(void)
 {
@@ -429,6 +456,9 @@
                        fatal("elf_kernel_reloc: REL sh_info is malformed");
                }
                if (!elf_section_mappable(&eif.shdr[secidx])) {
+                       if (elf_can_drop_unmappable(&eif.shdr[secidx])) {
+                               continue;
+                       }
                        fatal("elf_kernel_reloc: REL sh_info not mappable");
                }
                base = (uintptr_t)eif.ehdr + eif.shdr[secidx].sh_offset;
@@ -461,6 +491,9 @@
                        fatal("elf_kernel_reloc: RELA sh_info is malformed");
                }
                if (!elf_section_mappable(&eif.shdr[secidx])) {
+                       if (elf_can_drop_unmappable(&eif.shdr[secidx])) {
+                               continue;
+                       }
                        fatal("elf_kernel_reloc: RELA sh_info not mappable");
                }
                base = (uintptr_t)eif.ehdr + eif.shdr[secidx].sh_offset;



Home | Main Index | Thread Index | Old Index