From ab0bc274aaeb554748106eac0a6c68864085bfc4 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Tue, 6 Sep 2022 14:17:35 +0100 Subject: [PATCH] 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. --- sysdeps/aarch64/Makefile | 2 +- sysdeps/aarch64/dl-lookupcfg.h | 8 +++++ sysdeps/aarch64/dl-symaddr.c | 17 ++++++++++ sysdeps/aarch64/morello/Versions | 6 ++++ sysdeps/aarch64/morello/dl-symaddr.c | 49 ++++++++++++++++++++++++++++ sysdeps/generic/ldsodefs.h | 4 ++- 6 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 sysdeps/aarch64/dl-symaddr.c create mode 100644 sysdeps/aarch64/morello/Versions create mode 100644 sysdeps/aarch64/morello/dl-symaddr.c diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile index d50384c47b..9d6e16f66e 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 64d46a050e..aa3e50d46f 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 0000000000..a85969a8f5 --- /dev/null +++ b/sysdeps/aarch64/dl-symaddr.c @@ -0,0 +1,17 @@ +/* Empty file: AArch64 does not have special DL_SYMBOL_ADDRESS. + 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 + . */ diff --git a/sysdeps/aarch64/morello/Versions b/sysdeps/aarch64/morello/Versions new file mode 100644 index 0000000000..d6c306bcbe --- /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 0000000000..b49b416170 --- /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 + . */ + +#include +#include + +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 3cb35dbb93..0cc9d7e89c 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -140,8 +140,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)