about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-08-08 11:29:21 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-10-12 14:22:03 +0100
commit74085ebc1f762c9fd70af4b99b5615dc5358dee0 (patch)
tree0f39c269695a19a5a8228e2698b78dd767224c39
parent1b0716e08364e9b9985cd801e0f35edb6550e501 (diff)
downloadglibc-74085ebc1f762c9fd70af4b99b5615dc5358dee0.tar.gz
glibc-74085ebc1f762c9fd70af4b99b5615dc5358dee0.tar.xz
glibc-74085ebc1f762c9fd70af4b99b5615dc5358dee0.zip
aarch64: morello: Add elf_machine_rtld_base_setup
Use a new hook to do the rtld bootstrap map base address and root
capability setup on CHERI.

This will be needed to use separate per module RX and RW root caps.
-rw-r--r--sysdeps/aarch64/morello/dl-machine.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/sysdeps/aarch64/morello/dl-machine.h b/sysdeps/aarch64/morello/dl-machine.h
index 19110d75c5..ff5169d779 100644
--- a/sysdeps/aarch64/morello/dl-machine.h
+++ b/sysdeps/aarch64/morello/dl-machine.h
@@ -101,6 +101,78 @@ elf_machine_runtime_dynamic (void)
   return p;
 }
 
+/* PCC relative access to ehdr before relocations are processed.  */
+static const ElfW(Ehdr) *
+elf_machine_ehdr (void)
+{
+  const void *p;
+  asm (""
+    ".weak __ehdr_start\n"
+    ".hidden __ehdr_start\n"
+    "adrp %0, __ehdr_start\n"
+    "add %0, %0, :lo12:__ehdr_start\n" : "=r"(p));
+  return p;
+}
+
+/* Set up ld.so root capabilities and base address from args.  */
+static void __attribute__ ((unused))
+elf_machine_rtld_base_setup (struct link_map *map, void *args)
+{
+  uintptr_t *sp;
+  long argc;
+  uintptr_t cap_rx, cap_rw, cap_exe_rx, cap_exe_rw;
+  unsigned long ldso_base = 0;
+
+  sp = args;
+  argc = sp[0];
+  /* Skip argv.  */
+  sp += argc + 2;
+  /* Skip environ.  */
+  for (; *sp; sp++);
+  sp++;
+  cap_rx = cap_rw = cap_exe_rx = cap_exe_rw = 0;
+  for (; *sp != AT_NULL; sp += 2)
+    {
+      long t = sp[0];
+      if (t == AT_BASE)
+	ldso_base = sp[1];
+      if (t == AT_CHERI_INTERP_RX_CAP)
+	cap_rx = sp[1];
+      if (t == AT_CHERI_INTERP_RW_CAP)
+	cap_rw = sp[1];
+      if (t == AT_CHERI_EXEC_RX_CAP)
+	cap_exe_rx = sp[1];
+      if (t == AT_CHERI_EXEC_RW_CAP)
+	cap_exe_rw = sp[1];
+    }
+  /* Check if ldso is the executable.  */
+  if (ldso_base == 0)
+    {
+      cap_rx = cap_exe_rx;
+      cap_rw = cap_exe_rw;
+      ldso_base = cap_rx; /* Assume load segments start at vaddr 0.  */
+    }
+  map->l_addr = ldso_base;
+  map->l_map_start = cap_rx;
+  map->l_rw_start = cap_rw;
+
+  /* Set up the RW ranges of ld.so, required for symbolic relocations.  */
+  const ElfW(Ehdr) *ehdr = elf_machine_ehdr ();
+  const ElfW(Phdr) *phdr = (const void *) ehdr + ehdr->e_phoff;
+  if (sizeof *phdr != ehdr->e_phentsize)
+    __builtin_trap ();
+  for (const ElfW(Phdr) *ph = phdr; ph < phdr + ehdr->e_phnum; ph++)
+    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W))
+      {
+	uintptr_t allocend = map->l_addr + ph->p_vaddr + ph->p_memsz;
+	if (map->l_rw_count >= DL_MAX_RW_COUNT)
+	  __builtin_trap ();
+	map->l_rw_range[map->l_rw_count].start = map->l_addr + ph->p_vaddr;
+	map->l_rw_range[map->l_rw_count].end = allocend;
+	map->l_rw_count++;
+      }
+}
+
 /* Load address of the dynamic linker with correct bounds.  */
 static uintptr_t __attribute__ ((unused))
 elf_machine_load_address_from_args (void *arg)