about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-09-06 14:17:35 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-10-12 14:22:03 +0100
commitab0bc274aaeb554748106eac0a6c68864085bfc4 (patch)
tree9ddd110d7b3ce7ad57990dc38deb286da08c98ef
parent9912e5c608b276588a0e83926353c0632f516a02 (diff)
downloadglibc-ab0bc274aaeb554748106eac0a6c68864085bfc4.tar.gz
glibc-ab0bc274aaeb554748106eac0a6c68864085bfc4.tar.xz
glibc-ab0bc274aaeb554748106eac0a6c68864085bfc4.zip
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/Makefile2
-rw-r--r--sysdeps/aarch64/dl-lookupcfg.h8
-rw-r--r--sysdeps/aarch64/dl-symaddr.c17
-rw-r--r--sysdeps/aarch64/morello/Versions6
-rw-r--r--sysdeps/aarch64/morello/dl-symaddr.c49
-rw-r--r--sysdeps/generic/ldsodefs.h4
6 files changed, 84 insertions, 2 deletions
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
+   <https://www.gnu.org/licenses/>.  */
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
+   <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 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)