]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: morello: fix relative relocs
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 31 Aug 2022 15:37:40 +0000 (16:37 +0100)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 12 Oct 2022 13:22:03 +0000 (14:22 +0100)
use the reloc processing code from cheri-rel.h which already
supports separate RX and RW capabilities per module.

elf/dynamic-link.h
sysdeps/aarch64/ldsodefs.h
sysdeps/aarch64/morello/dl-irel.h
sysdeps/aarch64/morello/dl-machine.h

index 6102990581e6e68ceb982af25659f35fd5f3e282..86105714bbfa0fd4f8df120de4e516125aef7008 100644 (file)
@@ -46,9 +46,14 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
                  const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
                  const struct r_found_version *version, void *const reloc_addr,
                  int skip_ifunc);
+#  ifdef __CHERI_PURE_CAPABILITY__
 static inline void __attribute__((always_inline))
-elf_machine_rela_relative (elfptr_t l_addr, const ElfW(Rela) *reloc,
+elf_machine_rela_relative (struct link_map *map, const ElfW(Rela) *reloc);
+#  else
+static inline void __attribute__((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
                           void *const reloc_addr);
+#  endif
 # endif
 # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
 static inline void __attribute__((always_inline))
index ab42b05f6c53a9a722ae179300c600b50f4737f8..b0b23df93cd67e2dd4c395018e872938454f5c7d 100644 (file)
 #include <elf.h>
 #include <cpu-features.h>
 
+#ifdef __CHERI_PURE_CAPABILITY__
+# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
+  elf_machine_rela_relative (map, relative)
+#endif
+
 struct La_aarch64_regs;
 struct La_aarch64_retval;
 
index 0ff4d406228a01f3d5281c3d9b65d781358494ae..e12d29a089a34d7ac45a08afa62b457e0e8ef220 100644 (file)
@@ -41,42 +41,7 @@ elf_ifunc_invoke (uintptr_t addr)
         (GLRO(dl_hwcap) | _IFUNC_ARG_HWCAP, &arg);
 }
 
-#include <cheri_perms.h>
-
-static inline uintptr_t
-__attribute__ ((always_inline))
-morello_relative_value (uintptr_t l_addr,
-                       const ElfW(Rela) *reloc,
-                       void *reloc_addr)
-{
-  uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
-
-  /* Fragment identified by r_offset has the following information:
-     | 64-bit: address | 56-bits: length | 8-bits: permissions | */
-  unsigned long loc = u64_reloc_addr[0];
-  unsigned long len = u64_reloc_addr[1] & ((1UL << 56) - 1);
-  unsigned long perm = u64_reloc_addr[1] >> 56;
-  unsigned long perm_mask = 0;
-  uintptr_t value = __builtin_cheri_bounds_set_exact (l_addr + loc, len);
-
-  value = value + reloc->r_addend;
-
-  /* Set permissions. Permissions field encoded as:
-     4 = executable, 2 = read/write, 1 = read-only.
-     Mask should follow the same encoding as the ELF segment permissions.  */
-  if (perm == 1)
-    perm_mask = CAP_PERM_MASK_R;
-  if (perm == 2)
-    perm_mask = CAP_PERM_MASK_RW;
-  if (perm == 4)
-    perm_mask = CAP_PERM_MASK_RX;
-  value = __builtin_cheri_perms_and (value, perm_mask);
-
-  /* Seal capabilities, which provide execute permission, with MORELLO_RB.  */
-  if (perm == 4)
-    value = __builtin_cheri_seal_entry (value);
-  return value;
-}
+#include <cheri-rel.h>
 
 static inline void
 __attribute ((always_inline))
@@ -87,10 +52,13 @@ elf_irela (const ElfW(Rela) *reloc)
   if (__glibc_likely (r_type == MORELLO_R(IRELATIVE)))
     {
       struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-      void *reloc_addr = (void *) main_map->l_addr + reloc->r_offset;
+      void *reloc_addr = (void *) dl_rw_ptr (main_map, reloc->r_offset);
       uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
+      uint64_t base = main_map->l_addr;
+      uintptr_t cap_rx = main_map->l_map_start;
+      uintptr_t cap_rw = main_map->l_rw_start;
       uintptr_t value
-       = morello_relative_value (main_map->l_addr, reloc, reloc_addr);
+       = morello_relative (base, cap_rx, cap_rw, reloc, reloc_addr);
       *cap_reloc_addr = elf_ifunc_invoke (value);
     }
   else
index ff5169d779de1fbcd6002cbfc8a1989dc92b204e..4eaffc2cf68d5521e214413335c2e32308a1c01d 100644 (file)
@@ -282,7 +282,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
   const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
 
   if (r_type == MORELLO_R(RELATIVE))
-    *cap_reloc_addr = morello_relative_value (map->l_addr, reloc, reloc_addr);
+    *cap_reloc_addr = morello_relative (map->l_addr, map->l_map_start,
+                                       map->l_rw_start, reloc, reloc_addr);
   else if (r_type == AARCH64_R(RELATIVE))
     *u64_reloc_addr = map->l_addr + reloc->r_addend;
   else if (__builtin_expect (r_type == R_AARCH64_NONE, 0))
@@ -347,8 +348,11 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
 
        case MORELLO_R(IRELATIVE):
        {
-         uintptr_t value
-           = morello_relative_value (map->l_addr, reloc, reloc_addr);
+         uintptr_t value = morello_relative (map->l_addr,
+                                             map->l_map_start,
+                                             map->l_rw_start,
+                                             reloc,
+                                             reloc_addr);
          if (__glibc_likely (!skip_ifunc))
            value = elf_ifunc_invoke (value);
          *cap_reloc_addr = value;
@@ -410,15 +414,19 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
 
 static inline void
 __attribute__ ((always_inline))
-elf_machine_rela_relative (uintptr_t l_addr,
-                          const ElfW(Rela) *reloc,
-                          void *const reloc_addr)
+elf_machine_rela_relative (struct link_map *map, const ElfW(Rela) *reloc)
 {
+  ElfW(Addr) l_addr = map->l_addr;
+  uintptr_t cap_rx = map->l_map_start;
+  uintptr_t cap_rw = map->l_rw_start;
+  void *const reloc_addr
+    = (void *) __builtin_cheri_address_set (cap_rw, l_addr + reloc->r_offset);
   uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
   uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
   const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
   if (r_type == MORELLO_R(RELATIVE))
-    *cap_reloc_addr = morello_relative_value (l_addr, reloc, reloc_addr);
+    *cap_reloc_addr = morello_relative (l_addr, cap_rx, cap_rw,
+                                       reloc, reloc_addr);
   else
     *u64_reloc_addr = l_addr + reloc->r_addend;
 }
@@ -485,8 +493,8 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
     }
   else if (__glibc_unlikely (r_type == MORELLO_R(IRELATIVE)))
     {
-      uintptr_t value
-       = morello_relative_value (map->l_addr, reloc, reloc_addr);
+      uintptr_t value = morello_relative (map->l_addr, map->l_map_start,
+                                         map->l_rw_start, reloc, reloc_addr);
       if (__glibc_likely (!skip_ifunc))
        value = elf_ifunc_invoke (value);
       *cap_reloc_addr = value;