summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-08-31 16:37:40 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-10-12 14:22:03 +0100
commite6a2c4c4bbb922fd326e5085cd1f28d5265ade6d (patch)
tree5decfee722d442decef771901318aba8c6c40daf
parent87dffcda136a7d1b0c0f81ccf9ac084178181321 (diff)
downloadglibc-e6a2c4c4bbb922fd326e5085cd1f28d5265ade6d.tar.gz
aarch64: morello: fix relative relocs
use the reloc processing code from cheri-rel.h which already supports separate RX and RW capabilities per module.
-rw-r--r--elf/dynamic-link.h7
-rw-r--r--sysdeps/aarch64/ldsodefs.h5
-rw-r--r--sysdeps/aarch64/morello/dl-irel.h44
-rw-r--r--sysdeps/aarch64/morello/dl-machine.h26
4 files changed, 34 insertions, 48 deletions
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 6102990581..86105714bb 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -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))
diff --git a/sysdeps/aarch64/ldsodefs.h b/sysdeps/aarch64/ldsodefs.h
index ab42b05f6c..b0b23df93c 100644
--- a/sysdeps/aarch64/ldsodefs.h
+++ b/sysdeps/aarch64/ldsodefs.h
@@ -22,6 +22,11 @@
#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;
diff --git a/sysdeps/aarch64/morello/dl-irel.h b/sysdeps/aarch64/morello/dl-irel.h
index 0ff4d40622..e12d29a089 100644
--- a/sysdeps/aarch64/morello/dl-irel.h
+++ b/sysdeps/aarch64/morello/dl-irel.h
@@ -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
diff --git a/sysdeps/aarch64/morello/dl-machine.h b/sysdeps/aarch64/morello/dl-machine.h
index ff5169d779..4eaffc2cf6 100644
--- a/sysdeps/aarch64/morello/dl-machine.h
+++ b/sysdeps/aarch64/morello/dl-machine.h
@@ -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;