about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-09-21 15:32:34 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-11-22 14:31:25 +0000
commitd7d9ee6edcb81380645de095a41f0f301c1bf5e1 (patch)
treed3b1edef10bbcfe5c78e4f3887b0bd94c58f3799 /sysdeps
parent32c64139eef90920af88e85c07c168fcada73935 (diff)
downloadglibc-d7d9ee6edcb81380645de095a41f0f301c1bf5e1.tar.gz
glibc-d7d9ee6edcb81380645de095a41f0f301c1bf5e1.tar.xz
glibc-d7d9ee6edcb81380645de095a41f0f301c1bf5e1.zip
cheri: malloc: Initial capability narrowing support
Public interfaces return pointers with narrow bounds, this internally
requires bumping the size and alignment requirement of allocations so
the bounds are representible.

When pointers with narrow bounds need to be turned back to have wide
bounds (free, realloc), the pointer is rederived from DDC. (So this
patch relies on DDC to cover all heap memory with RW permission.)

Allocations above the mmap threshold waste memory for alignment and
realloc often falls back to the inefficient alloc, copy, free sequence
instead of mremap or other inplace solution.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/aarch64/morello/libc-cap.h66
-rw-r--r--sysdeps/generic/libc-cap.h34
2 files changed, 100 insertions, 0 deletions
diff --git a/sysdeps/aarch64/morello/libc-cap.h b/sysdeps/aarch64/morello/libc-cap.h
new file mode 100644
index 0000000000..d772e36dee
--- /dev/null
+++ b/sysdeps/aarch64/morello/libc-cap.h
@@ -0,0 +1,66 @@
+/* Support for allocations with narrow capability bounds.  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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _AARCH64_MORELLO_LIBC_CAP_H
+#define _AARCH64_MORELLO_LIBC_CAP_H 1
+
+/* No special alignment is needed for n <= __CAP_ALIGN_THRESHOLD
+   allocations, i.e. __libc_cap_align (n) <= MALLOC_ALIGNMENT.  */
+#define __CAP_ALIGN_THRESHOLD 32759
+
+/* Round up the allocation size so the allocated pointer bounds
+   can be represented.  Note: this may be called before any
+   checks on n, so it should work with all possible n values.  */
+static __always_inline size_t
+__libc_cap_roundup (size_t n)
+{
+  if (__glibc_unlikely (n > PTRDIFF_MAX))
+    return n;
+  return __builtin_cheri_round_representable_length (n);
+}
+
+/* Returns the alignment requirement for an allocation size n such
+   that the allocated pointer bounds can be represented.  Note:
+   same n should be used in __libc_cap_roundup and __libc_cap_align
+   and the results used together for __libc_cap_narrow.  */
+static __always_inline size_t
+__libc_cap_align (size_t n)
+{
+  return -__builtin_cheri_representable_alignment_mask (n);
+}
+
+/* Narrow the bounds of p to be [p, p+n).  Note: the original bounds
+   of p includes the entire mapping where p points to and that bound
+   should be recoverable by __libc_cap_widen.  Called with p aligned
+   and n sized according to __libc_cap_align and __libc_cap_roundup.  */
+static __always_inline void *
+__libc_cap_narrow (void *p, size_t n)
+{
+  return __builtin_cheri_bounds_set_exact (p, n);
+}
+
+/* Given a p with narrowed bound (output of __libc_cap_narrow) return
+   the same pointer with the internal wide bound.  */
+static __always_inline void *
+__libc_cap_widen (void *p)
+{
+  void *cap = __builtin_cheri_global_data_get ();
+  return __builtin_cheri_address_set (cap, p);
+}
+
+#endif
diff --git a/sysdeps/generic/libc-cap.h b/sysdeps/generic/libc-cap.h
new file mode 100644
index 0000000000..85ff2a6b61
--- /dev/null
+++ b/sysdeps/generic/libc-cap.h
@@ -0,0 +1,34 @@
+/* Support for allocations with narrow capability bounds.  Generic 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC_CAP_H
+#define _LIBC_CAP_H 1
+
+/* Larger allocations may need special alignment via cap_align.  */
+#define __CAP_ALIGN_THRESHOLD SIZE_MAX
+
+/* Error if the identifiers bellow are used.  */
+void __libc_cap_link_error (void);
+
+#define __libc_cap_fail(rtype) (__libc_cap_link_error (), (rtype) 0)
+#define __libc_cap_roundup(n) __libc_cap_fail (size_t)
+#define __libc_cap_align(n) __libc_cap_fail (size_t)
+#define __libc_cap_narrow(p, n) __libc_cap_fail (void *)
+#define __libc_cap_widen(p) __libc_cap_fail (void *)
+
+#endif