diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2022-09-06 14:17:35 +0100 |
---|---|---|
committer | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2022-10-27 14:46:54 +0100 |
commit | 63aa755b4064a0cbd1598b53cb8c82ecb8ea4e2d (patch) | |
tree | d8192646029f0445d31392ac85d6d40778ac85ed | |
parent | c62607b9006c23b2f21f1bc5b36b048ce93071ec (diff) | |
download | glibc-63aa755b4064a0cbd1598b53cb8c82ecb8ea4e2d.zip glibc-63aa755b4064a0cbd1598b53cb8c82ecb8ea4e2d.tar.gz glibc-63aa755b4064a0cbd1598b53cb8c82ecb8ea4e2d.tar.bz2 |
aarch64: morello: fix DL_SYMBOL_ADDRESS
It has to return a pointer that can be dereferenced, so it must be
derived correctly from RX and RW capabilities.
Try to have tight object bounds and seal function symbols.
-rw-r--r-- | sysdeps/aarch64/Makefile | 2 | ||||
-rw-r--r-- | sysdeps/aarch64/dl-lookupcfg.h | 8 | ||||
-rw-r--r-- | sysdeps/aarch64/dl-symaddr.c | 0 | ||||
-rw-r--r-- | sysdeps/aarch64/morello/Versions | 6 | ||||
-rw-r--r-- | sysdeps/aarch64/morello/dl-symaddr.c | 49 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 4 |
6 files changed, 67 insertions, 2 deletions
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile index d50384c..9d6e16f 100644 --- a/sysdeps/aarch64/Makefile +++ b/sysdeps/aarch64/Makefile @@ -9,7 +9,7 @@ LDFLAGS-rtld += -Wl,-z,force-bti,--fatal-warnings endif ifeq ($(subdir),elf) -sysdep-dl-routines += dl-bti +sysdep-dl-routines += dl-bti dl-symaddr tests += tst-audit26 \ tst-audit27 diff --git a/sysdeps/aarch64/dl-lookupcfg.h b/sysdeps/aarch64/dl-lookupcfg.h index 64d46a0..aa3e50d 100644 --- a/sysdeps/aarch64/dl-lookupcfg.h +++ b/sysdeps/aarch64/dl-lookupcfg.h @@ -22,6 +22,14 @@ struct link_map; +#ifdef __CHERI_PURE_CAPABILITY__ +/* Symbol pointer with correct capability permission and bounds. */ +void *_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref); +rtld_hidden_proto (_dl_symbol_address) + +# define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref) +#endif + extern void _dl_unmap (struct link_map *map); #define DL_UNMAP(map) _dl_unmap (map) diff --git a/sysdeps/aarch64/dl-symaddr.c b/sysdeps/aarch64/dl-symaddr.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sysdeps/aarch64/dl-symaddr.c diff --git a/sysdeps/aarch64/morello/Versions b/sysdeps/aarch64/morello/Versions new file mode 100644 index 0000000..d6c306b --- /dev/null +++ b/sysdeps/aarch64/morello/Versions @@ -0,0 +1,6 @@ +ld { + GLIBC_PRIVATE { + # in ld.so, but used by libc.so too. + _dl_symbol_address; + } +} diff --git a/sysdeps/aarch64/morello/dl-symaddr.c b/sysdeps/aarch64/morello/dl-symaddr.c new file mode 100644 index 0000000..b49b416 --- /dev/null +++ b/sysdeps/aarch64/morello/dl-symaddr.c @@ -0,0 +1,49 @@ +/* Get the symbol address. Morello version. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <ldsodefs.h> +#include <dl-machine.h> + +void * +_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref) +{ + elfptr_t value = SYMBOL_ADDRESS (map, ref, false); + if (map == NULL) + return (void *) value; + if (ELFW(ST_TYPE) (ref->st_info) == STT_OBJECT) + { + unsigned long perm_mask = CAP_PERM_MASK_R; + for (int i = 0; i < map->l_rw_count; i++) + if (map->l_rw_range[i].start <= value + && map->l_rw_range[i].end > value) + { + value = dl_rw_ptr (map, value - map->l_addr); + perm_mask = CAP_PERM_MASK_RW; + break; + } + value = __builtin_cheri_bounds_set_exact (value, ref->st_size); + value = __builtin_cheri_perms_and (value, perm_mask); + } + else if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC) + { + /* Seal function pointers. Note: ifunc is handled by the caller. */ + value = __builtin_cheri_seal_entry (value); + } + return (void *) value; +} +rtld_hidden_def (_dl_symbol_address) diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 81b6356..54316b7 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -141,8 +141,10 @@ typedef void (*dl_init_t) (int, char **, char **); to the actual code of the function but rather an architecture specific descriptor. */ #ifndef ELF_FUNCTION_PTR_IS_SPECIAL -# define DL_SYMBOL_ADDRESS(map, ref) \ +# ifndef __CHERI_PURE_CAPABILITY__ +# define DL_SYMBOL_ADDRESS(map, ref) \ (void *) SYMBOL_ADDRESS (map, ref, false) +# endif # define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr)) (addr)) # define DL_CALL_DT_INIT(map, start, argc, argv, env) \ ((dl_init_t) (start)) (argc, argv, env) |