]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: morello: fix DL_SYMBOL_ADDRESS
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Tue, 6 Sep 2022 13:17:35 +0000 (14:17 +0100)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 12 Oct 2022 13:22:03 +0000 (14:22 +0100)
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
sysdeps/aarch64/dl-lookupcfg.h
sysdeps/aarch64/dl-symaddr.c [new file with mode: 0644]
sysdeps/aarch64/morello/Versions [new file with mode: 0644]
sysdeps/aarch64/morello/dl-symaddr.c [new file with mode: 0644]
sysdeps/generic/ldsodefs.h

index d50384c47b2476bc7c1dc3dc331ecd2b7b5f1f66..9d6e16f66ea13207bb002ea321fbe247bfed0987 100644 (file)
@@ -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
index 64d46a050ebb9f099152eca055e6fd5c1ad62ca2..aa3e50d46fc6612c1fbbedc9989682c3f19bd329 100644 (file)
 
 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 (file)
index 0000000..a85969a
--- /dev/null
@@ -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 (file)
index 0000000..d6c306b
--- /dev/null
@@ -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 (file)
index 0000000..b49b416
--- /dev/null
@@ -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)
index 3cb35dbb93010aab085eea0f6438282292ec1225..0cc9d7e89c661ede10fc12971a6f341a76d02df0 100644 (file)
@@ -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)