Compare commits

...
Author SHA1 Message Date
Carlos Eduardo Seo 42c99ba55f cheri: stdio-common: Add test for %#p printf modifier
Testcase for printing capabilities.
2022-10-26 15:50:33 +01:00
Szabolcs Nagy 829e179a52 Fix elf/tst-tls20 stack OOB access
Off-by-one error found on morello with strict stack bounds.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 8a4566d712 Revert "Fix elf/tst-tls20 stack OOB access"
This reverts commit 37cfa707b0.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 7a76b94bab TODO: fix _dl_runtime_profile entry after revert
TODO: squash into

  commit 392f32c841
  aarch64: morello: add lazy binding entry code
2022-10-26 15:39:59 +01:00
Szabolcs Nagy a6e4d0bbd7 Revert "TODO(audit): aarch64: morello: add _dl_runtime_profile entry"
This reverts commit 0c66b05c7f0b2ec5fdf7d37b4150ba517efa5df8.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy c5872cb18b Revert "TODO(gprof): aarch64: morello: add gprof profiling support to asm"
This reverts commit 960401b6f740232d2b97bfe9ea4118b394112a5e.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 3295936b27 Revert "TODO(drop): aarch64: morello: CPU feature detection for Morello"
This reverts commit 078ebf3e35bd0c50b58dc2ec796530054f69b9a9.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 782fb76092 Revert "TODO(relro): cheri: make __attribute_relro a nop"
This reverts commit 347f7e2ac1.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 8593166279 Revert "TODO(l_addr): cheri: rtld: elfptr_t fix in rtld.c program header processing"
This reverts commit 93ab84cd80.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy bf969db943 aarch64: morello: add prctl with correct vararg handling
prctl is a variadic function and on morello args that were not passed
cannot be accessed so the generic code does not work.
2022-10-26 15:39:59 +01:00
Szabolcs Nagy a46c1b96f3 TODO: fix variadic syscalls
Only use as many varargs as accessible according to the bounds of c9.

TODO: squash into original syscall support
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 0e893e3d68 TODO: use empty dl-symaddr.c
TODO: squash into

  commit 0edbd4c6d389b9e2be5ff1d026b4d30ae70a4af9
  aarch64: morello: fix DL_SYMBOL_ADDRESS
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 057a635835 TODO: use empty wordcopy.c
TODO: squash into

  commit 418b9dac8999e5a64b69ee072321cd6eed8d8be1
  aarch64: don't build wordcopy
2022-10-26 15:39:59 +01:00
Szabolcs Nagy 45b4ae2ffd TODO: more l_addr cleanup
TODO: squash into

  commit f2f4f441fbda6080d0ff742f3bb535c09315ef98
  cheri: elf: Turn l_addr back to ElfW(Addr)
2022-10-26 15:39:59 +01:00
Szabolcs Nagy e8d0e61aa2 TODO(uapi): cheri: start: restrict auxv capability permissions
TODO: not needed with full pcuabi
2022-10-26 15:39:59 +01:00
Szabolcs Nagy df30ef1b0d cheri: Fix capability permissions of PROT_NONE maps in test code 2022-10-26 15:39:59 +01:00
Szabolcs Nagy cef9089a68 cheri: Fix capability permissions of PROT_NONE map in locarchive 2022-10-26 15:39:59 +01:00
Szabolcs Nagy b2854b0bcc cheri: nptl: Fix thread stack capability permissions 2022-10-26 15:39:59 +01:00
Szabolcs Nagy 40b60cc1db cheri: elf: Fix segment mapping permissions
Ensure mmap returns pointers with RWX permission covering all segments.
These pointers later get restricted to RX and RW permission.
2022-10-26 15:32:01 +01:00
Szabolcs Nagy 44283b4f2f cheri: malloc: Ensure the mappings have RW permission
The arena allocator incrementally applies RW mprotect to a PROT_NONE
mapping.  Use PROT_MAX to ensure the pointers derived from the original
mapping have RW capability permission.
2022-10-26 15:32:01 +01:00
Szabolcs Nagy 418ede06d7 aarch64: morello: define PROT_MAX
Specifies the prot flags a mapping may gain via mprotect or MAP_FIXED.
On CHERI targets this is used to get capability with more permissions
than the original mmap protection would imply.
2022-10-26 15:32:01 +01:00
Szabolcs Nagy dac0b184e7 TODO(uapi): mmap perm emulation 2022-10-26 15:32:01 +01:00
Szabolcs Nagy 28f19db3b8 TODO: update cheri_perms.h
TODO: squash into initial cheri_perms.h
2022-10-26 15:32:01 +01:00
Szabolcs Nagy 78412dcc6a cheri: Update the static tls requirement of the libc
Larger requirement because pointers are bigger.
2022-10-20 18:16:55 +01:00
Szabolcs Nagy 4ad4ea848b math: Fix asin and acos invalid exception
This works around a gcc issue where it const folds inf/inf into nan,
preventing the invalid exception signal to be raised.

(x-x)/(x-x) is more robust against optimizations and works for x==nan
too.

The issue should be fixed in gcc-11.3.0 and gcc-12, but glibc supports
older compilers.
2022-10-13 11:43:54 +01:00
Szabolcs Nagy f660eb9cc7 cheri: malloc: disable capability narrowing on some tests
malloc/tst-malloc-backtrace tests heap corruption.
malloc/tst-dynarray uses malloc_debug wrappers that access internals.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 1fa257f338 cheri: malloc: add tunable to turn narrowing off 2022-10-12 14:22:03 +01:00
Szabolcs Nagy cdba5ffdae cheri: malloc: Capability narrowing using internal lookup table
Add more cap_ hooks to implement narrowing without depending on a
global capability covering the heap.  Either recording every
narrowed capability in a lookup table or recording every mapping
used for the heap are supported.  The morello implmentation uses
a lookup table for now.

The lookup table adds memory overhead, failure paths and locks.
Recording and removing entries from the lookup table must be done
carefully in realloc so on failure the old pointer is usable and
on success the old pointer is immediately reusable concurrently.
The locks require fork hooks so malloc works in multi-threaded
fork child.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy f54124b801 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.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 3d959e4b0e malloc: Don't use __libc_free for tcache cleanup
__libc_free must only be used for memory given out by __libc_malloc
and similar public apis, but tcache stores a cache of already freed
pointers and itself is allocated using internal malloc apis.  Strong
double free detection in __libc_free breaks tcache_thread_shutdown,
so use a cut down version of free to reset tcache entries.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy c0a839639b cheri: elf: make sure dlpi_phdr covers the load segments
In dl_iterate_phdr phdr is the only capability passed to the callback
that may be used to derive pointers of the elf module, so ensure it
has wide bounds.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 0648dbf3a0 aarch64: morello: add dl-r_debug.h
Used internally for r_debug tests, but with the assumption that
the return value can be dereferenced, so change the prototype
and return a valid capability.

Also used in pldd, where we only support purecap abi processes.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy bbfb104b50 TODO(api): cheri: fix dl_iterate_phdr dlpi_addr
The dlpi_addr field is a capability that has value l_addr, but we can
only do this for libraries (ET_DYN) where l_addr == l_map_start,
otherwise we return l_addr which is normally 0 then (ET_EXEC) so the
caller can detect and special case it.

For now l_addr != 0 and l_addr != l_map_start case is not supported.
Note: this api may be used by the unwinder to find and read .eh_frame
data.

TODO: dlpi_addr could be address only, but requires unwinder update
and agreement about the abi.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 66e78c5b74 aarch64: morello: elf: drop unused load address computation
l_addr is no longer a capability so this is not needed.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 4d7cf069ee cheri: elf: Turn l_addr back to ElfW(Addr)
Pointers are no longer derived from l_addr, but l_map_start (RX) and
l_rw_start (RW) so it does not have to be a capability.

This also allows removing hacks where l_addr was derived from DDC.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 9c11d64d6d cheri: elf: use RX, RW capabilities to derive pointers
Instead of

  map->l_addr + offset

use

  dl_rx_ptr (map, offset)
  dl_rw_ptr (map, offset)

depending on RX or RW permission requirement.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy b35504abf0 aarch64: morello: RX, RW fixes for relocation processing 2022-10-12 14:22:03 +01:00
Szabolcs Nagy f0e8f3667c aarch64: morello: elf: Return bounded pointer in __tls_get_addr
There is no traditional TLS support in morello that would explicitly
call __tls_get_addr, but the libc uses it internally and the returned
pointer escapes to user code.  So bound the pointers according to
the tls symbol size instead of doing so in each caller.

(Affects dlsym and dynamic TLSDESC.)
2022-10-12 14:22:03 +01:00
Szabolcs Nagy ab0bc274aa 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.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 9912e5c608 cheri: fix SYMBOL_ADDRESS to return RX derived pointer
All symbol addresses can be derived from the RX capability of the
module (l_map_start). For RW object symbols pointer will have to
be rederived from l_rw_start.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy e841326457 cheri: elf: Use RW permissions for l_ld when needed
The dynamic section of an executable needs to be written to set the
DT_DEBUG entry for debuggers (unless the target has some other place
to store r_debug). For this reason we make l_ld writable whenever
the dynamic section is writable.

The ld.so l_ld is kept RX, since it does not have DT_DEBUG.
(Note: relocating the dynamic section is not allowed on cheri and
that's the only other reason glibc would write to it.)
2022-10-12 14:22:03 +01:00
Szabolcs Nagy a1d26f7b1d aarch64: morello: add D_PTR_RW
Writable version of D_PTR, required for updating GOT[1] and GOT[2].
2022-10-12 14:22:03 +01:00
Szabolcs Nagy e6a2c4c4bb aarch64: morello: fix relative relocs
use the reloc processing code from cheri-rel.h which already
supports separate RX and RW capabilities per module.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 87dffcda13 cheri: Setup RX, RW capabilities for static linking
At least tls image access requires RX capability of the main link_map.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy a66d563c9e cheri: elf: Setup per module RX and RW capabilities
The l_map_start and l_rw_start of the ld.so and exe comes from the auxv
since they are normally mapped by the kernel.  Some generic code had to
be modified so l_map_start is propagated and not overwritten when it is
recomputed.

The l_rw_range should exclude the relro region, but in libc.so and
ld.so this does not work: symbols are accessed before relro is applied
and then the permission should be writable.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 74085ebc1f aarch64: morello: Add elf_machine_rtld_base_setup
Use a new hook to do the rtld bootstrap map base address and root
capability setup on CHERI.

This will be needed to use separate per module RX and RW root caps.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 1b0716e083 elf: add dl_{rx,rw}_ptr to derive addresses within a map
To derive pointers within a module from the per module RX and RW caps.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 55ada9157d cheri: elf: add an RW capability to link_map
For each module keep an RX and an RW root capability.  Use the existing
l_map_start for RX (covering all load segments) and add l_rw_start for
RW (covering all writable load segments).

For relocation processing, we also need individual RW ranges to decide
which objects need to be derived from RW and RX capabilities.  In
practice most modules have exactly one RW segment and it's unlikely
that any module needs more than four distinct ranges to tightly cover
the RW mappings.

Only added on CHERI targets so always has to be used behind ifdef.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 11e0080cd5 aarch64: morello: Use purecap ELF entry ABI in _start
The purecap ELF entry is special: passes separate argc, argv, envp,
auxv in registers instead of on the stack.

The ldso internal _dl_start still expects continuous argc, argv, envp,
auxv, so that's emulated.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy bb624b6c43 aarch64: morello: use RW and RX capabilities for static start code
For each module there will be separate RW and RX capabilities that
cover the writable and all load segments respectively.

Prepare the relative reloc processing in static start code for such
separate capabilities.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 8d2bab6e17 cheri: change __libc_start_main prototype
The prototype of __libc_start_main is changed to

  void
  __libc_start_main (int main (int, char **, char **, void *),
                     int argc, char **argv, char **envp, void *auxv,
                     void rtld_fini (void), void *sp);

so envp is passed down separately and the unused init, fini args are
dropped.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy d5f9769d53 aarch64: morello: rewrite start code in C 2022-10-12 14:22:03 +01:00
Szabolcs Nagy 009e1fd306 aarch64: morello: remove ELF_MACHINE_START_ADDRESS
The start address (l_entry) is now a capability so no need to fix it.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy a3085f72f8 cheri: elf: make l_entry a capability
Previously the entry address was fixed up to be a capability before
using it so l_entry could be ElfW(Addr), but the code is simpler and
more consistent if l_entry is a capability throughout:

The AT_ENTRY auxv entry is specified to be a capability and a number
if internal l_entry usage is simpler if it is elfptr_t.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 456f4dd6e5 TODO: cheri: elf: Add new AT_* auxv types
Used for purecap ABI.

TODO: squash into
091bcf0e1c cheri: elf: Add new a_type entries
2022-10-12 14:22:03 +01:00
Szabolcs Nagy a2d8296886 TODO: drop unused u64 reloc addr from lazy relocs
squash into
3eb1c569eb TODO(l_addr): aarch64: morello: dynamic linking support
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 73f47b6560 TODO: aarch64: morello: fix abs sym reloc
TODO: squash into
3eb1c569eb TODO(l_addr): aarch64: morello: dynamic linking support
2022-10-12 14:22:03 +01:00
Szabolcs Nagy bfc66c9896 TODO: cheri: elf: turn back to addresses: l_map_end, l_text_end, l_relro_start
TODO: squash into
51fe1e15ed TODO(incomplete): cheri: rtld: more elfptr_t in linkmap struct
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 284e4f1755 aarch64: morello: update HWCAP2_MORELLO value
Unfortunately this will keep changing during the development
as upstream linux did not want to reserve a bit for morello.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy afbfdd28bd TODO(uapi): narrow capability in mmap and mremap
This is a temporary workaround.

length is rounded up to pagesize and don't use exact bound (bounds
will be larger if exact value is not representable).

TODO: kernel should do this
2022-10-12 14:22:03 +01:00
Szabolcs Nagy c3d2d246c5 static: glibc-bug: NL_CURRENT_INDIRECT is broken so disable it
nl_langinfo_l ignores its locale argument with NL_CURRENT_INDIRECT
which is wrong when that argument does not match the current thread's
locale.

upstream glibc is not tested with static linking so this is not found.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 94f15a4231 TODO: cheri: printf: fix unused variable warning
warning happens in non-purecap build.

TODO: squash into original cheri printf change
2022-10-12 14:22:03 +01:00
Szabolcs Nagy cb2ecefc21 cheri: use getauxptr in iconv/tst-gconv-init-failure test
On CHERI targets getauxval cannot return a valid pointer.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 85c6eba32a Fix OOB read in stdlib thousand separator handling
__correctly_grouped_prefixmb only worked with thousands_len == 1,
otherwise it read past the end of cp or thousands.

Avoid OOB access by considering thousands_len when initializing cp.

On morello with strict bounds checking this fixes

FAIL: stdlib/tst-strtod4
FAIL: stdlib/tst-strtod5i

both of which set cs_CZ.UTF-8 locale that has 3 byte thousands_len.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy 059dd1983c elf: Fix _dl_debug_vdprintf stack buffer underflow
When printing numbers the alloca buffer size did not consider the
optional width parameter for padding. The width is used e.g. by
_dl_map_object_from_fd which passes '(int) sizeof (void *) * 2'
which can be larger than the buffer size on systems where
sizeof (void *) >= 2 * sizeof (unsigned long).  But even if large
width is not used currently it is better to handle it to avoid
surprises.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy ed157fcccd Fix missing NUL terminator in stdio-common/scanf13 test
sscanf is only defined on nul terminated string input, but '\0' was
missing in this test which caused _IO_str_init_static_internal to
read OOB on the stack when computing the bounds of the string.
2022-10-12 14:22:03 +01:00
Szabolcs Nagy fbc8167346 Fix malloc/tst-scratch_buffer
The test used scratch_buffer_dupfree incorrectly:

- The passed in size must be <= buf.length.
- Must be called at most once on a buf object since it frees it.
- After it is called buf.data and buf.length must not be accessed.

All of these were violated, the test happened to work because the
buffer was on the stack, which meant the test copied out-of-bounds
bytes from the stack into a new buffer and then compared those bytes.

Run one test and avoid the issues above.
2022-10-12 12:54:07 +01:00
Szabolcs Nagy 37cfa707b0 Fix elf/tst-tls20 stack OOB access
Off-by-one error found on morello with strict stack bounds.
2022-10-12 12:54:07 +01:00
Szabolcs Nagy 00f9cd1a70 Fix off-by-one error in iconv/tst-iconv-mt
The iconv buffer sizes must not include the \0 string terminator.
(When \0 cannot be part of a valid character encoding glibc iconv
would copy it to the output as expected, but then later the explicit
output termination with *outbufpos = '\0' is out of bounds.)
2022-10-12 12:54:07 +01:00
Carlos Eduardo Seo 2f3bf4cf63 TODO(drop): aarch64: morello: CPU feature detection for Morello
Initial detection of Arm Morello architecture from the HWCAP2 bit and CPU
identification from MIDR_EL0.

TODO: not needed?
- lp64 does not have to detect
- purecap can assume morello
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ccce788403 TODO(gprof): aarch64: morello: add gprof profiling support to asm
Assembly prologue code with mcount call for gprof instrumentation.

TODO: untested, likely needs further runtime updates too.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 5ef98a9900 TODO(sprof): cheri: disable profiling shared libraries
This is needed now to avoid referencing abort in ld.so.

TODO: Fixing shared library profiling for capabilities requires
type fixes so capabilities are not stored into shared memory
(maybe purecap layout can match the lp64 one and then no file format
and external tooling change is required.)
TODO: Proper fix also depends on _dl_runtime_profile plt entry
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a8989aef06 TODO(audit): aarch64: morello: add _dl_runtime_profile entry
Required for LD_AUDIT PLT hooks and shared library profiling.

incomplete, untested.

TODO: needs La_aarch64* layout definition for morello
TODO: needs to save c9 for vararg abi
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 7f9c78bc3a TODO(pldd): cheri: elf: fix pldd to compile for purecap abi
Adjust types in the E(*) structs to support capabilities.

TODO: purecap pldd should refuse to deal with lp64 and ELF32 processes.
the code for the 32bit case should be disabled.
TODO: a correct fix requires support for all abis that can run on the
same system (purecap, lp64 and ELF32 too).
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 7dac60585d cheri: Update libc.abilist for getauxptr
Updates libc.abilist files for getauxptr to version 2.37.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 6cca02f732 cheri: elf: Fix tst-auxv for Morello 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2b9e393156 TODO(api): cheri: misc: Implement new function getauxptr for CHERI capabilities
New function to return values from the auxiliary vector as
capabilities. This is the same as implemented by other C libraries.

TODO: agree about exact semantics across libcs
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d74b162292 TODO(uapi): aarch64: morello: add HWCAP2_MORELLO
TODO: the value will change
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo f4fe4afdf0 support: Fix TEST_COMPARE for uintptr_t.
TEST_COMPARE should allow comparison between two capability values.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 3be82efc58 cheri: stdio-common: add support for printing CHERI capabilities
This adds a new modifier %#p for printing capability information
according to the CHERI C Programming guide:

https://github.com/CTSRD-CHERI/cheri-c-programming/wiki/Displaying-Capabilities

A %#p option in printf will display:

  <address> [<permissions>,<base>-<top>] (<attr>)

   * address: Virtual address of capability displayed as a hexadecimal
     value with a 0x prefix.
   * permissions: Zero or more of the following characters:
      r: LOAD permission
      w: STORE permission
      x: EXECUTE permission
      R: LOAD_CAP permission
      W: STORE_CAP permission
      E: EXECUTIVE permission (Morello only)
   * base: Lower bound of capability displayed as a hexadecimal value
     with a 0x prefix.
   * top: Upper bound of capability plus 1 displayed as a hexadecimal
     value with a 0x prefix.
   * attr: Zero or more of the following comma-separated attributes. If
     none of the attributes are present, this field is omitted (along
     with the enclosing parentheses/brackets).
      invalid: Capability's tag is clear.
      sentry: Capability is a sealed entry.
      sealed: Capability is sealed with a type other than the sealed
              entry object type.

A %p option in printf will display the capability value (address) normally.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo cec148df6f cheri: nptl: Check user provided stack for PCS constraints
In pthread_attr_setstack fail with EINVAL if the input stack does not
meet the PCS constraints.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d8173e2496 TODO(uapi): cheri: Fix sigevent ABI
TODO: depends on kernel sigevent definition update.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy bb648757f0 TODO(morello): cheri: fix posix timers
We need to distinguish timerids that are small integers returned by
the kernel and timerids that are pointers to struct timer. The existing
pointer tagging does not work for CHERI because of the pointer shift.

Simply use the top bit without shift to tag pointers. This still relies
on the top byte ignore of aarch64 (the top byte does not affect the
capability representation) and that pointers are not tagged for other
reasons (like HWASAN).

TODO: this is morello specific and does not work for generic cheri.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 989eb50954 TODO(api): cheri: elfptr_t in public api for unwinder
TODO: needs agreement across cheri libcs
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 93ab84cd80 TODO(l_addr): cheri: rtld: elfptr_t fix in rtld.c program header processing
TODO: depends on l_addr design
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 3eb1c569eb TODO(l_addr): aarch64: morello: dynamic linking support
Add morello specific dl-machine.h.

Add morello dynamic relocation processing support for purecap ABI.
Only support R_AARCH64_NONE, R_AARCH64_ABS64 and R_AARCH64_RELATIVE
dynamic relocs from the lp64 abi. This required several APIs to
change ElfW(Addr) to uintptr_t including in generic code (where
elfptr_t used to cover both traditional and capability abis).

RELATIVE and IRELATIVE relocs use a helper function to construct a
capability.  Also fixed the IRELATIVE handling for static linking.

Use new machine routines on morello for load address computation so it
is a valid capability:

 void *elf_machine_runtime_dynamic (void)
 uintptr_t elf_machine_load_address_from_args (void *)

The ld.so load address is either AT_BASE or if it is invoked as a
command then derived from AT_PHDR or _DYNAMIC (pcc).

ELF_MACHINE_START_ADDRESS is updated to turn the ElfW(Addr) user entry
into a capability based on l_addr.

TODO: __tls_get_addr should return a bounded pointer.
(in case traditional tls is defined for morello)

note: tls_index struct that is used for trad tls is changed for morello.
(this is abi once trad tls is defined for morello)

arguably _dl_make_tlsdesc_dynamic should set up tlsinfo.ti_size too.
(but it's better to avoid changing the generic code)

TODO: use cheri auxv entries to derive ld.so capabilities, this will
      require separate RW and RX base pointers instead of single l_addr.
      AT_BASE will not be a capability covering ld.so.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 6f93421a5f aarch64: rtld: avoid loading incompatible binaries
Prevent lp64 ld.so loading purecap binaries.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 392f32c841 aarch64: morello: add lazy binding entry code 2022-08-05 19:45:19 +01:00
Szabolcs Nagy d15c9f859f TODO(l_addr): cheri: rtld: elfptr_t fixes in dl-map-segments.h
Ensure map_end is derived from map_start.

Use stricter mmap bounds when using MAP_FIXED:
c->mapend is aligned up to pagesize, but the capability representing
the mapping has bounds that are not page aligned, so use c->dataend
that is the actual end bound of the loaded segment.

TODO: l_addr of a pde is 0 but it should cover the exe.
this will have to be fixed. (and must not use morello asm)
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 51fe1e15ed TODO(incomplete): cheri: rtld: more elfptr_t in linkmap struct
TODO: requires follwup patches to make sure all usage of the fields
preserve capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2b1192cae0 cheri: elf: fix pointer provenance of l_tls_initimage 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 06fda78445 cheri: rtld: fix _dl_start to return elfptr_t
Functions returning a pointer to the user entry need to use an int type
that can represent pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a0cbaef87c aarch64: morello: rtld: add ld.so _start code
The purecap version of aarch64 dl-start.S. Note: self relocation of
ld.so is handled by the rtld bootstrap code.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4f45607de9 aarch64: morello: rtld: define DL_RO_DYN_SECTION
The dynamic section cannot be relocated to hold pointers in place.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy c755eefac5 aarch64: morello: fix ldconfig for purecap abi
Add purecap ld cache flag. Add the purecap ld.so name to known names.
Handle lib64c system library paths. And set the purecap abi flag on
cache entries.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy c779cc818e aarch64: morello: disable the vpcs test
The asm code of the test is for lp64 ABI only.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo ec5240f821 aarch64: morello: add purecap ucontext support
Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
implementations accordingly.

Note: mcontext layout follows the linux sigcontext struct, in userspace
*context functions rely on the c registers stored in the extension area
and ignore the mcontext fields for x registers.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 89ab8ac121 aarch64: morello: add purecap setjmp/longjmp
Similar to lp64 setjmp/longjmp, but handles capability registers.
Save q regs instead of d regs to simplify the offset computation.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 257781e305 cheri: malloc: avoid switch over uintptr_t
We should use a type that guarantees to represent all address bits.
In CHERI C this would be ptraddr_t, but we use unsigned long for now
not to cause regressions on other targets where this type is missing.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 6af67120e8 cheri: malloc: fix alignment logic in obstack
If sizeof(ptrdiff_t) < sizeof(void*) the alignment logic was wrong
(incorrectly assumed that base was already sufficiently aligned).

Use more robust alignment logic: this one should work on any target.
Note: this is an installed header so it must be namespace clean and
portable.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 84068c087b cheri: malloc: use uintptr_t in alloc_buffer
This is the right type as the values hold pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4064e7a4fc cheri: malloc: align up without breaking capability in memalign 2022-08-05 19:45:19 +01:00
Szabolcs Nagy b3d26f52f7 cheri: malloc: Disable pointer protection
Such arithmetic invalidates capabilities so this security measure does
not work for CHERI.

Note: the architecture makes it hard to corrupt pointers in malloc
metadata, but not impossible: current allocation bounds include the
metadata and capabilities are not revoked after free. These issues can
be fixed by a capability aware malloc.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 0205012984 cheri: malloc: use intptr_t to preserve capabilities
Avoid integer casts and arithmetics that invalidates capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d0db1e8a12 cheri: fix invalid pointer use after realloc in localealias
This code updates pointers to a reallocated buffer to point to the new
buffer.  It is not conforming (does arithmetics with freed pointers),
but it also creates invalid capabilities because the provenance is
derived from the original freed pointers instead of the new buffer.

Change the arithmetics so provenance is derived from the new buffer.
The conformance issue is not fixed.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 68822420a6 cheri: fix pointer tagging in tsearch
USE_MALLOC_LOW_BIT should work for capabilities too, but we need to
ensure that pointer provenance is right: the red/black flag is
computed as uintptr_t, but with uintptr_t | uintptr_t it's not clear
which side provides the provenance.

So use unsigned int type for the flag (which is the type used in case
of !USE_MALLOC_LOW_BIT anyway), then unsigned int | uintptr_t works.

The type of RED is corrected too to match unsigned int.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 159a76a8dd cheri: fix qsort for capabilities
On capability targets avoid copying pointers via unsigned long.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy f7842f9392 cheri: wctype: turn wctype_t into a pointer
Make wctype_t a pointer so dereferencing it works. wctrans_t is already
a pointer and used the same way.

Existing targets are not affected, only capability targets where this
is necessary.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 5778537ccd cheri: rseq: remove const to avoid readonly permission
Using const on the definition does not work for a pure capability ABI:
the capability permissions when accessing the object will be read only.

Use a hack to hide the public declaration in the TU where the const
objects are initialized. (This should work on non-capability targets
too, but to err on the safe side only enable the hack on capability
targets.)
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 01faa1bcd4 aarch64: morello: nptl: fix thread pointer setup 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 63bee6f155 aarch64: morello: nptl: fix pthread types for 128 bit pointers 2022-08-05 19:45:19 +01:00
Szabolcs Nagy f29dda01e0 cheri: nptl: fix pthread_attr_t alignment
Alignment of the public definition did not match the internal layout.
Ensure that the type is at least pointer aligned.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy b38585301d cheri: nptl: fix thread ID types for capabilities 2022-08-05 19:45:19 +01:00
Szabolcs Nagy c8f1fc9d94 cheri: Implement 128-bit atomics
Arm Morello requires 128-bit atomics.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 7880bbd374 cheri: elf: Use elfptr_t in _dl_protect_relro
start/end should be capabilities now that l_addr is a capability.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d63bc8be87 cheri: elf: elfptr_t fixes for preinit/init/fini array
According to the ELF spec:

 "Each element of this array is a pointer to a function to be executed
  by the dynamic linker."

 "Note that the address of a function need not be the same as a pointer
  to a function as defined by the processor supplement."

so these should be accessed via uintptr_t type instead of ElfW(Addr).
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d257d001c3 TODO(l_addr): cheri: in static exe initialize l_addr to a zero capability
The base should be 0, but also a valid capability. Initialize to a zero
capability instead of relying on AT_BASE.

TODO: this is a hack. we will need stricter bounds and possibly separate
l_addr and bounds info.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 8536404f41 cheri: elf: use elfptr_t for auxv parsing 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 8022e6934e cheri: elf: Adjust Elf64_auxv_t for capabilities
The Elf64_auxv_t needs to be adjusted for the new capability size.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a4f02d3f68 cheri: elf: make l_addr a capability
l_addr should be a capability on Morello. This is synchronized with the
same variable in gdb.

Use elfptr_t when ElfW(Addr) represents a runtime pointer that may be
dereferenced.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 091bcf0e1c cheri: elf: Add new a_type entries
The Morello Pure Capability kernel uABI defines new a_type entries:

https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-capability-kernel-user-Linux-ABI-specification#auxiliary-vector-auxv
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 823a9cb203 elf: add EF_AARCH64_CHERI_PURECAP 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo bb5bc76947 elf: add Arm Morello relocations to elf.h 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 110733491a cheri: fix __minimal_malloc
The linker created _end symbol does not have the right bounds, so
don't try to reuse leftover memory at the end of the .data section.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 4275aff6b8 cheri: fix static linking TLS setup
Use l_addr provenance for TLS initimage.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy cb79f5073a cheri: fix static linking early allocation
Store mmap result to intptr_t instead of long.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 887a33c6bb TODO(gcc): cheri: work around a gcc bug in _dl_setup_stack_chk_guard
morello purecap gcc in some cases inlines 16byte memcpy as a capability
load, which is wrong if the source or dest may be unaligned.

stack guard only needs random for the address portion since only that
part is compared, so 8 byte is enough with 64 bit addresses, but the
current code is only right on little endian systems.

TODO: drop when gcc is fixed
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ff2cd89ebb cheri: don't use dl_random for pointer mangling
Pointer mangling cannot be supported on capability architectures.
And there is not enough bytes in dl_random for 128 bit pointers.

Stack guard is still loaded from dl_random: stack protection is
unlikely to be useful on a capability architecture, but it works.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 347f7e2ac1 TODO(relro): cheri: make __attribute_relro a nop
relro does not work in the libc, because capabilities are readonly
even before the page protection is applied.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo d77736297a TODO(ddc): aarch64: morello: purecap support in the CSU
Purecap ABI versions of start.S, crti.S and crtn.S.

TODO: must not use ddc but caps from auxv
TODO: start.S: dynamic linked case is now detected by x0 != 0 (ld.so passes
__rtld_fini there), but the value of c0 on entry is not abi, just that
it has to be passed back to the libc start code in c5, so ideally the
linker should be fixed to reliably emit __rela_dyn_start when a static
exe must self relocate.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2d0278e6d7 cheri: aarch64: Add header for CHERI permissions
New file containing the capability permission bits.

The capability permission bits are defined in the Arm Architecture
Reference Manual Suplement- Morello for A-Profile Architecture:

https://developer.arm.com/documentation/ddi0606/latest
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 822571c5b1 TODO(uapi): aarch64: morello: use non-ifunc gettimeofday
TODO: Remove this once morello has vdso gettimeofday.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9f92fe592b TODO(uapi): aarch64: morello: make brk always fail
TODO: drop this once linux brk always fails.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy fb41a562bf TODO(uapi): cheri: fix clone_args
Current clone_args does not support 128 bit pointers.

TODO: the fix is incomplete (missing clone3 abi checks) and has to be
aligned with purecap clone3 struct layout.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ed90470cc0 aarch64: morello: fix missing variadic argument in fcntl
In fcntl va_arg is currently used even if the caller did not pass
any variadic arguments. This is undefined behaviour and does not
work with the Morello purecap ABI, so use a helper macro.

When the argument is missing, the result of the helper macro is
arbitrary as it will be ignored by the kernel, we just have to
ensure it does not cause a runtime crash.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d23dfc0324 aarch64: morello: fix vfork
No need to set the child stack to sp, 0 means the parent stack is used.
This avoids purecap specific ifdefs in vfork.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo ff371935db aarch64: morello: add purecap syscall support
Support the Morello Linux purecap syscall ABI.  The macro definitions
are moved to a morello specific sysdep.h to avoid cluttering the
aarch64 one.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9ef71c0be0 aarch64: fix VDSO setup to only apply to known ABIs
New syscall ABI requires different VDSO support code.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2d17978865 TODO(api): cheri: fix syscall return type
TODO: this affects API (syscall return type is long)
so breaks portability and requires doc updates.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy fbdd679dfe aarch64: morello: string: memcpy
from arm optimized-routines morello branch.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy dd44f97920 aarch64: morello: string: memset
memset from arm optimized-routines morello branch.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 30d6fef4c7 aarch64: morello: string: dummy c memcmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 05c7fd2959 aarch64: morello: string: dummy c memchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy df91141390 aarch64: morello: string: dummy c memrchr 2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 2e1fc3bdee aarch64: morello: purecap rawmemchr
Modified rawmemchr to support Arm Morello Capabilities.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 0ae704caef aarch64: morello: string: dummy c strchrnul 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 538a80eaf4 aarch64: morello: string: dummy c strlen 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 42ab155048 aarch64: morello: string: dummy c strnlen 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 424b0ffa6f aarch64: morello: string: dummy c strcpy and stpcpy 2022-08-05 19:45:19 +01:00
Szabolcs Nagy bec24b66e8 aarch64: morello: string: dummy c strcmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy d496a3dd55 aarch64: morello: string: dummy c strncmp 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 750a8bb78b aarch64: morello: string: dummy c strchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 3a0ce7aeb0 aarch64: morello: string: dummy c strrchr 2022-08-05 19:45:19 +01:00
Szabolcs Nagy eca95865e3 aarch64: morello: string: dummy c strspn
avoids out of bound access of the generic implementation.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy e8728f756a aarch64: morello: string: dummy c strcspn
avoids out of bounds access of the generic implementation.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo db037e48fb aarch64: morello: update sysdep.h for purecap ABI
Add macro definitions for purecap ABI in sysdep.h.
2022-08-05 19:45:19 +01:00
Carlos Eduardo Seo 434271f132 TODO(spec): cheri: __LP64__ is not defined for purecap ABI
TODO: there is no good ABI macro to check, for now we assume
__CHERI_PURE_CAPABILITY__ implies 64 bit long, 64 bit address and
128 bit pointer.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 93c5545300 cheri: headers: Define {u}intptr_t and {u}intcap_t for CHERI
The CHERI pure capability programming model for C requires special
definition of {u}intptr_t.

Only the pure capability model is supported for hosted compilation,
but for freestanding compilation there is limited support for other
(hybrid capability) programming models too, which require new
{u}intcap_t type definitions.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 77777d453d aarch64: morello: use separate c++-types.data
The c++ mangling ABI for intptr_t and pthread_t are different on
morello.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 78cc285037 aarch64: morello: use separate localplt data for morello
There is no longer PLT reference to matherr in libm.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy ccec84f408 aarch64: morello: Add separate lp64 and morello linux abilists
The base symbol version is 2.36.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9e6811dafb aarch64: morello: Add purecap abi-variants on linux 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 18fb025070 aarch64: morello: configure change for purecap abi
Detect default-abi and add aarch64-purecap make variable.

Purecap abi sets HIDDEN_VAR_NEEDS_DYNAMIC_RELOC and unsets
SUPPORT_STATIC_PIE.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 4fc4072240 aarch64: morello: Use separate lp64 and morello sysdep directories
Provide separate directories for lp64 and purecap abi related sysdep
functionality.

purecap may be better name than morello, but we started with morello
and that is more future compatible with alternative cheri-like
extensions on top of aarch64.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 570f6858b7 aarch64: morello: add purecap support to build-many-glibcs.py
aarch64-linux-gnu compiler is a lp64,purecap multilib gcc and
supported glibc variants:

  aarch64-linux-gnu
  aarch64-linux-gnu-purecap
  aarch64-linux-gnu-purecap-nopie

aarch64-linux-gnu_purecap compiler is a default purecap gcc, with
supported glibc variants:

  aarch64-linux-gnu_purecap
  aarch64-linux-gnu_purecap-nopie

purecap libgomp and libitm builds fail so disabled for now.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 084ac620b1 aarch64: Use fewer ifdefs in bits/fcntl.h
This simplifies adding the Morello purecap abi target.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2adfa58c4f aarch64: cleanup MOVL definition in sysdep.h
PTR_REG is for ILP32, there is no point using it under __LP64__.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy f8335dc69a libio: adjust _IO_FILE / _IO_FILE_complete for 128 bit pointers
The size of the reserved space has to be adjusted because it underflows
with 16 byte pointers.  With the new value there should be enough space
for 2 more pointers in the struct on CHERI targets.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 1cb2ecf162 cheri: Fix elf/tst-dlmodcount test
switch statement does not work for intptr_t, use a large int type
that's guaranteed to work.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy a87b3fcbb3 Fix the symbolic link of multilib dirs
If dir contains several / then 'ln -s . $dir' does not link it to the
current directory. Use the existing rellns.sh script to compute the
correct relative path to .
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 30719666f8 cheri: Fix pointer alignment in fts
ALIGN has to work on pointers and the code assumed unsigned long can
always represent pointers.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 1943345fa3 cheri: Fix invalid pointer deref in wcpcpy_chk
Accessing src via the dest pointer is invalid.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy dec33ea23f cheri: Fix invalid pointer deref in wcscpy_chk
The src pointer is const, accessing dest via it fails on CHERI targets.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy db674b0d98 Fix string/tester alignment code
The code assumed pointers can be converted to unsigned long without
loss of information.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy d8ecbea3fc Fix resource/bug-ulimit1 test
ulimit is a variadic function and the second argument must have type
long (or unsigned long).
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 14c8e3a355 Fix stdlib/test-dlclose-exit-race to not hang 2022-08-05 19:45:19 +01:00
Szabolcs Nagy 2f90599f89 aarch64: fix extension header write in getcontext and swapcontext
The extension header is two 32bit words and in the last header both
should be 0. There is plenty space in the __reserved area, but it's
better not to write more than we mean to.
2022-08-05 19:45:19 +01:00
Szabolcs Nagy 9ed39f584e aarch64: don't build wordcopy
Use an empty wordcopy.c to avoid building the generic one.
It does not seem to be used anywhere.
2022-08-05 19:45:09 +01:00
Szabolcs Nagy 9f22387b95 scripts: Use bool in tunables initializer 2022-08-05 15:28:42 +01:00
Florian Weimer c74bb93cfd dlfcn: Pass caller pointer to static dlopen implementation (bug 29446)
Fixes commit 0c1c3a771e ("dlfcn: Move
dlopen into libc").

(cherry picked from commit ed0185e412)
2022-08-04 17:57:11 +02:00
H.J. Lu 33f1b4c145 wcsmbs: Add missing test-c8rtomb/test-mbrtoc8 dependency
Make test-c8rtomb.out and test-mbrtoc8.out depend on $(gen-locales) for

  xsetlocale (LC_ALL, "de_DE.UTF-8");
  xsetlocale (LC_ALL, "zh_HK.BIG5-HKSCS");

Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e03f5ccd6c)
2022-08-01 10:02:06 -03:00
Tom Honermann c3fda489cf stdlib: Suppress gcc diagnostic that char8_t is a keyword in C++20 in uchar.h.
gcc 13 issues the following diagnostic for the uchar.h header when the
-Wc++20-compat option is enabled in C++ modes that do not enable char8_t
as a builtin type (C++17 and earlier by default; subject to _GNU_SOURCE
and the gcc -f[no-]char8_t option).
  warning: identifier ‘char8_t’ is a keyword in C++20 [-Wc++20-compat]
This change modifies the uchar.h header to suppress the diagnostic through
the use of '#pragma GCC diagnostic' directives for gcc 10 and later (the
-Wc++20-compat option was added in gcc version 10).  Unfortunately, a bug
in gcc currently prevents those directives from having the intended effect
as reported at https://gcc.gnu.org/PR106423.  A patch for that issue has
been submitted and is available in the email thread archive linked below.
  https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598736.html

(cherry picked from commit 825f84f133)
2022-08-01 10:02:00 -03:00
256 changed files with 9462 additions and 331 deletions
+1 -1
View File
@@ -1002,7 +1002,7 @@ endef
define make-link-multidir
$(patsubst %/,cd %,$(objpfx)); \
$(addprefix $(abspath $(..)scripts/mkinstalldirs) ,$(dir $(multidir))); \
$(LN_S) . $(multidir) 2> /dev/null; \
$(SHELL) $(abspath $(..)scripts/rellns-sh) . $(multidir) 2> /dev/null; \
test -L $(multidir)
endef
else
+7
View File
@@ -4,6 +4,13 @@ See the end for copying conditions.
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
Version 2.36.1
The following bugs are resolved with this release:
[29446] _dlopen now ignores dl_caller argument in static mode
Version 2.36
+1 -1
View File
@@ -62,7 +62,7 @@
#define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
#define __CPU_MASK_TYPE __ULONGWORD_TYPE
#ifdef __LP64__
#if defined __LP64__ || defined __CHERI_PURE_CAPABILITY__
/* Tell the libc code that off_t and off64_t are actually the same type
for all ABI purposes, even if possibly expressed as different base types
for C type-checking purposes. */
+19 -3
View File
@@ -132,15 +132,15 @@ call_init (int argc, char **argv, char **env)
the same file. */
if (ELF_INITFINI && l->l_info[DT_INIT] != NULL)
DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr,
DL_CALL_DT_INIT(l, dl_rx_ptr (l, l->l_info[DT_INIT]->d_un.d_ptr),
argc, argv, env);
ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
if (init_array != NULL)
{
unsigned int jm
= l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
ElfW(Addr) *addrs = (void *) (init_array->d_un.d_ptr + l->l_addr);
= l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (elfptr_t);
elfptr_t *addrs = (void *) dl_rx_ptr (l, init_array->d_un.d_ptr);
for (unsigned int j = 0; j < jm; ++j)
((dl_init_t) addrs[j]) (argc, argv, env);
}
@@ -210,11 +210,16 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
MAIN_AUXVEC_DECL),
int argc,
char **argv,
#ifdef LIBC_START_MAIN_ENVP_ARG
char **envp,
#endif
#ifdef LIBC_START_MAIN_AUXVEC_ARG
ElfW(auxv_t) *auxvec,
#endif
#ifndef LIBC_START_MAIN_NO_INITFINI_ARG
__typeof (main) init,
void (*fini) (void),
#endif
void (*rtld_fini) (void),
void *stack_end)
__attribute__ ((noreturn));
@@ -233,15 +238,24 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
int argc, char **argv,
#ifdef LIBC_START_MAIN_ENVP_ARG
char **envp,
#endif
#ifdef LIBC_START_MAIN_AUXVEC_ARG
ElfW(auxv_t) *auxvec,
#endif
#ifndef LIBC_START_MAIN_NO_INITFINI_ARG
__typeof (main) init,
void (*fini) (void),
#endif
void (*rtld_fini) (void), void *stack_end)
{
#ifndef SHARED
#ifdef LIBC_START_MAIN_ENVP_ARG
char **ev = envp;
#else
char **ev = &argv[argc + 1];
#endif
__environ = ev;
@@ -358,11 +372,13 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
#ifndef LIBC_START_MAIN_NO_INITFINI_ARG
if (init != NULL)
/* This is a legacy program which supplied its own init
routine. */
(*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
else
#endif
/* This is a current program. Use the dynamic segment to find
constructors. */
call_init (argc, argv, __environ);
+1 -1
View File
@@ -125,7 +125,7 @@ __libc_setup_tls (void)
/* Remember the values we need. */
memsz = phdr->p_memsz;
filesz = phdr->p_filesz;
initimage = (void *) phdr->p_vaddr + main_map->l_addr;
initimage = (void *) dl_rx_ptr (main_map, phdr->p_vaddr);
align = phdr->p_align;
if (phdr->p_align > max_align)
max_align = phdr->p_align;
+1 -2
View File
@@ -28,13 +28,12 @@ __wcpcpy_chk (wchar_t *dest, const wchar_t *src, size_t destlen)
{
wchar_t *wcp = (wchar_t *) dest - 1;
wint_t c;
const ptrdiff_t off = src - dest + 1;
do
{
if (__glibc_unlikely (destlen-- == 0))
__chk_fail ();
c = wcp[off];
c = *src++;
*++wcp = c;
}
while (c != L'\0');
+7 -27
View File
@@ -24,36 +24,16 @@ wchar_t *
__wcscpy_chk (wchar_t *dest, const wchar_t *src, size_t n)
{
wint_t c;
wchar_t *wcp;
wchar_t *wcp = dest;
if (__alignof__ (wchar_t) >= sizeof (wchar_t))
do
{
const ptrdiff_t off = dest - src - 1;
wcp = (wchar_t *) src;
do
{
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *wcp++;
wcp[off] = c;
}
while (c != L'\0');
}
else
{
wcp = dest;
do
{
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *src++;
*wcp++ = c;
}
while (c != L'\0');
if (__glibc_unlikely (n-- == 0))
__chk_fail ();
c = *src++;
*wcp++ = c;
}
while (c != L'\0');
return dest;
}
+1 -1
View File
@@ -90,7 +90,7 @@ compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1);
void *
__dlopen (const char *file, int mode, void *dl_caller)
{
return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
return dlopen_implementation (file, mode, dl_caller);
}
void *
+3
View File
@@ -210,6 +210,9 @@ print_entry (const char *lib, int flag, uint64_t hwcap,
case FLAG_AARCH64_LIB64:
fputs (",AArch64", stdout);
break;
case FLAG_AARCH64_PURECAP:
fputs (",purecap", stdout);
break;
/* Uses the ARM soft-float ABI. */
case FLAG_ARM_LIBSF:
fputs (",soft-float", stdout);
+4 -6
View File
@@ -119,11 +119,10 @@ call_destructors (void *closure)
if (map->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (map->l_addr
+ map->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
elfptr_t *array =
(elfptr_t *) dl_rx_ptr (map, map->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
/ sizeof (elfptr_t));
while (sz-- > 0)
((fini_t) array[sz]) ();
@@ -131,8 +130,7 @@ call_destructors (void *closure)
/* Next try the old-style destructor. */
if (map->l_info[DT_FINI] != NULL)
DL_CALL_DT_FINI (map, ((void *) map->l_addr
+ map->l_info[DT_FINI]->d_un.d_ptr));
DL_CALL_DT_FINI (map, dl_rx_ptr (map, map->l_info[DT_FINI]->d_un.d_ptr));
}
void
+1 -1
View File
@@ -105,7 +105,7 @@ _dl_find_object_from_map (struct link_map *l,
if (ph->p_type == DLFO_EH_SEGMENT_TYPE)
{
atomic_store_relaxed (&result->eh_frame,
(void *) (ph->p_vaddr + l->l_addr));
(void *) dl_rx_ptr (l, ph->p_vaddr));
#if DLFO_STRUCT_HAS_EH_COUNT
atomic_store_relaxed (&result->eh_count, ph->p_memsz / 8);
#endif
+4 -5
View File
@@ -133,11 +133,10 @@ _dl_fini (void)
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (l->l_addr
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
ElfW(Addr) v = l->l_info[DT_FINI_ARRAY]->d_un.d_ptr;
elfptr_t *array = (elfptr_t *) dl_rx_ptr (l, v);
unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
/ sizeof (elfptr_t));
while (i-- > 0)
((fini_t) array[i]) ();
}
@@ -145,7 +144,7 @@ _dl_fini (void)
/* Next try the old-style destructor. */
if (ELF_INITFINI && l->l_info[DT_FINI] != NULL)
DL_CALL_DT_FINI
(l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr);
(l, dl_rx_ptr (l, l->l_info[DT_FINI]->d_un.d_ptr));
}
#ifdef SHARED
+8 -7
View File
@@ -53,7 +53,8 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
- the others in the DT_INIT_ARRAY.
*/
if (ELF_INITFINI && l->l_info[DT_INIT] != NULL)
DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr, argc, argv, env);
DL_CALL_DT_INIT(l, dl_rx_ptr (l, l->l_info[DT_INIT]->d_un.d_ptr),
argc, argv, env);
/* Next see whether there is an array with initialization functions. */
ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
@@ -61,11 +62,11 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
{
unsigned int j;
unsigned int jm;
ElfW(Addr) *addrs;
elfptr_t *addrs;
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (elfptr_t);
addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
addrs = (elfptr_t *) dl_rx_ptr (l, init_array->d_un.d_ptr);
for (j = 0; j < jm; ++j)
((dl_init_t) addrs[j]) (argc, argv, env);
}
@@ -88,16 +89,16 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
/* Don't do anything if there is no preinit array. */
if (__builtin_expect (preinit_array != NULL, 0)
&& preinit_array_size != NULL
&& (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
&& (i = preinit_array_size->d_un.d_val / sizeof (elfptr_t)) > 0)
{
ElfW(Addr) *addrs;
elfptr_t *addrs;
unsigned int cnt;
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
_dl_debug_printf ("\ncalling preinit: %s\n\n",
DSO_FILENAME (main_map->l_name));
addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
addrs = (elfptr_t *) dl_rx_ptr (main_map, preinit_array->d_un.d_ptr);
for (cnt = 0; cnt < i; ++cnt)
((dl_init_t) addrs[cnt]) (argc, argv, env);
}
+11
View File
@@ -61,9 +61,20 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
{
#ifdef __CHERI_PURE_CAPABILITY__
info.dlpi_addr = l->l_real->l_addr == l->l_real->l_map_start
? l->l_real->l_map_start
: l->l_real->l_addr;
#else
info.dlpi_addr = l->l_real->l_addr;
#endif
info.dlpi_name = l->l_real->l_name;
#ifdef __CHERI_PURE_CAPABILITY__
ElfW(Addr) phdr = (ElfW(Addr)) l->l_real->l_phdr - l->l_real->l_addr;
info.dlpi_phdr = (const void *) dl_rx_ptr (l->l_real, phdr);
#else
info.dlpi_phdr = l->l_real->l_phdr;
#endif
info.dlpi_phnum = l->l_real->l_phnum;
info.dlpi_adds = GL(dl_load_adds);
info.dlpi_subs = GL(dl_load_adds) - nloaded;
+8 -5
View File
@@ -866,7 +866,7 @@ _dl_init_paths (const char *llp, const char *source,
void
_dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph)
{
const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
const ElfW(Nhdr) *note = (const void *) dl_rx_ptr (l, ph->p_vaddr);
const ElfW(Addr) size = ph->p_memsz;
const ElfW(Addr) align = ph->p_align;
@@ -1276,7 +1276,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
}
if (l->l_ld != 0)
l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
l->l_ld = (ElfW(Dyn) *) (l->l_ld_readonly
? dl_rx_ptr (l, (elfptr_t) l->l_ld)
: dl_rw_ptr (l, (elfptr_t) l->l_ld));
elf_get_dynamic_info (l, false, false);
@@ -1314,7 +1316,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
}
else
/* Adjust the PT_PHDR value by the runtime load address. */
l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
l->l_phdr = (ElfW(Phdr) *) dl_rx_ptr (l, (ElfW(Addr)) l->l_phdr);
if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X))
{
@@ -1369,7 +1371,8 @@ cannot enable executable stack as shared object requires");
/* Adjust the address of the TLS initialization image. */
if (l->l_tls_initimage != NULL)
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
l->l_tls_initimage
= (void *) dl_rw_ptr (l, (ElfW(Addr)) l->l_tls_initimage);
/* Process program headers again after load segments are mapped in
case processing requires accessing those segments. Scan program
@@ -1402,7 +1405,7 @@ cannot enable executable stack as shared object requires");
/* If this is ET_EXEC, we should have loaded it as lt_executable. */
assert (type != ET_EXEC || l->l_type == lt_executable);
l->l_entry += l->l_addr;
l->l_entry = dl_rx_ptr (l, l->l_entry);
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\
+71 -14
View File
@@ -18,15 +18,26 @@
<https://www.gnu.org/licenses/>. */
#include <dl-load.h>
#ifdef __CHERI_PURE_CAPABILITY__
# include <cheri_perms.h>
#endif
/* Allow RWX mprotect later, on CHERI this means RWX capability permission. */
#ifdef PROT_MAX
# define PROT_MAX_RWX PROT_MAX (PROT_READ | PROT_WRITE | PROT_EXEC)
#else
# define PROT_MAX_RWX 0
#endif
/* Map a segment and align it properly. */
static __always_inline ElfW(Addr)
static __always_inline elfptr_t
_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
const size_t maplength, int fd)
{
if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize)))
return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot,
return (elfptr_t) __mmap ((void *) mappref, maplength,
c->prot|PROT_MAX_RWX,
MAP_COPY|MAP_FILE, fd, c->mapoff);
/* If the segment alignment > the page size, allocate enough space to
@@ -34,16 +45,16 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
ElfW(Addr) maplen = (maplength >= c->mapalign
? (maplength + c->mapalign)
: (2 * c->mapalign));
ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen,
PROT_NONE,
elfptr_t map_start = (elfptr_t) __mmap ((void *) mappref, maplen,
PROT_NONE|PROT_MAX_RWX,
MAP_ANONYMOUS|MAP_PRIVATE,
-1, 0);
if (__glibc_unlikely ((void *) map_start == MAP_FAILED))
return map_start;
ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign);
map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned,
maplength, c->prot,
elfptr_t map_start_aligned = ALIGN_UP (map_start, c->mapalign);
map_start_aligned = (elfptr_t) __mmap ((void *) map_start_aligned,
maplength, c->prot|PROT_MAX_RWX,
MAP_COPY|MAP_FILE|MAP_FIXED,
fd, c->mapoff);
if (__glibc_unlikely ((void *) map_start_aligned == MAP_FAILED))
@@ -54,7 +65,7 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
ElfW(Addr) delta = map_start_aligned - map_start;
if (delta)
__munmap ((void *) map_start, delta);
ElfW(Addr) map_end = map_start_aligned + maplength;
elfptr_t map_end = map_start + (map_start_aligned - map_start) + maplength;
map_end = ALIGN_UP (map_end, GLRO(dl_pagesize));
delta = map_start + maplen - map_end;
if (delta)
@@ -79,6 +90,10 @@ _dl_map_segments (struct link_map *l, int fd,
struct link_map *loader)
{
const struct loadcmd *c = loadcmds;
#ifdef __CHERI_PURE_CAPABILITY__
ElfW(Addr) rw_start = -1;
ElfW(Addr) rw_end = 0;
#endif
if (__glibc_likely (type == ET_DYN))
{
@@ -116,7 +131,7 @@ _dl_map_segments (struct link_map *l, int fd,
c->mapend))
return N_("ELF load command address/offset not page-aligned");
if (__glibc_unlikely
(__mprotect ((caddr_t) (l->l_addr + c->mapend),
(__mprotect ((caddr_t) dl_rx_ptr (l, c->mapend),
loadcmds[nloadcmds - 1].mapstart - c->mapend,
PROT_NONE) < 0))
return DL_MAP_SEGMENTS_ERROR_MPROTECT;
@@ -126,6 +141,23 @@ _dl_map_segments (struct link_map *l, int fd,
goto postmap;
}
#ifdef __CHERI_PURE_CAPABILITY__
else
{
/* Need a single capability to cover all load segments. */
void *p = __mmap ((void *) c->mapstart, maplength,
c->prot|PROT_MAX_RWX,
MAP_FIXED|MAP_COPY|MAP_FILE,
fd, c->mapoff);
if (p == MAP_FAILED)
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
l->l_map_start = (elfptr_t) p;
l->l_map_end = l->l_map_start + maplength;
l->l_contiguous = !has_holes;
goto postmap;
}
#endif
/* Remember which part of the address space this object uses. */
l->l_map_start = c->mapstart + l->l_addr;
@@ -134,10 +166,10 @@ _dl_map_segments (struct link_map *l, int fd,
while (c < &loadcmds[nloadcmds])
{
if (c->mapend > c->mapstart
if (c->dataend > c->mapstart
/* Map the segment contents from the file. */
&& (__mmap ((void *) (l->l_addr + c->mapstart),
c->mapend - c->mapstart, c->prot,
&& (__mmap ((void *) dl_rx_ptr (l, c->mapstart),
c->dataend - c->mapstart, c->prot,
MAP_FIXED|MAP_COPY|MAP_FILE,
fd, c->mapoff)
== MAP_FAILED))
@@ -146,13 +178,28 @@ _dl_map_segments (struct link_map *l, int fd,
postmap:
_dl_postprocess_loadcmd (l, header, c);
#ifdef __CHERI_PURE_CAPABILITY__
if (c->prot & PROT_WRITE)
{
if (l->l_rw_count >= DL_MAX_RW_COUNT)
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; // TODO: right error code
if (c->mapstart < rw_start)
rw_start = c->mapstart;
if (c->allocend > rw_end)
rw_end = c->allocend;
l->l_rw_range[l->l_rw_count].start = l->l_addr + c->mapstart;
l->l_rw_range[l->l_rw_count].end = l->l_addr + c->allocend;
l->l_rw_count++;
}
#endif
if (c->allocend > c->dataend)
{
/* Extra zero pages should appear at the end of this segment,
after the data mapped from the file. */
ElfW(Addr) zero, zeroend, zeropage;
elfptr_t zero, zeroend, zeropage;
zero = l->l_addr + c->dataend;
zero = dl_rx_ptr (l, c->dataend);
zeroend = l->l_addr + c->allocend;
zeropage = ((zero + GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
@@ -194,6 +241,16 @@ _dl_map_segments (struct link_map *l, int fd,
++c;
}
#ifdef __CHERI_PURE_CAPABILITY__
if (l->l_rw_count > 0)
{
l->l_rw_start = __builtin_cheri_address_set (l->l_map_start, l->l_addr + rw_start);
l->l_rw_start = __builtin_cheri_bounds_set (l->l_rw_start, rw_end - rw_start);
l->l_rw_start = __builtin_cheri_perms_and (l->l_rw_start, CAP_PERM_MASK_RW);
}
l->l_map_start = __builtin_cheri_perms_and (l->l_map_start, CAP_PERM_MASK_RX);
#endif
/* Notify ELF_PREFERRED_ADDRESS that we have to load this one
fixed. */
ELF_FIXED_ADDRESS (loader, c->mapstart);
+4 -1
View File
@@ -23,6 +23,7 @@
# pragma GCC visibility push(hidden)
#endif
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <ldsodefs.h>
#include <malloc/malloc-internal.h>
@@ -33,6 +34,7 @@ static void *alloc_ptr, *alloc_end, *alloc_last_block;
void *
__minimal_malloc (size_t n)
{
#ifndef __CHERI_PURE_CAPABILITY__
if (alloc_end == 0)
{
/* Consume any unused space in the last page of our data segment. */
@@ -42,9 +44,10 @@ __minimal_malloc (size_t n)
+ GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
}
#endif
/* Make sure the allocation pointer is ideally aligned. */
alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + MALLOC_ALIGNMENT - 1)
alloc_ptr = (void *)(((uintptr_t)alloc_ptr + (MALLOC_ALIGNMENT - 1))
& ~(MALLOC_ALIGNMENT - 1));
if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr)
+5 -2
View File
@@ -163,8 +163,11 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
/* We use alloca() to allocate the buffer with the most
pessimistic guess for the size. Using alloca() allows
having more than one integer formatting in a call. */
char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
int size = 1 + 3 * sizeof (unsigned long int);
if (width + 1 > size)
size = width + 1;
char *buf = (char *) alloca (size);
char *endp = &buf[size];
char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
/* Pad to the width the user specified. */
+4
View File
@@ -182,6 +182,9 @@ static unsigned int log_hashfraction;
void
_dl_start_profile (void)
{
#ifdef __CHERI_PURE_CAPABILITY__
__libc_fatal ("Profiling is not supported on capability architectures.");
#else
char *filename;
int fd;
struct __stat64_t64 st;
@@ -482,6 +485,7 @@ _dl_start_profile (void)
/* Turn on profiling. */
running = 1;
#endif
}
+1 -2
View File
@@ -353,8 +353,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
void
_dl_protect_relro (struct link_map *l)
{
ElfW(Addr) start = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr),
elfptr_t start = ALIGN_DOWN(dl_rx_ptr (l, l->l_relro_addr),
GLRO(dl_pagesize));
ElfW(Addr) end = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr
+1 -1
View File
@@ -55,7 +55,7 @@ _dl_fixup (
+ reloc_offset (pltgot, reloc_arg));
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
const ElfW(Sym) *refsym = sym;
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
void *const rel_addr = (void *) dl_rw_ptr (l, reloc->r_offset);
lookup_t result;
DL_FIXUP_VALUE_TYPE value;
+7
View File
@@ -255,6 +255,13 @@ _dl_aux_init (ElfW(auxv_t) *av)
for (int i = 0; i < array_length (auxv_values); ++i)
auxv_values[i] = 0;
_dl_parse_auxv (av, auxv_values);
# ifdef __CHERI_PURE_CAPABILITY__
_dl_main_map.l_map_start = auxv_values[AT_CHERI_EXEC_RX_CAP];
_dl_main_map.l_map_start = __builtin_cheri_perms_and (_dl_main_map.l_map_start, CAP_PERM_MASK_RX);
_dl_main_map.l_rw_start = auxv_values[AT_CHERI_EXEC_RW_CAP];
_dl_main_map.l_rw_start = __builtin_cheri_perms_and (_dl_main_map.l_rw_start, CAP_PERM_MASK_RW);
# endif
}
#endif
+1 -1
View File
@@ -41,7 +41,7 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
{
DL_FIXUP_VALUE_TYPE fixup
= DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
= DL_FIXUP_MAKE_VALUE (result, (elfptr_t) value);
fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
}
+4
View File
@@ -49,6 +49,10 @@ _dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref)
{
.ti_module = map->l_tls_modid,
.ti_offset = ref->st_value
# ifdef __CHERI_PURE_CAPABILITY__
,
.ti_size = ref->st_size
# endif
};
return __TLS_GET_ADDR (&tmp);
+8
View File
@@ -62,7 +62,11 @@
observed PT_GNU_TLS sizes across all architectures. Some
architectures have lower values due to differences in type sizes
and link editor capabilities. */
#ifdef __CHERI_PURE_CAPABILITY__
#define LIBC_IE_TLS 256
#else
#define LIBC_IE_TLS 144
#endif
/* Size of initial-exec TLS in libraries other than libc.so.
This should be large enough to cover runtime libraries of the
@@ -87,7 +91,11 @@ tls_static_surplus (int nns, int opt_tls)
the computation of dl_tls_static_surplus in
_dl_tls_static_surplus_init yields the historic value 1664, for
backwards compatibility. */
#ifdef __CHERI_PURE_CAPABILITY__
#define LEGACY_TLS 0
#else
#define LEGACY_TLS (1664 - tls_static_surplus (DEFAULT_NNS, OPTIONAL_TLS))
#endif
/* Calculate the size of the static TLS surplus, when the given
number of audit modules are loaded. Must be called after the
+7
View File
@@ -159,6 +159,13 @@ glibc {
maxval: 255
security_level: SXID_IGNORE
}
cap_narrowing {
type: INT_32
minval: 0
maxval: 1
default: 1
security_level: SXID_IGNORE
}
}
rtld {
+5 -5
View File
@@ -86,7 +86,7 @@ checking for version `%s' in file %s [%lu] required by file %s [%lu]\n",
def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
assert (def_offset != 0);
def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
def = (ElfW(Verdef) *) dl_rx_ptr (map, def_offset);
while (1)
{
/* Currently the version number of the definition entry is 1.
@@ -177,7 +177,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
if (dyn != NULL)
{
/* This file requires special versions from its dependencies. */
ElfW(Verneed) *ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
ElfW(Verneed) *ent = (ElfW(Verneed) *) dl_rx_ptr (map, dyn->d_un.d_ptr);
/* Currently the version number of the needed entry is 1.
Make sure all we see is this version. */
@@ -257,7 +257,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
if (def != NULL)
{
ElfW(Verdef) *ent;
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
ent = (ElfW(Verdef) *) dl_rx_ptr (map, def->d_un.d_ptr);
while (1)
{
if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high)
@@ -296,7 +296,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
if (dyn != NULL)
{
ElfW(Verneed) *ent;
ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
ent = (ElfW(Verneed) *) dl_rx_ptr (map, dyn->d_un.d_ptr);
while (1)
{
ElfW(Vernaux) *aux;
@@ -334,7 +334,7 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
if (def != NULL)
{
ElfW(Verdef) *ent;
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
ent = (ElfW(Verdef) *) dl_rx_ptr (map, def->d_un.d_ptr);
while (1)
{
ElfW(Verdaux) *aux;
+6 -6
View File
@@ -41,7 +41,7 @@
static inline void __attribute__ ((always_inline))
elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) reladdr, ElfW(Addr) relsize,
elfptr_t reladdr, ElfW(Addr) relsize,
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
int lazy, int skip_ifunc)
{
@@ -62,7 +62,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
{
ElfW (Half) ndx = version[ELFW (R_SYM) (r->r_info)] & 0x7fff;
const ElfW (Sym) *sym = &symtab[ELFW (R_SYM) (r->r_info)];
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
void *const r_addr_arg = (void *) dl_rw_ptr (map, r->r_offset);
const struct r_found_version *rversion = &map->l_versions[ndx];
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, skip_ifunc);
@@ -132,7 +132,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
{
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
void *const r_addr_arg = (void *) dl_rw_ptr (map, r->r_offset);
const struct r_found_version *rversion = &map->l_versions[ndx];
#if defined ELF_MACHINE_IRELATIVE
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
@@ -169,7 +169,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
elf_machine_rel (map, scope, r2,
&symtab[ELFW(R_SYM) (r2->r_info)],
&map->l_versions[ndx],
(void *) (l_addr + r2->r_offset),
(void *) dl_rw_ptr (map, r2->r_offset),
skip_ifunc);
}
#endif
@@ -179,7 +179,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
for (; r < end; ++r)
{
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
void *const r_addr_arg = (void *) dl_rw_ptr (map, r->r_offset);
# ifdef ELF_MACHINE_IRELATIVE
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
{
@@ -210,7 +210,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
for (; r2 <= end2; ++r2)
if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
NULL, (void *) (l_addr + r2->r_offset),
NULL, (void *) dl_rw_ptr (map, r2->r_offset),
skip_ifunc);
# endif
}
+7 -2
View File
@@ -46,9 +46,14 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
const struct r_found_version *version, void *const reloc_addr,
int skip_ifunc);
# ifdef __CHERI_PURE_CAPABILITY__
static inline void __attribute__((always_inline))
elf_machine_rela_relative (struct link_map *map, const ElfW(Rela) *reloc);
# else
static inline void __attribute__((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr);
# endif
# endif
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
static inline void __attribute__((always_inline))
@@ -80,7 +85,7 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
do { \
struct { ElfW(Addr) start, size; \
struct { elfptr_t start; ElfW(Addr) size; \
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \
\
@@ -97,7 +102,7 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
if ((map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
{ \
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
elfptr_t start = D_PTR ((map), l_info[DT_JMPREL]); \
ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
\
if (ranges[0].start == 0) \
+45
View File
@@ -1159,6 +1159,14 @@ typedef struct
typedef struct
{
#if defined __CHERI_PURE_CAPABILITY__
uint64_t a_type;
uint64_t __pad;
union
{
__uintcap_t a_val;
} a_un;
#else
uint64_t a_type; /* Entry type */
union
{
@@ -1167,6 +1175,7 @@ typedef struct
though, since it does not work when using 32-bit definitions
on 64-bit platforms and vice versa. */
} a_un;
#endif
} Elf64_auxv_t;
/* Legal values for a_type (entry type). */
@@ -1243,6 +1252,18 @@ typedef struct
#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery */
#define AT_CHERI_EXEC_RW_CAP 60
#define AT_CHERI_EXEC_RX_CAP 61
#define AT_CHERI_INTERP_RW_CAP 62
#define AT_CHERI_INTERP_RX_CAP 63
#define AT_CHERI_STACK_CAP 64
#define AT_CHERI_SEAL_CAP 65
#define AT_CHERI_CID_CAP 66
#define AT_ARGC 80
#define AT_ARGV 81
#define AT_ENVC 82
#define AT_ENVP 83
/* Note section contents. Each entry in the note section begins with
a header of a fixed form. */
@@ -2906,6 +2927,9 @@ enum
/* MTE memory tag segment type. */
#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 2)
/* Processor specific flags for the ELF header e_flags field. */
#define EF_AARCH64_CHERI_PURECAP 0x00010000
/* AArch64 specific values for the Dyn d_tag field. */
#define DT_AARCH64_BTI_PLT (DT_LOPROC + 1)
#define DT_AARCH64_PAC_PLT (DT_LOPROC + 3)
@@ -2915,6 +2939,27 @@ enum
/* AArch64 specific values for the st_other field. */
#define STO_AARCH64_VARIANT_PCS 0x80
/* Morello relocs. */
#define R_MORELLO_TSTBR14 57344
#define R_MORELLO_CONDBR19 57345
#define R_MORELLO_JUMP26 57346
#define R_MORELLO_CALL26 57347
#define R_MORELLO_LD_PREL_LO17 57348
#define R_MORELLO_ADR_PREL_PG_HI20 57349
#define R_MORELLO_ADR_PREL_PG_HI20_NC 57350
#define R_MORELLO_ADR_GOT_PAGE 57351
#define R_MORELLO_LD128_GOT_LO12_NC 57352
#define R_MORELLO_TLSDESC_ADR_PAGE20 57600
#define R_MORELLO_TLSDESC_LD128_LO12 57601
#define R_MORELLO_TLSDESC_CALL 57602
#define R_MORELLO_CAPINIT 59392
#define R_MORELLO_GLOB_DAT 59393
#define R_MORELLO_JUMP_SLOT 59394
#define R_MORELLO_RELATIVE 59395
#define R_MORELLO_IRELATIVE 59396
#define R_MORELLO_TLSDESC 59397
#define R_MORELLO_TPREL128 59398
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
+7 -1
View File
@@ -34,6 +34,12 @@
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h>
#ifdef __CHERI_PURE_CAPABILITY__
typedef uintptr_t elfptr_t;
#else
typedef ElfW(Addr) elfptr_t;
#endif
/* The legacy rendezvous structure used by the run-time dynamic linker to
communicate details of shared object loading to the debugger. */
@@ -154,7 +160,7 @@ enum
struct dl_phdr_info
{
ElfW(Addr) dlpi_addr;
elfptr_t dlpi_addr;
const char *dlpi_name;
const ElfW(Phdr) *dlpi_phdr;
ElfW(Half) dlpi_phnum;
+43 -15
View File
@@ -24,6 +24,7 @@
#include <dl-r_debug.h>
#ifndef __CHERI_PURE_CAPABILITY__
struct E(link_map)
{
EW(Addr) l_addr;
@@ -35,6 +36,48 @@ struct E(link_map)
Lmid_t l_ns;
EW(Addr) l_libname;
};
struct E(libname_list)
{
EW(Addr) name;
EW(Addr) next;
};
struct E(r_debug)
{
int r_version;
# if CLASS == 64
int pad;
# endif
EW(Addr) r_map;
};
#else
struct E(link_map)
{
uintptr_t l_addr;
uintptr_t l_name;
uintptr_t l_ld;
uintptr_t l_next;
uintptr_t l_prev;
uintptr_t l_real;
Lmid_t l_ns;
uintptr_t l_libname;
};
struct E(libname_list)
{
uintptr_t name;
uintptr_t next;
};
struct E(r_debug)
{
int r_version;
int pad;
uintptr_t r_map;
};
#endif
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr), "l_addr");
@@ -44,27 +87,12 @@ _Static_assert (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next), "l_next");
#endif
struct E(libname_list)
{
EW(Addr) name;
EW(Addr) next;
};
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name), "name");
_Static_assert (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next), "next");
#endif
struct E(r_debug)
{
int r_version;
#if CLASS == 64
int pad;
#endif
EW(Addr) r_map;
};
#if CLASS == __ELF_NATIVE_CLASS
_Static_assert (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version), "r_version");
+70 -16
View File
@@ -384,7 +384,7 @@ extern struct rtld_global_ro _rtld_local_ro
static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv);
elfptr_t *user_entry, ElfW(auxv_t) *auxv);
/* These two variables cannot be moved into .data.rel.ro. */
static struct libname_list _dl_rtld_libname;
@@ -416,15 +416,15 @@ DL_SYSINFO_IMPLEMENTATION
#endif
#ifdef DONT_USE_BOOTSTRAP_MAP
static ElfW(Addr) _dl_start_final (void *arg);
static elfptr_t _dl_start_final (void *arg);
#else
struct dl_start_final_info
{
struct link_map l;
RTLD_TIMING_VAR (start_time);
};
static ElfW(Addr) _dl_start_final (void *arg,
struct dl_start_final_info *info);
static elfptr_t _dl_start_final (void *arg,
struct dl_start_final_info *info);
#endif
/* These are defined magically by the linker. */
@@ -446,14 +446,14 @@ RTLD_START
this function is not inlined (see below). */
#ifdef DONT_USE_BOOTSTRAP_MAP
static inline ElfW(Addr) __attribute__ ((always_inline))
static inline elfptr_t __attribute__ ((always_inline))
_dl_start_final (void *arg)
#else
static ElfW(Addr) __attribute__ ((noinline))
static elfptr_t __attribute__ ((noinline))
_dl_start_final (void *arg, struct dl_start_final_info *info)
#endif
{
ElfW(Addr) start_addr;
elfptr_t start_addr;
/* Do not use an initializer for these members because it would
intefere with __rtld_static_init. */
@@ -474,10 +474,19 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
sizeof GL(dl_rtld_map).l_info);
GL(dl_rtld_map).l_mach = info->l.l_mach;
GL(dl_rtld_map).l_relocated = 1;
# ifdef __CHERI_PURE_CAPABILITY__
GL(dl_rtld_map).l_map_start = info->l.l_map_start;
GL(dl_rtld_map).l_rw_start = info->l.l_rw_start;
GL(dl_rtld_map).l_rw_count = info->l.l_rw_count;
for (int i = 0; i < info->l.l_rw_count; i++)
GL(dl_rtld_map).l_rw_range[i] = info->l.l_rw_range[i];
# endif
#endif
_dl_setup_hash (&GL(dl_rtld_map));
GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
#ifndef __CHERI_PURE_CAPABILITY__
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) &__ehdr_start;
#endif
GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
/* Copy the TLS related data if necessary. */
@@ -515,7 +524,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
# define bootstrap_map info.l
#endif
static ElfW(Addr) __attribute_used__
static elfptr_t __attribute_used__
_dl_start (void *arg)
{
#ifdef DONT_USE_BOOTSTRAP_MAP
@@ -542,11 +551,16 @@ _dl_start (void *arg)
# endif
#endif
#ifdef __CHERI_PURE_CAPABILITY__
elf_machine_rtld_base_setup (&bootstrap_map, arg);
bootstrap_map.l_ld = elf_machine_runtime_dynamic ();
#else
/* Figure out the run-time load address of the dynamic linker itself. */
bootstrap_map.l_addr = elf_machine_load_address ();
/* Read our own dynamic section and fill in the info array. */
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
#endif
bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION;
elf_get_dynamic_info (&bootstrap_map, true, false);
@@ -708,8 +722,7 @@ match_version (const char *string, struct link_map *map)
/* The file has no symbol versioning. */
return 0;
def = (ElfW(Verdef) *) ((char *) map->l_addr
+ map->l_info[VERDEFTAG]->d_un.d_ptr);
def = (ElfW(Verdef) *) dl_rx_ptr (map, map->l_info[VERDEFTAG]->d_un.d_ptr);
while (1)
{
ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);
@@ -1125,8 +1138,13 @@ rtld_setup_main_map (struct link_map *main_map)
main_map->l_map_end = 0;
main_map->l_text_end = 0;
#ifndef __CHERI_PURE_CAPABILITY__
/* Perhaps the executable has no PT_LOAD header entries at all. */
main_map->l_map_start = ~0;
#else
/* May be computed already when exe is loaded by ld.so. */
main_map->l_rw_count = 0;
#endif
/* And it was opened directly. */
++main_map->l_direct_opencount;
main_map->l_contiguous = 1;
@@ -1157,8 +1175,10 @@ rtld_setup_main_map (struct link_map *main_map)
case PT_DYNAMIC:
/* This tells us where to find the dynamic section,
which tells us everything we need to do. */
main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr;
main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
main_map->l_ld = (void *) (main_map->l_ld_readonly
? dl_rx_ptr (main_map, ph->p_vaddr)
: dl_rw_ptr (main_map, ph->p_vaddr));
break;
case PT_INTERP:
/* This "interpreter segment" was used by the program loader to
@@ -1167,8 +1187,8 @@ rtld_setup_main_map (struct link_map *main_map)
dlopen call or DT_NEEDED entry, for something that wants to link
against the dynamic linker as a shared library, will know that
the shared object is already loaded. */
_dl_rtld_libname.name = ((const char *) main_map->l_addr
+ ph->p_vaddr);
_dl_rtld_libname.name = (const char *) dl_rx_ptr (main_map,
ph->p_vaddr);
/* _dl_rtld_libname.next = NULL; Already zero. */
GL(dl_rtld_map).l_libname = &_dl_rtld_libname;
@@ -1205,8 +1225,10 @@ rtld_setup_main_map (struct link_map *main_map)
/* Remember where the main program starts in memory. */
mapstart = (main_map->l_addr
+ (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
#ifndef __CHERI_PURE_CAPABILITY__
if (main_map->l_map_start > mapstart)
main_map->l_map_start = mapstart;
#endif
if (main_map->l_contiguous && expected_load_address != 0
&& expected_load_address != mapstart)
@@ -1223,6 +1245,15 @@ rtld_setup_main_map (struct link_map *main_map)
segment. */
expected_load_address = ((allocend + GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
#ifdef __CHERI_PURE_CAPABILITY__
if (ph->p_flags & PF_W)
{
assert (main_map->l_rw_count < DL_MAX_RW_COUNT);
main_map->l_rw_range[main_map->l_rw_count].start = mapstart;
main_map->l_rw_range[main_map->l_rw_count].end = allocend;
main_map->l_rw_count++;
}
#endif
}
break;
@@ -1274,7 +1305,7 @@ rtld_setup_main_map (struct link_map *main_map)
the executable is actually an ET_DYN object. */
if (main_map->l_tls_initimage != NULL)
main_map->l_tls_initimage
= (char *) main_map->l_tls_initimage + main_map->l_addr;
= (void *) dl_rx_ptr (main_map, (ElfW(Addr)) main_map->l_tls_initimage);
if (! main_map->l_map_end)
main_map->l_map_end = ~0;
if (! main_map->l_text_end)
@@ -1352,7 +1383,7 @@ _dl_start_args_adjust (int skip_args)
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
ElfW(Addr) *user_entry,
elfptr_t *user_entry,
ElfW(auxv_t) *auxv)
{
struct link_map *main_map;
@@ -1635,6 +1666,14 @@ dl_main (const ElfW(Phdr) *phdr,
case AT_EXECFN:
av->a_un.a_val = (uintptr_t) _dl_argv[0];
break;
# ifdef __CHERI_PURE_CAPABILITY__
case AT_CHERI_EXEC_RX_CAP:
av->a_un.a_val = main_map->l_map_start;
break;
case AT_CHERI_EXEC_RW_CAP:
av->a_un.a_val = main_map->l_rw_start;
break;
# endif
}
#endif
@@ -1678,6 +1717,21 @@ dl_main (const ElfW(Phdr) *phdr,
/* We delay initializing the path structure until we got the dynamic
information for the program. */
#ifdef __CHERI_PURE_CAPABILITY__
for (ElfW(auxv_t) *av = auxv; av->a_type != AT_NULL; av++)
switch (av->a_type)
{
case AT_CHERI_EXEC_RX_CAP:
main_map->l_map_start = av->a_un.a_val;
main_map->l_map_start = __builtin_cheri_perms_and (main_map->l_map_start, CAP_PERM_MASK_RX);
break;
case AT_CHERI_EXEC_RW_CAP:
main_map->l_rw_start = av->a_un.a_val;
main_map->l_rw_start = __builtin_cheri_perms_and (main_map->l_rw_start, CAP_PERM_MASK_RW);
break;
}
#endif
}
bool has_interp = rtld_setup_main_map (main_map);
@@ -2194,7 +2248,7 @@ dl_main (const ElfW(Phdr) *phdr,
continue;
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
ent = (ElfW(Verneed) *) dl_rx_ptr (map, dyn->d_un.d_ptr);
if (first)
{
+8
View File
@@ -27,7 +27,11 @@ static int
do_test (int argc, char *argv[])
{
errno = 0;
#ifndef __CHERI_PURE_CAPABILITY__
const char *execfn = (const char *) getauxval (AT_NULL);
#else
const char *execfn = (const char *) getauxptr (AT_NULL);
#endif
if (errno != ENOENT)
{
@@ -43,7 +47,11 @@ do_test (int argc, char *argv[])
}
errno = 0;
#ifndef __CHERI_PURE_CAPABILITY__
execfn = (const char *) getauxval (AT_EXECFN);
#else
execfn = (const char *) getauxptr (AT_EXECFN);
#endif
if (execfn == NULL)
{
+1 -1
View File
@@ -30,7 +30,7 @@ static int
callback (struct dl_phdr_info *info, size_t size, void *ptr)
{
static int last_adds = 0, last_subs = 0;
intptr_t cmd = (intptr_t) ptr;
unsigned long cmd = (intptr_t) ptr;
printf (" size = %Zu\n", size);
if (size < (offsetof (struct dl_phdr_info, dlpi_subs)
+2 -2
View File
@@ -264,7 +264,7 @@ do_test_dependency (void)
xdlclose (moddep);
}
for (int n = 1; n <= nmods; n++)
for (int n = 1; n < nmods; n++)
if (mods[n] != 0)
unload_mod (n);
}
@@ -342,7 +342,7 @@ do_test_invalid_dependency (bool bind_now)
xdlclose (moddep);
}
for (int n = 1; n <= nmods; n++)
for (int n = 1; n < nmods; n++)
if (mods[n] != 0)
unload_mod (n);
}
+3 -3
View File
@@ -31,13 +31,13 @@
static void
activate_test_gconv_modules (void)
{
unsigned long ptr = getauxval (AT_EXECFN);
if (ptr == 0)
const char *ptr = getauxptr (AT_EXECFN);
if (ptr == NULL)
{
printf ("warning: AT_EXECFN not support, cannot run test\n");
exit (EXIT_UNSUPPORTED);
}
char *test_program_directory = dirname (xstrdup ((const char *) ptr));
char *test_program_directory = dirname (xstrdup (ptr));
TEST_VERIFY (setenv ("GCONV_PATH", test_program_directory, 1) == 0);
free (test_program_directory);
}
+2 -2
View File
@@ -58,11 +58,11 @@ worker (void * arg)
char ascii[] = CONV_INPUT;
char *inbufpos = ascii;
size_t inbytesleft = sizeof (CONV_INPUT);
size_t inbytesleft = sizeof (CONV_INPUT) - 1;
char *utf8 = xcalloc (sizeof (CONV_INPUT), 1);
char *outbufpos = utf8;
size_t outbytesleft = sizeof (CONV_INPUT);
size_t outbytesleft = sizeof (CONV_INPUT) - 1;
if (tidx < TCOUNT/2)
/* The first half of the worker thread pool synchronize together here,
+6 -5
View File
@@ -82,6 +82,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <sys/param.h>
#include <libc-pointer-arith.h>
/* struct alloc_buffer objects refer to a region of bytes in memory of a
fixed size. The functions below can be used to allocate single
@@ -248,9 +249,9 @@ __alloc_buffer_alloc (struct alloc_buffer *buf, size_t size, size_t align)
if (size == 1 && align == 1)
return alloc_buffer_alloc_bytes (buf, size);
size_t current = buf->__alloc_buffer_current;
size_t aligned = roundup (current, align);
size_t new_current = aligned + size;
uintptr_t current = buf->__alloc_buffer_current;
uintptr_t aligned = roundup (current, align);
uintptr_t new_current = aligned + size;
if (aligned >= current /* No overflow in align step. */
&& new_current >= size /* No overflow in size computation. */
&& new_current <= buf->__alloc_buffer_end) /* Room in buffer. */
@@ -282,8 +283,8 @@ __alloc_buffer_next (struct alloc_buffer *buf, size_t align)
if (align == 1)
return (const void *) buf->__alloc_buffer_current;
size_t current = buf->__alloc_buffer_current;
size_t aligned = roundup (current, align);
uintptr_t current = buf->__alloc_buffer_current;
uintptr_t aligned = roundup (current, align);
if (aligned >= current /* No overflow in align step. */
&& aligned <= buf->__alloc_buffer_end) /* Room in buffer. */
{
+15 -2
View File
@@ -62,6 +62,8 @@
__atg1_result = pre##_32_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 8) \
__atg1_result = pre##_64_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 16) \
__atg1_result = pre##_128_##post (mem, __VA_ARGS__); \
else \
abort (); \
__atg1_result; \
@@ -77,6 +79,8 @@
__atg2_result = pre##_32_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 8) \
__atg2_result = pre##_64_##post (mem, __VA_ARGS__); \
else if (sizeof (*mem) == 16) \
__atg2_result = pre##_128_##post (mem, __VA_ARGS__); \
else \
abort (); \
__atg2_result; \
@@ -540,7 +544,11 @@
/* We require 32b atomic operations; some archs also support 64b atomic
operations. */
void __atomic_link_error (void);
# if __HAVE_64B_ATOMICS == 1
# if defined __CHERI_PURE_CAPABILITY__
# define __atomic_check_size(mem) \
if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8) && (sizeof (*mem) != 16)) \
__atomic_link_error ();
# elif __HAVE_64B_ATOMICS == 1
# define __atomic_check_size(mem) \
if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8)) \
__atomic_link_error ();
@@ -553,7 +561,12 @@ void __atomic_link_error (void);
need other atomic operations of such sizes, and restricting the support to
loads and stores makes this easier for archs that do not have native
support for atomic operations to less-than-word-sized data. */
# if __HAVE_64B_ATOMICS == 1
# if defined __CHERI_PURE_CAPABILITY__
# define __atomic_check_size_ls(mem) \
if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4) \
&& (sizeof (*mem) != 8) && (sizeof (*mem) != 16)) \
__atomic_link_error ();
# elif __HAVE_64B_ATOMICS == 1
# define __atomic_check_size_ls(mem) \
if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4) \
&& (sizeof (*mem) != 8)) \
+17 -3
View File
@@ -83,6 +83,7 @@ struct r_search_path_struct
extern struct r_search_path_struct __rtld_search_dirs attribute_hidden;
extern struct r_search_path_struct __rtld_env_path_list attribute_hidden;
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup.
@@ -96,9 +97,9 @@ struct link_map
{
/* These first few members are part of the protocol with the debugger.
This is the same format used in SVR4. */
ElfW(Addr) l_addr; /* Difference between the address in the ELF
file and the addresses in memory. */
char *l_name; /* Absolute file name object was found in. */
ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
@@ -133,7 +134,7 @@ struct link_map
ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
ElfW(Addr) l_entry; /* Entry point location. */
elfptr_t l_entry; /* Entry point location. */
ElfW(Half) l_phnum; /* Number of program header entries. */
ElfW(Half) l_ldnum; /* Number of dynamic segment entries. */
@@ -252,9 +253,22 @@ struct link_map
/* Start and finish of memory map for this object. l_map_start
need not be the same as l_addr. */
ElfW(Addr) l_map_start, l_map_end;
elfptr_t l_map_start;
ElfW(Addr) l_map_end;
/* End of the executable part of the mapping. */
ElfW(Addr) l_text_end;
#ifdef __CHERI_PURE_CAPABILITY__
/* Writable part of the mapping (may have non-writable holes). */
elfptr_t l_rw_start;
# define DL_MAX_RW_COUNT 4
/* Writable ranges: objects are writable in these ranges. */
int l_rw_count;
struct rw_range
{
ElfW(Addr) start;
ElfW(Addr) end;
} l_rw_range[DL_MAX_RW_COUNT];
#endif
/* Default array for 'l_scope'. */
struct r_scope_elem *l_scope_mem[4];
+4
View File
@@ -10,4 +10,8 @@ libc_hidden_proto (__getauxval)
_Bool __getauxval2 (unsigned long int type, unsigned long int *result);
libc_hidden_proto (__getauxval2)
/* Like getauxval, but for Arm Morello capabilities. */
extern __typeof (getauxptr) __getauxptr;
libc_hidden_proto (__getauxptr)
#endif /* !_ISOMAC */
+4 -2
View File
@@ -340,8 +340,10 @@ read_alias_file (const char *fname, int fname_len)
for (i = 0; i < nmap; i++)
{
map[i].alias += new_pool - string_space;
map[i].value += new_pool - string_space;
map[i].alias = new_pool
+ (map[i].alias - string_space);
map[i].value = new_pool
+ (map[i].value - string_space);
}
}
+2 -1
View File
@@ -55,6 +55,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#include <dirent.h>
#include <errno.h>
#include <fts.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -67,7 +68,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#endif
/* Align P to that size. */
#ifndef ALIGN
#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
#define ALIGN(p) (((uintptr_t) (p) + ALIGNBYTES) & ~ALIGNBYTES)
#endif
+3 -1
View File
@@ -95,7 +95,9 @@ struct _IO_FILE_complete
size_t __pad5;
int _mode;
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
char _unused2[sizeof (void *) == 4 * sizeof (int)
? 9 * sizeof (int)
: 15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
/* These macros are used by bits/stdio.h and internal headers. */
+2 -2
View File
@@ -247,8 +247,8 @@ __libc_tsd_define (extern, locale_t, LOCALE)
But with thread-local locale settings, it becomes quite ungainly unless
we can use __thread variables. So only in that case do we attempt this. */
#ifndef SHARED
# include <tls.h>
# define NL_CURRENT_INDIRECT 1
//# include <tls.h>
//# define NL_CURRENT_INDIRECT 1
#endif
#ifdef NL_CURRENT_INDIRECT
+9 -1
View File
@@ -84,6 +84,13 @@ static const char *locnames[] =
/* Size of the reserved address space area. */
#define RESERVE_MMAP_SIZE 512 * 1024 * 1024
/* On CHERI targets ensure the mmap returned capability has RW permissions. */
#ifdef PROT_MAX
# define PROT_MAX_RW PROT_MAX (PROT_READ | PROT_WRITE)
#else
# define PROT_MAX_RW 0
#endif
/* To prepare for enlargements of the mmaped area reserve some address
space. On some machines, being a file mapping rather than an anonymous
mapping affects the address selection. So do this mapping from the
@@ -94,7 +101,8 @@ prepare_address_space (int fd, size_t total, size_t *reserved, int *xflags,
{
if (total < RESERVE_MMAP_SIZE)
{
void *p = mmap64 (NULL, RESERVE_MMAP_SIZE, PROT_NONE, MAP_SHARED, fd, 0);
void *p = mmap64 (NULL, RESERVE_MMAP_SIZE,
PROT_NONE | PROT_MAX_RW, MAP_SHARED, fd, 0);
if (p != MAP_FAILED)
{
void *aligned_p = PTR_ALIGN_UP (p, MAP_FIXED_ALIGNMENT);
+5
View File
@@ -88,6 +88,7 @@ tests-exclude-hugetlb1 = \
tst-interpose-thread \
tst-interpose-static-nothread \
tst-interpose-static-thread \
tst-malloc-backtrace \
tst-malloc-usable \
tst-malloc-usable-tunables \
tst-mallocstate
@@ -159,6 +160,8 @@ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
libc_malloc_debug-routines = malloc-debug $(sysdep_malloc_debug_routines)
libc_malloc_debug-inhibit-o = $(filter-out .os,$(object-suffixes))
tst-malloc-backtrace-ENV = GLIBC_TUNABLES=glibc.mem.cap_narrowing=0
$(objpfx)tst-malloc-backtrace: $(shared-thread-library)
$(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
$(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
@@ -331,12 +334,14 @@ $(objpfx)tst-interpose-static-thread: \
$(objpfx)tst-interpose-aux-thread.o $(static-thread-library)
tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \
GLIBC_TUNABLES=glibc.mem.cap_narrowing=0 \
LD_PRELOAD=$(objpfx)libc_malloc_debug.so
$(objpfx)tst-dynarray-mem.out: $(objpfx)tst-dynarray.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray.mtrace > $@; \
$(evaluate-test)
tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \
GLIBC_TUNABLES=glibc.mem.cap_narrowing=0 \
LD_PRELOAD=$(objpfx)libc_malloc_debug.so
$(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \
+3 -3
View File
@@ -23,12 +23,12 @@ void *
__libc_alloc_buffer_alloc_array (struct alloc_buffer *buf, size_t element_size,
size_t align, size_t count)
{
size_t current = buf->__alloc_buffer_current;
uintptr_t current = buf->__alloc_buffer_current;
/* The caller asserts that align is a power of two. */
size_t aligned = ALIGN_UP (current, align);
uintptr_t aligned = ALIGN_UP (current, align);
size_t size;
bool overflow = __builtin_mul_overflow (element_size, count, &size);
size_t new_current = aligned + size;
uintptr_t new_current = aligned + size;
if (!overflow /* Multiplication did not overflow. */
&& aligned >= current /* No overflow in align step. */
&& new_current >= size /* No overflow in size computation. */
+26 -3
View File
@@ -191,6 +191,7 @@ __malloc_fork_lock_parent (void)
if (ar_ptr == &main_arena)
break;
}
cap_fork_lock ();
}
void
@@ -199,6 +200,8 @@ __malloc_fork_unlock_parent (void)
if (!__malloc_initialized)
return;
cap_fork_unlock_parent ();
for (mstate ar_ptr = &main_arena;; )
{
__libc_lock_unlock (ar_ptr->mutex);
@@ -215,6 +218,8 @@ __malloc_fork_unlock_child (void)
if (!__malloc_initialized)
return;
cap_fork_unlock_child ();
/* Push all arenas to the free list, except thread_arena, which is
attached to the current thread. */
__libc_lock_init (free_list_lock);
@@ -321,6 +326,14 @@ ptmalloc_init (void)
tcache_key_initialize ();
#endif
#ifdef __CHERI_PURE_CAPABILITY__
if (TUNABLE_GET_FULL (glibc, mem, cap_narrowing, int32_t, NULL) == 0)
cap_narrowing_enabled = false;
else
cap_narrowing_enabled = true;
#endif
cap_init ();
#ifdef USE_MTAG
if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
{
@@ -444,7 +457,7 @@ dump_heap (heap_info *heap)
fprintf (stderr, "Heap %p, size %10lx:\n", heap, (long) heap->size);
ptr = (heap->ar_ptr != (mstate) (heap + 1)) ?
(char *) (heap + 1) : (char *) (heap + 1) + sizeof (struct malloc_state);
p = (mchunkptr) (((unsigned long) ptr + MALLOC_ALIGN_MASK) &
p = (mchunkptr) (((uintptr_t) ptr + MALLOC_ALIGN_MASK) &
~MALLOC_ALIGN_MASK);
for (;; )
{
@@ -518,7 +531,7 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
p1 = (char *) MMAP (0, max_size << 1, PROT_NONE, mmap_flags);
if (p1 != MAP_FAILED)
{
p2 = (char *) (((unsigned long) p1 + (max_size - 1))
p2 = (char *) (((uintptr_t) p1 + (max_size - 1))
& ~(max_size - 1));
ul = p2 - p1;
if (ul)
@@ -526,6 +539,9 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
else
aligned_heap_area = p2 + max_size;
__munmap (p2 + max_size, max_size - ul);
#ifdef __CHERI_PURE_CAPABILITY__
p2 = __builtin_cheri_bounds_set_exact (p2, max_size);
#endif
}
else
{
@@ -548,6 +564,12 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
return 0;
}
if (!cap_map_add (p2))
{
__munmap (p2, max_size);
return 0;
}
madvise_thp (p2, size);
h = (heap_info *) p2;
@@ -670,6 +692,7 @@ heap_trim (heap_info *heap, size_t pad)
LIBC_PROBE (memory_heap_free, 2, heap, heap->size);
if ((char *) heap + max_size == aligned_heap_area)
aligned_heap_area = NULL;
cap_map_del (heap);
__munmap (heap, max_size);
heap = prev_heap;
if (!prev_inuse (p)) /* consolidate backward */
@@ -760,7 +783,7 @@ _int_new_arena (size_t size)
/* Set up the top chunk, with proper alignment. */
ptr = (char *) (a + 1);
misalign = (unsigned long) chunk2mem (ptr) & MALLOC_ALIGN_MASK;
misalign = (uintptr_t) chunk2mem (ptr) & MALLOC_ALIGN_MASK;
if (misalign > 0)
ptr += MALLOC_ALIGNMENT - misalign;
top (a) = (mchunkptr) ptr;
+363 -22
View File
@@ -244,6 +244,9 @@
/* For memory tagging. */
#include <libc-mtag.h>
/* For CHERI capability narrowing. */
#include <libc-cap.h>
#include <malloc/malloc-internal.h>
/* For SINGLE_THREAD_P. */
@@ -341,8 +344,12 @@ Fatal glibc error: malloc assertion failure in %s: %s\n",
It assumes a minimum page size of 4096 bytes (12 bits). Systems with
larger pages provide less entropy, although the pointer mangling
still works. */
#ifdef __CHERI_PURE_CAPABILITY__
#define PROTECT_PTR(pos, ptr) (ptr)
#else
#define PROTECT_PTR(pos, ptr) \
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#endif
#define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr)
/*
@@ -478,6 +485,153 @@ tag_at (void *ptr)
return ptr;
}
/* CHERI capability narrowing support. */
#ifdef __CHERI_PURE_CAPABILITY__
static bool cap_narrowing_enabled = true;
#else
# define cap_narrowing_enabled 0
#endif
static __always_inline void
cap_init (void)
{
if (cap_narrowing_enabled)
assert (__libc_cap_init ());
}
static __always_inline void
cap_fork_lock (void)
{
if (cap_narrowing_enabled)
__libc_cap_fork_lock ();
}
static __always_inline void
cap_fork_unlock_parent (void)
{
if (cap_narrowing_enabled)
__libc_cap_fork_unlock_parent ();
}
static __always_inline void
cap_fork_unlock_child (void)
{
if (cap_narrowing_enabled)
__libc_cap_fork_unlock_child ();
}
static __always_inline bool
cap_map_add (void *p)
{
if (cap_narrowing_enabled)
return __libc_cap_map_add (p);
return true;
}
static __always_inline void
cap_map_del (void *p)
{
if (cap_narrowing_enabled)
__libc_cap_map_del (p);
}
/* Round up size so capability bounds can be represented. */
static __always_inline size_t
cap_roundup (size_t n)
{
if (cap_narrowing_enabled)
return __libc_cap_roundup (n);
return n;
}
/* Alignment such that capability bounds can be represented. */
static __always_inline size_t
cap_align (size_t n)
{
if (cap_narrowing_enabled)
return __libc_cap_align (n);
return 1;
}
/* Narrow the bounds of p to [p, p+n) exactly unless p is NULL.
Must match a previous cap_reserve call. */
static __always_inline void *
cap_narrow (void *p, size_t n)
{
if (cap_narrowing_enabled)
{
if (p == NULL)
__libc_cap_unreserve ();
else
p = __libc_cap_narrow (p, n);
}
return p;
}
/* Used in realloc if p is already narrowed or NULL.
Must match a previous cap_reserve call. */
static __always_inline bool
cap_narrow_check (void *p, void *oldp)
{
if (cap_narrowing_enabled)
{
if (p == NULL)
(void) __libc_cap_narrow (oldp, 0);
else
__libc_cap_unreserve ();
}
return p != NULL;
}
/* Used in realloc if p is new allocation or NULL but not yet narrowed.
Must match a previous cap_reserve call. */
static __always_inline void *
cap_narrow_try (void *p, size_t n, void *oldp)
{
if (cap_narrowing_enabled)
{
if (p == NULL)
(void) __libc_cap_narrow (oldp, 0);
else
p = __libc_cap_narrow (p, n);
}
return p;
}
/* Widen back the bounds of a non-NULL p that was returned by cap_narrow. */
static __always_inline void *
cap_widen (void *p)
{
if (cap_narrowing_enabled)
return __libc_cap_widen (p);
return p;
}
/* Reserve memory for the following cap_narrow, this may fail with ENOMEM. */
static __always_inline bool
cap_reserve (void)
{
if (cap_narrowing_enabled)
return __libc_cap_reserve ();
return true;
}
/* Release the reserved memory by cap_reserve. */
static __always_inline void
cap_unreserve (void)
{
if (cap_narrowing_enabled)
__libc_cap_unreserve ();
}
/* Remove p so cap_widen no longer works on it. */
static __always_inline void
cap_drop (void *p)
{
if (cap_narrowing_enabled)
__libc_cap_drop (p);
}
#include <string.h>
/*
@@ -1130,8 +1284,16 @@ static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
# define MAP_NORESERVE 0
#endif
/* Allow RW mprotect later, on CHERI this means RW capability permission. */
#ifdef PROT_MAX
# define PROT_MAX_RW PROT_MAX (PROT_READ | PROT_WRITE)
#else
# define PROT_MAX_RW 0
#endif
#define MMAP(addr, size, prot, flags) \
__mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)
__mmap((addr), (size), (prot)|PROT_MAX_RW, \
(flags)|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)
/*
@@ -1288,6 +1450,18 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
_int_memalign: Returns untagged memory.
_mid_memalign: Returns tagged memory.
_int_realloc: Takes and returns tagged memory.
With CHERI capability narrowing enabled, public interfaces take and
return pointers with bounds that cannot access malloc internal chunk
headers. Narrowing CHERI capabilities in internal interfaces:
sysmalloc: Returns wide capability.
_int_malloc: Returns wide capability.
_int_free: Takes wide capability.
_int_memalign: Returns wide capability.
_int_memalign: Returns wide capability.
_mid_memalign: Returns narrow capability.
_int_realloc: Takes and returns wide capability.
*/
/* The chunk header is two SIZE_SZ elements, but this is used widely, so
@@ -2438,6 +2612,12 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
if (mm == MAP_FAILED)
return mm;
if (!cap_map_add (mm))
{
__munmap (mm, size);
return MAP_FAILED;
}
#ifdef MAP_HUGETLB
if (!(extra_flags & MAP_HUGETLB))
madvise_thp (mm, size);
@@ -2523,6 +2703,12 @@ sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
if (mbrk == MAP_FAILED)
return MAP_FAILED;
if (!cap_map_add (mbrk))
{
__munmap (mbrk, size);
return MAP_FAILED;
}
#ifdef MAP_HUGETLB
if (!(extra_flags & MAP_HUGETLB))
madvise_thp (mbrk, size);
@@ -3056,6 +3242,8 @@ munmap_chunk (mchunkptr p)
atomic_decrement (&mp_.n_mmaps);
atomic_add (&mp_.mmapped_mem, -total_size);
cap_map_del ((void *) block);
/* If munmap failed the process virtual memory address space is in a
bad shape. Just leave the block hanging around, the process will
terminate shortly anyway since not much can be done. */
@@ -3094,6 +3282,9 @@ mremap_chunk (mchunkptr p, size_t new_size)
if (cp == MAP_FAILED)
return 0;
cap_map_del ((void *) block);
cap_map_add (cp);
madvise_thp (cp, new_size);
p = (mchunkptr) (cp + offset);
@@ -3193,6 +3384,35 @@ tcache_get (size_t tc_idx)
return (void *) e;
}
/* Cut down __libc_free for cleaning up tcache entries. */
static void
tcache_libc_free (void *mem)
{
int err = errno;
mchunkptr p = mem2chunk(mem);
if (chunk_is_mmapped (p))
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
}
else
{
mstate ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);
}
__set_errno (err);
}
static void
tcache_thread_shutdown (void)
{
@@ -3218,11 +3438,11 @@ tcache_thread_shutdown (void)
malloc_printerr ("tcache_thread_shutdown(): "
"unaligned tcache chunk detected");
tcache_tmp->entries[i] = REVEAL_PTR (e->next);
__libc_free (e);
tcache_libc_free (e);
}
}
__libc_free (tcache_tmp);
tcache_libc_free (tcache_tmp);
}
static void
@@ -3287,7 +3507,13 @@ __libc_malloc (size_t bytes)
if (!__malloc_initialized)
ptmalloc_init ();
size_t align = cap_align (bytes);
bytes = cap_roundup (bytes);
#if USE_TCACHE
_Static_assert (MAX_TCACHE_SIZE <= __CAP_ALIGN_THRESHOLD,
"tcache entries are already aligned for capability narrowing");
/* int_free also calls request2size, be careful to not pad twice. */
size_t tbytes = checked_request2size (bytes);
if (tbytes == 0)
@@ -3304,17 +3530,28 @@ __libc_malloc (size_t bytes)
&& tcache
&& tcache->counts[tc_idx] > 0)
{
if (!cap_reserve ())
return NULL;
victim = tcache_get (tc_idx);
return tag_new_usable (victim);
victim = tag_new_usable (victim);
victim = cap_narrow (victim, bytes);
return victim;
}
DIAG_POP_NEEDS_COMMENT;
#endif
if (align > MALLOC_ALIGNMENT)
return _mid_memalign (align, bytes, 0);
if (!cap_reserve ())
return NULL;
if (SINGLE_THREAD_P)
{
victim = tag_new_usable (_int_malloc (&main_arena, bytes));
assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
&main_arena == arena_for_chunk (mem2chunk (victim)));
victim = cap_narrow (victim, bytes);
return victim;
}
@@ -3337,6 +3574,7 @@ __libc_malloc (size_t bytes)
assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
ar_ptr == arena_for_chunk (mem2chunk (victim)));
victim = cap_narrow (victim, bytes);
return victim;
}
libc_hidden_def (__libc_malloc)
@@ -3350,6 +3588,9 @@ __libc_free (void *mem)
if (mem == 0) /* free(0) has no effect */
return;
mem = cap_widen (mem);
cap_drop (mem);
/* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled))
@@ -3411,6 +3652,8 @@ __libc_realloc (void *oldmem, size_t bytes)
if (oldmem == 0)
return __libc_malloc (bytes);
oldmem = cap_widen (oldmem);
/* Perform a quick check to ensure that the pointer's tag matches the
memory's tag. */
if (__glibc_unlikely (mtag_enabled))
@@ -3437,6 +3680,8 @@ __libc_realloc (void *oldmem, size_t bytes)
|| __builtin_expect (misaligned_chunk (oldp), 0)))
malloc_printerr ("realloc(): invalid pointer");
size_t align = cap_align (bytes);
bytes = cap_roundup (bytes);
nb = checked_request2size (bytes);
if (nb == 0)
{
@@ -3444,10 +3689,23 @@ __libc_realloc (void *oldmem, size_t bytes)
return NULL;
}
/* Every return path below should unreserve using the cap_narrow* apis. */
if (!cap_reserve ())
return NULL;
cap_drop (oldmem);
if (chunk_is_mmapped (oldp))
{
void *newmem;
#ifdef __CHERI_PURE_CAPABILITY__
size_t pagesize = GLRO (dl_pagesize);
// TODO: with pcuabi kernel more cases can be handled by mremap
/* Don't try in-place realloc if oldmem is unaligned. */
if (align <= pagesize && ((size_t) oldmem & (align - 1)) == 0)
{
#endif
#if HAVE_MREMAP
newp = mremap_chunk (oldp, nb);
if (newp)
@@ -3458,30 +3716,65 @@ __libc_realloc (void *oldmem, size_t bytes)
reused. There's a performance hit for both us and the
caller for doing this, so we might want to
reconsider. */
return tag_new_usable (newmem);
newmem = tag_new_usable (newmem);
newmem = cap_narrow_try (newmem, bytes, oldmem);
return newmem;
}
#endif
#ifdef __CHERI_PURE_CAPABILITY__
}
size_t sz = oldsize - CHUNK_HDR_SZ;
/* In-place realloc if the size shrinks, but if it shrinks a lot
then don't waste the rest of the mapping. */
if (sz >= bytes && sz / 4 < bytes
&& ((size_t) oldmem & (align - 1)) == 0)
return cap_narrow (oldmem, bytes);
#else
/* Note the extra SIZE_SZ overhead. */
if (oldsize - SIZE_SZ >= nb)
return oldmem; /* do nothing */
#endif
/* Must alloc, copy, free. */
#ifdef __CHERI_PURE_CAPABILITY__
if (align > MALLOC_ALIGNMENT)
newmem = _mid_memalign (align, bytes, 0);
else
#endif
newmem = __libc_malloc (bytes);
if (newmem == 0)
if (!cap_narrow_check (newmem, oldmem))
return 0; /* propagate failure */
#ifdef __CHERI_PURE_CAPABILITY__
memcpy (newmem, oldmem, sz < bytes ? sz : bytes);
#else
memcpy (newmem, oldmem, oldsize - CHUNK_HDR_SZ);
#endif
munmap_chunk (oldp);
return newmem;
}
/* Large alignment is required and it's not possible to realloc in place. */
if (align > MALLOC_ALIGNMENT
&& (oldsize < nb || ((size_t) oldmem & (align - 1)) != 0))
{
/* Use memalign, copy, free. */
void *newmem = _mid_memalign (align, bytes, 0);
if (!cap_narrow_check (newmem, oldmem))
return newmem;
size_t sz = oldsize - CHUNK_HDR_SZ;
memcpy (newmem, oldmem, sz < bytes ? sz : bytes);
(void) tag_region (oldmem, sz);
_int_free (ar_ptr, oldp, 0);
return newmem;
}
if (SINGLE_THREAD_P)
{
newp = _int_realloc (ar_ptr, oldp, oldsize, nb);
assert (!newp || chunk_is_mmapped (mem2chunk (newp)) ||
ar_ptr == arena_for_chunk (mem2chunk (newp)));
return newp;
return cap_narrow_try (newp, bytes, oldmem);
}
__libc_lock_lock (ar_ptr->mutex);
@@ -3497,14 +3790,15 @@ __libc_realloc (void *oldmem, size_t bytes)
/* Try harder to allocate memory in other arenas. */
LIBC_PROBE (memory_realloc_retry, 2, bytes, oldmem);
newp = __libc_malloc (bytes);
if (newp != NULL)
{
size_t sz = memsize (oldp);
memcpy (newp, oldmem, sz);
(void) tag_region (chunk2mem (oldp), sz);
_int_free (ar_ptr, oldp, 0);
}
if (!cap_narrow_check (newp, oldmem))
return NULL;
size_t sz = memsize (oldp);
memcpy (newp, oldmem, sz);
(void) tag_region (chunk2mem (oldp), sz);
_int_free (ar_ptr, oldp, 0);
}
else
newp = cap_narrow (newp, bytes);
return newp;
}
@@ -3517,6 +3811,11 @@ __libc_memalign (size_t alignment, size_t bytes)
ptmalloc_init ();
void *address = RETURN_ADDRESS (0);
size_t align = cap_align (bytes);
bytes = cap_roundup (bytes);
if (align > alignment)
alignment = align;
return _mid_memalign (alignment, bytes, address);
}
@@ -3542,6 +3841,8 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
return 0;
}
if (!cap_reserve ())
return NULL;
/* Make sure alignment is power of 2. */
if (!powerof2 (alignment))
@@ -3557,7 +3858,9 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
p = _int_memalign (&main_arena, alignment, bytes);
assert (!p || chunk_is_mmapped (mem2chunk (p)) ||
&main_arena == arena_for_chunk (mem2chunk (p)));
return tag_new_usable (p);
p = tag_new_usable (p);
p = cap_narrow (p, bytes);
return p;
}
arena_get (ar_ptr, bytes + alignment + MINSIZE);
@@ -3575,7 +3878,9 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
assert (!p || chunk_is_mmapped (mem2chunk (p)) ||
ar_ptr == arena_for_chunk (mem2chunk (p)));
return tag_new_usable (p);
p = tag_new_usable (p);
p = cap_narrow (p, bytes);
return p;
}
/* For ISO C11. */
weak_alias (__libc_memalign, aligned_alloc)
@@ -3589,6 +3894,10 @@ __libc_valloc (size_t bytes)
void *address = RETURN_ADDRESS (0);
size_t pagesize = GLRO (dl_pagesize);
size_t align = cap_align (bytes);
bytes = cap_roundup (bytes);
if (align > pagesize)
pagesize = align;
return _mid_memalign (pagesize, bytes, address);
}
@@ -3611,6 +3920,10 @@ __libc_pvalloc (size_t bytes)
}
rounded_bytes = rounded_bytes & -(pagesize - 1);
size_t align = cap_align (rounded_bytes);
rounded_bytes = cap_roundup (rounded_bytes);
if (align > pagesize)
pagesize = align;
return _mid_memalign (pagesize, rounded_bytes, address);
}
@@ -3633,12 +3946,28 @@ __libc_calloc (size_t n, size_t elem_size)
}
sz = bytes;
sz = cap_roundup (sz);
if (!__malloc_initialized)
ptmalloc_init ();
size_t align = cap_align (bytes);
if (align > MALLOC_ALIGNMENT)
{
mem = _mid_memalign (align, sz, 0);
if (mem == NULL)
return mem;
mchunkptr p = mem2chunk (cap_widen (mem));
if (chunk_is_mmapped (p) && __glibc_likely (perturb_byte == 0))
return mem;
return memset (mem, 0, sz);
}
MAYBE_INIT_TCACHE ();
if (!cap_reserve ())
return NULL;
if (SINGLE_THREAD_P)
av = &main_arena;
else
@@ -3690,6 +4019,8 @@ __libc_calloc (size_t n, size_t elem_size)
}
/* Allocation failed even after a retry. */
if (mem == 0)
cap_unreserve ();
if (mem == 0)
return 0;
@@ -3699,13 +4030,19 @@ __libc_calloc (size_t n, size_t elem_size)
regardless of MORECORE_CLEARS, so we zero the whole block while
doing so. */
if (__glibc_unlikely (mtag_enabled))
return tag_new_zero_region (mem, memsize (p));
{
mem = tag_new_zero_region (mem, memsize (p));
mem = cap_narrow (mem, sz);
return mem;
}
INTERNAL_SIZE_T csz = chunksize (p);
/* Two optional cases in which clearing not necessary */
if (chunk_is_mmapped (p))
{
mem = cap_narrow (mem, sz);
if (__builtin_expect (perturb_byte, 0))
return memset (mem, 0, sz);
@@ -3729,8 +4066,7 @@ __libc_calloc (size_t n, size_t elem_size)
assert (nclears >= 3);
if (nclears > 9)
return memset (d, 0, clearsize);
mem = memset (mem, 0, clearsize);
else
{
*(d + 0) = 0;
@@ -3753,6 +4089,7 @@ __libc_calloc (size_t n, size_t elem_size)
}
}
mem = cap_narrow (mem, sz);
return mem;
}
#endif /* IS_IN (libc) */
@@ -4978,8 +5315,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
we can move to the next aligned spot -- we've allocated enough
total room so that this is always possible.
*/
brk = (char *) mem2chunk (((unsigned long) (m + alignment - 1)) &
- ((signed long) alignment));
brk = (char *) mem2chunk (m + alignment - ((unsigned long) (m) % alignment));
if ((unsigned long) (brk - (char *) (p)) < MINSIZE)
brk += alignment;
@@ -5135,6 +5471,7 @@ __malloc_usable_size (void *m)
{
if (m == NULL)
return 0;
m = cap_widen (m);
return musable (m);
}
#endif
@@ -5681,6 +6018,10 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
|| alignment == 0)
return EINVAL;
size_t align = cap_align (size);
size = cap_roundup (size);
if (align > alignment)
alignment = align;
void *address = RETURN_ADDRESS (0);
mem = _mid_memalign (alignment, size, address);
+1 -1
View File
@@ -74,7 +74,7 @@ checkhdr (const struct hdr *hdr)
an error and report it. */
return MCHECK_OK;
switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
switch (hdr->magic ^ ((unsigned long) hdr->prev + (unsigned long) hdr->next))
{
default:
status = MCHECK_HEAD;
+3 -16
View File
@@ -116,22 +116,9 @@
# define PTR_INT_TYPE ptrdiff_t
#endif
/* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1. B and P must be of type
char *. A + 1 must be a power of 2. */
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers,
and converted back again. If PTR_INT_TYPE is narrower than a
pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \
__BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
/* Align P to the next multiple of A + 1, where A + 1 is a power of 2,
A fits into unsigned long and P has type char *. */
#define __PTR_ALIGN(B, P, A) ((P) + (-(unsigned long)(P) & (A)))
#include <string.h>
+7 -15
View File
@@ -155,21 +155,13 @@ do_test (void)
struct scratch_buffer buf;
scratch_buffer_init (&buf);
memset (buf.data, '@', buf.length);
size_t sizes[] = { 16, buf.length, buf.length + 16 };
for (int i = 0; i < array_length (sizes); i++)
{
/* The extra size is unitialized through realloc. */
size_t l = sizes[i] > buf.length ? sizes[i] : buf.length;
void *r = scratch_buffer_dupfree (&buf, l);
void *c = xmalloc (l);
memset (c, '@', l);
TEST_COMPARE_BLOB (r, l, buf.data, l);
free (r);
free (c);
}
scratch_buffer_free (&buf);
size_t l = 16 <= buf.length ? 16 : buf.length;
void *r = scratch_buffer_dupfree (&buf, l);
void *c = xmalloc (l);
memset (c, '@', l);
TEST_COMPARE_BLOB (r, l, c, l);
free (r);
free (c);
}
return 0;
}
+6
View File
@@ -612,3 +612,9 @@ support in the kernel if this tunable has any non-zero value.
The default value is @samp{0}, which disables all memory tagging.
@end deftp
@deftp Tunable glibc.mem.cap_narrowing
On CHERI architecture use capability bounds narrowing in the malloc
implementation. By default it is set to 1, to disable bounds narrowing
set it to 0.
@end deftp
+3
View File
@@ -164,6 +164,9 @@ libc {
GLIBC_2.32 {
__libc_single_threaded;
}
GLIBC_2.37 {
__getauxptr; getauxptr;
}
GLIBC_PRIVATE {
__madvise;
__mktemp;
+33
View File
@@ -20,6 +20,39 @@
#include <ldsodefs.h>
#include <stdbool.h>
void *
__getauxptr (unsigned long int type)
{
/* error if asking for a non-pointer from getauxptr(). This list is not a
perfect enforcement as it currently supports both transitional and draft
ABIs, which have different capability entries. */
switch (type) {
case AT_ENTRY:
case AT_PHDR:
case AT_BASE:
case AT_SYSINFO_EHDR:
case AT_EXECFN:
case AT_RANDOM:
case AT_PLATFORM:
case AT_CHERI_EXEC_RW_CAP:
case AT_CHERI_EXEC_RX_CAP:
case AT_CHERI_INTERP_RW_CAP:
case AT_CHERI_INTERP_RX_CAP:
case AT_CHERI_SEAL_CAP:
{
ElfW(auxv_t) *p;
for (p = GLRO(dl_auxv); p->a_type != AT_NULL; p++)
if (p->a_type == type)
return (void *) p->a_un.a_val;
}
}
__set_errno (ENOENT);
return 0;
}
weak_alias (__getauxptr, getauxptr)
libc_hidden_def (__getauxptr)
bool
__getauxval2 (unsigned long int type, unsigned long int *result)
{
+4
View File
@@ -31,6 +31,10 @@ __BEGIN_DECLS
extern unsigned long int getauxval (unsigned long int __type)
__THROW;
/* Same as getauxval, but for Arm Morello capabilities. */
extern void * getauxptr (unsigned long int __type)
__THROW;
__END_DECLS
#endif /* sys/auxv.h */
+4 -4
View File
@@ -131,15 +131,15 @@ typedef struct node_t
uintptr_t right_node;
} *node;
#define RED(N) (node)((N)->left_node & ((uintptr_t) 0x1))
#define RED(N) (unsigned int)((N)->left_node & ((uintptr_t) 0x1))
#define SETRED(N) (N)->left_node |= ((uintptr_t) 0x1)
#define SETBLACK(N) (N)->left_node &= ~((uintptr_t) 0x1)
#define SETNODEPTR(NP,P) (*NP) = (node)((((uintptr_t)(*NP)) \
#define SETNODEPTR(NP,P) (*NP) = (node)((unsigned int)(((uintptr_t)(*NP)) \
& (uintptr_t) 0x1) | (uintptr_t)(P))
#define LEFT(N) (node)((N)->left_node & ~((uintptr_t) 0x1))
#define LEFTPTR(N) (node *)(&(N)->left_node)
#define SETLEFT(N,L) (N)->left_node = (((N)->left_node & (uintptr_t) 0x1) \
| (uintptr_t)(L))
#define SETLEFT(N,L) (N)->left_node = ((unsigned int)((N)->left_node \
& (uintptr_t) 0x1) | (uintptr_t)(L))
#define RIGHT(N) (node)((N)->right_node)
#define RIGHTPTR(N) (node *)(&(N)->right_node)
#define SETRIGHT(N,R) (N)->right_node = (uintptr_t)(R)
+9 -1
View File
@@ -52,6 +52,13 @@
# define MAP_STACK 0
#endif
/* On CHERI targets ensure the mmap returned capability has RW permissions. */
#ifdef PROT_MAX
# define PROT_MAX_RW PROT_MAX (PROT_READ | PROT_WRITE)
#else
# define PROT_MAX_RW 0
#endif
/* Get a stack frame from the cache. We have to match by size since
some blocks might be too small or far too large. */
static struct pthread *
@@ -363,7 +370,8 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
/* If a guard page is required, avoid committing memory by first
allocate with PROT_NONE and then reserve with required permission
excluding the guard page. */
mem = __mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
mem = __mmap (NULL, size,
(guardsize == 0) ? prot : PROT_NONE | PROT_MAX_RW,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (__glibc_unlikely (mem == MAP_FAILED))
+8 -1
View File
@@ -19,7 +19,9 @@
#include <limits.h>
#include "pthreadP.h"
#include <shlib-compat.h>
#ifdef __CHERI_PURE_CAPABILITY__
# include <cheri_perms.h>
#endif
#ifndef NEW_VERNUM
# define NEW_VERNUM GLIBC_2_3_3
@@ -43,6 +45,11 @@ __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
EXTRA_PARAM_CHECKS;
#endif
#ifdef __CHERI_PURE_CAPABILITY__
if (!STACK_CAP_CHECK (stackaddr, stacksize))
return EINVAL;
#endif
iattr->stacksize = stacksize;
#if _STACK_GROWS_DOWN
iattr->stackaddr = (char *) stackaddr + stacksize;
+4
View File
@@ -204,7 +204,11 @@ typedef __off64_t __loff_t; /* Type of file sizes and offsets (LFS). */
typedef char *__caddr_t;
/* Duplicates info from stdint.h but this is used in unistd.h. */
#ifdef __CHERI_PURE_CAPABILITY__
__STD_TYPE __intcap_t __intptr_t;
#else
__STD_TYPE __SWORD_TYPE __intptr_t;
#endif
/* Duplicate info from sys/socket.h. */
__STD_TYPE __U32_TYPE __socklen_t;
+1 -1
View File
@@ -7,7 +7,7 @@ main (void)
int retval = 0;
long int res;
res = ulimit (UL_SETFSIZE, 10000);
res = ulimit (UL_SETFSIZE, 10000L);
printf ("Result of ulimit (UL_SETFSIZE, 10000): %ld\n", res);
if (res != 10000)
retval = 1;
+17 -1
View File
@@ -159,8 +159,24 @@ class Context(object):
"""Add all known glibc build configurations."""
self.add_config(arch='aarch64',
os_name='linux-gnu',
gcc_cfg=['--with-multilib-list=lp64,purecap',
'--disable-libgomp', '--disable-libitm'],
glibcs=[{},
{'variant': 'purecap',
'ccopts': '-mabi=purecap -march=morello+c64',
'cfg': ['--disable-werror']}],
extra_glibcs=[{'variant': 'disable-multi-arch',
'cfg': ['--disable-multi-arch']}])
'cfg': ['--disable-multi-arch']},
{'variant': 'purecap-nopie',
'ccopts': '-mabi=purecap -march=morello+c64',
'cfg': ['--disable-werror', '--disable-default-pie']}])
self.add_config(arch='aarch64',
os_name='linux-gnu_purecap',
gcc_cfg=['--with-abi=purecap', '--with-arch=morello+c64', '--disable-multilib',
'--disable-libgomp', '--disable-libitm'],
glibcs=[{'cfg': ['--disable-werror']}],
extra_glibcs=[{'variant': 'nopie',
'cfg': ['--disable-werror', '--disable-default-pie']}])
self.add_config(arch='aarch64_be',
os_name='linux-gnu')
self.add_config(arch='arc',
+1 -1
View File
@@ -177,7 +177,7 @@ END {
n = indices[2];
m = indices[3];
printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, false, TUNABLE_SECLEVEL_%s, %s},\n",
types[t,n,m], minvals[t,n,m], maxvals[t,n,m],
default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]);
}
+5
View File
@@ -80,6 +80,7 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
spec->info.pad = ' ';
spec->info.wide = sizeof (UCHAR_T) > 1;
spec->info.is_binary128 = 0;
spec->info.is_cap = 0;
/* Test for positional argument. */
if (ISDIGIT (*format))
@@ -371,6 +372,10 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
break;
case L'p':
spec->data_arg_type = PA_POINTER;
#ifdef __CHERI_PURE_CAPABILITY__
if (spec->info.alt)
spec->info.is_cap = 1;
#endif
break;
case L'n':
spec->data_arg_type = PA_INT|PA_FLAG_PTR;
+2 -1
View File
@@ -50,7 +50,8 @@ struct printf_info
unsigned int i18n:1; /* I flag. */
unsigned int is_binary128:1; /* Floating-point argument is ABI-compatible
with IEC 60559 binary128. */
unsigned int __pad:3; /* Unused so far. */
unsigned int is_cap:1; /* CHERI capability. */
unsigned int __pad:2; /* Unused so far. */
unsigned short int user; /* Bits for user-installed modifiers. */
wchar_t pad; /* Padding character. */
};
+1
View File
@@ -67,6 +67,7 @@ main (void)
buf[2049] = 0x84;
buf[2058] = '\t';
buf[2059] = 'a';
buf[sizeof (buf) - 1] = '\0';
if (sscanf (buf, "%ms%mc", &sp1, &sp2) != 2)
FAIL ();
else
+15
View File
@@ -116,6 +116,10 @@
while (0)
#endif
#ifdef __CHERI_PURE_CAPABILITY__
# include <cheri_perms.h>
#endif
/* Add LENGTH to DONE. Return the new value of DONE, or -1 on
overflow (and set errno accordingly). */
static inline int
@@ -792,6 +796,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
int base;
union printf_arg the_arg;
CHAR_T *string; /* Pointer to argument string. */
#ifdef __CHERI_PURE_CAPABILITY__
const void *cap = 0;
#endif
int alt = 0; /* Alternate format. */
int space = 0; /* Use space prefix if no sign is needed. */
int left = 0; /* Left-justify output. */
@@ -805,6 +812,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
int is_char = 0; /* Argument is promoted (unsigned) char. */
int width = 0; /* Width of output; 0 means none specified. */
int prec = -1; /* Precision of output; -1 means none specified. */
__attribute__((unused))
int is_cap = 0; /* Argument is a capability. */
/* This flag is set by the 'I' modifier and selects the use of the
`outdigits' as determined by the current locale. */
int use_outdigits = 0;
@@ -1324,6 +1334,9 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
} number;
int base;
CHAR_T *string; /* Pointer to argument string. */
#ifdef __CHERI_PURE_CAPABILITY__
const void *cap = 0;
#endif
/* Fill variables from values in struct. */
int alt = specs[nspecs_done].info.alt;
@@ -1338,6 +1351,8 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
int is_long = specs[nspecs_done].info.is_long;
int width = specs[nspecs_done].info.width;
int prec = specs[nspecs_done].info.prec;
__attribute__((unused))
int is_cap = specs[nspecs_done].info.is_cap;
int use_outdigits = specs[nspecs_done].info.i18n;
char pad = specs[nspecs_done].info.pad;
CHAR_T spec = specs[nspecs_done].info.spec;
+121
View File
@@ -25,6 +25,115 @@
{
/* Start real work. We know about all flags and modifiers and
now process the wanted format specifier. */
/* Process capability information according to the CHERI C Programming guide:
https://github.com/CTSRD-CHERI/cheri-c-programming/wiki/Displaying-Capabilities */
#ifdef __CHERI_PURE_CAPABILITY__
LABEL (capability):
/* CHERI capability. */
{
uint64_t cap_perm = 0;
uint64_t cap_base = 0;
uint64_t cap_limit = 0;
uint64_t cap_tag = 0;
uint64_t cap_type = 0;
outchar (L_(' '));
outchar (L_('['));
cap_perm = __builtin_cheri_perms_get (cap);
if (cap_perm & CAP_PERM_LOAD)
outchar (L_('r'));
if (cap_perm & CAP_PERM_STORE)
outchar (L_('w'));
if (cap_perm & CAP_PERM_EXECUTE)
outchar (L_('x'));
if (cap_perm & CAP_PERM_LOAD_CAP)
outchar (L_('R'));
if (cap_perm & CAP_PERM_STORE_CAP)
outchar (L_('W'));
if (cap_perm & CAP_PERM_EXECUTIVE)
outchar (L_('E'));
outchar (L_(','));
cap_base = __builtin_cheri_base_get (cap);
number.word = (unsigned long int) cap_base;
if (prec < 0)
prec = 1;
else
pad = L_(' ');
string = _itoa_word (number.word, workend, base, spec == L_('X'));
prec = MAX (0, prec - (workend - string));
width -= workend - string + prec;
if (number.word != 0)
width -= 2;
if (pad == L_(' '))
{
PAD (L_(' '));
width = 0;
}
if (number.word != 0)
{
outchar (L_('0'));
outchar (spec);
}
width += prec;
PAD (L_('0'));
outstring (string, workend - string);
outchar (L_('-'));
cap_limit = __builtin_cheri_length_get (cap) + cap_base;
number.word = (unsigned long int) cap_limit;
if (prec < 0)
prec = 1;
else
pad = L_(' ');
string = _itoa_word (number.word, workend, base, spec == L_('X'));
prec = MAX (0, prec - (workend - string));
width -= workend - string + prec;
if (number.word != 0)
width -= 2;
if (pad == L_(' '))
{
PAD (L_(' '));
width = 0;
}
if (number.word != 0)
{
outchar (L_('0'));
outchar (spec);
}
width += prec;
PAD (L_('0'));
outstring (string, workend - string);
outchar (L_(']'));
cap_tag = __builtin_cheri_tag_get (cap);
if (!cap_tag)
{
outchar (L_(' '));
outchar (L_('('));
outstring ("invalid", 8);
outchar (L_(')'));
break;
}
cap_type = __builtin_cheri_type_get (cap);
if (cap_type != 0)
{
if (cap_type == 1)
{
outchar (L_(' '));
outchar (L_('('));
outstring ("sentry", 7);
outchar (L_(')'));
}
else
{
outchar (L_(' '));
outchar (L_('('));
outstring ("sealed", 7);
outchar (L_(')'));
}
}
}
break;
#endif
LABEL (form_percent):
/* Write a literal "%". */
outchar (L_('%'));
@@ -212,6 +321,11 @@ LABEL (unsigned_number): /* Unsigned number of base BASE. */
outstring (string, workend - string);
#ifdef __CHERI_PURE_CAPABILITY__
if (is_cap == 1)
goto LABEL(capability);
#endif
break;
}
else
@@ -265,6 +379,13 @@ LABEL (form_pointer):
base = 16;
number.word = (unsigned long int) ptr;
is_negative = 0;
#ifdef __CHERI_PURE_CAPABILITY__
if (alt == 1)
{
cap = ptr;
is_cap = 1;
}
#endif
alt = 1;
group = 0;
spec = L_('x');
+8
View File
@@ -64,9 +64,17 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
thousands_len = strlen (thousands);
#endif
#ifdef USE_WIDE_CHAR
while (end > begin)
#else
while (end - begin >= thousands_len)
#endif
{
#ifdef USE_WIDE_CHAR
const STRING_TYPE *cp = end - 1;
#else
const STRING_TYPE *cp = end - thousands_len;
#endif
const char *gp = grouping;
/* Check first group. */
+4
View File
@@ -289,6 +289,10 @@ __qsort_r (void *b, size_t n, size_t s, __compar_d_fn_t cmp, void *arg)
&& ((char *) b - (char *) 0) % __alignof__ (uint64_t) == 0)
p.var = 1;
else if ((s & (sizeof (unsigned long) - 1)) == 0
#ifdef __CHERI_PURE_CAPABILITY__
&& ((char *) b - (char *) 0)
% __alignof__ (void *) != 0
#endif
&& ((char *) b - (char *) 0)
% __alignof__ (unsigned long) == 0)
p.var = 2;
+12
View File
@@ -84,10 +84,22 @@ typedef unsigned long long int uint_fast64_t;
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
# ifdef __CHERI_PURE_CAPABILITY__
typedef __intcap_t intptr_t;
# else
typedef long int intptr_t;
# endif
# define __intptr_t_defined
# endif
# ifdef __CHERI_PURE_CAPABILITY__
typedef __uintcap_t uintptr_t;
# else
typedef unsigned long int uintptr_t;
# endif
# if defined __CHERI__ && !defined __CHERI_PURE_CAPABILITY__
typedef __uintcap_t uintcap_t;
typedef __intcap_t intcap_t;
# endif
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
+3 -1
View File
@@ -63,7 +63,7 @@ last (void)
}
int
main (void)
do_test (void)
{
int value;
void *dso;
@@ -90,3 +90,5 @@ main (void)
FAIL_EXIT1 ("Did not terminate via exit(0) in exit_thread() as expected.");
}
#include <support/test-driver.c>
+7 -6
View File
@@ -27,6 +27,7 @@
#endif
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -529,7 +530,7 @@ test_strlen (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strlen (p) == 2, 4+i);
@@ -554,7 +555,7 @@ test_strnlen (void)
char buf[4096];
for (int i = 0; i < 0x100; ++i)
{
char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
char *p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p + 3, "BAD/WRONG");
check (strnlen (p, 100) == 2, 10 + i);
@@ -582,7 +583,7 @@ test_strchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strchr (p, '/') == NULL, 9+i);
@@ -614,7 +615,7 @@ test_strchrnul (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
cp = strchrnul (p, '/');
@@ -643,7 +644,7 @@ test_rawmemchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (rawmemchr (p, 'R') == p+8, 6+i);
@@ -689,7 +690,7 @@ test_strrchr (void)
char *p;
for (i=0; i < 0x100; i++)
{
p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
strcpy (p, "OK");
strcpy (p+3, "BAD/WRONG");
check (strrchr (p, '/') == NULL, 9+i);
+1 -1
View File
@@ -151,7 +151,7 @@ allocate_big (size_t total_size, const void *element, size_t element_size,
/* Reserve the memory region. If we cannot create the mapping,
there is no reason to set up the backing file. */
void *target = mmap (NULL, total_size, PROT_NONE,
void *target = mmap (NULL, total_size, PROT_NONE | PROT_MAX_RW,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (target == MAP_FAILED)
return (struct support_blob_repeat) { 0 };
+40 -2
View File
@@ -98,7 +98,8 @@ void support_record_failure (void);
/* Compare the two integers LEFT and RIGHT and report failure if they
are different. */
#define TEST_COMPARE(left, right) \
#ifndef __CHERI_PURE_CAPABILITY__
# define TEST_COMPARE(left, right) \
({ \
/* + applies the integer promotions, for bitfield support. */ \
typedef __typeof__ (+ (left)) __left_type; \
@@ -126,6 +127,32 @@ void support_record_failure (void);
#left, __left_value, __left_is_positive, sizeof (__left_type), \
#right, __right_value, __right_is_positive, sizeof (__right_type)); \
})
#else
# define TEST_COMPARE(left, right) \
({ \
/* + applies the integer promotions, for bitfield support. */ \
typedef __typeof__ (+ (left)) __left_type; \
typedef __typeof__ (+ (right)) __right_type; \
__left_type __left_value = (left); \
__right_type __right_value = (right); \
int __left_is_positive = __left_value > 0; \
int __right_is_positive = __right_value > 0; \
/* Prevent use with floating-point types. */ \
support_static_assert ((__left_type) 1.0 == (__left_type) 1.5, \
"left value has floating-point type"); \
support_static_assert ((__right_type) 1.0 == (__right_type) 1.5, \
"right value has floating-point type"); \
/* Compare the value. */ \
if (__left_value != __right_value \
|| __left_is_positive != __right_is_positive) \
/* Pass the sign for printing the correct value. */ \
support_test_compare_failure \
(__FILE__, __LINE__, \
#left, __left_value, __left_is_positive, sizeof (__left_type), \
#right, __right_value, __right_is_positive, sizeof (__right_type)); \
})
#endif
/* Internal implementation of TEST_COMPARE. LEFT_POSITIVE and
RIGHT_POSITIVE are used to store the sign separately, so that both
@@ -133,6 +160,7 @@ void support_record_failure (void);
RIGHT_VALUE, and the function can still print the original value.
LEFT_SIZE and RIGHT_SIZE specify the size of the argument in bytes,
for hexadecimal formatting. */
#ifndef __CHERI_PURE_CAPABILITY__
void support_test_compare_failure (const char *file, int line,
const char *left_expr,
long long left_value,
@@ -142,7 +170,17 @@ void support_test_compare_failure (const char *file, int line,
long long right_value,
int right_positive,
int right_size);
#else
void support_test_compare_failure (const char *file, int line,
const char *left_expr,
__uintcap_t left_value,
int left_positive,
int left_size,
const char *right_expr,
__uintcap_t right_value,
int right_positive,
int right_size);
#endif
/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT +
RIGHT_LENGTH) and report a test failure if the arrays are
+1 -1
View File
@@ -60,7 +60,7 @@ support_stack_alloc (size_t size)
so we know they are allocated. */
void *alloc_base = xmmap (0,
alloc_size,
PROT_NONE,
PROT_NONE|PROT_MAX_RW,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK,
-1);
/* Some architecture still requires executable stack for the signal return
+25
View File
@@ -34,6 +34,7 @@ report (const char *which, const char *expr, long long value, int positive,
printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr);
}
#ifndef __CHERI_PURE_CAPABILITY__
void
support_test_compare_failure (const char *file, int line,
const char *left_expr,
@@ -56,3 +57,27 @@ support_test_compare_failure (const char *file, int line,
report ("right", right_expr, right_value, right_positive, right_size);
errno = saved_errno;
}
#else
void
support_test_compare_failure (const char *file, int line,
const char *left_expr,
__uintcap_t left_value,
int left_positive,
int left_size,
const char *right_expr,
__uintcap_t right_value,
int right_positive,
int right_size)
{
int saved_errno = errno;
support_record_failure ();
if (left_size != right_size)
printf ("%s:%d: numeric comparison failure (widths %d and %d)\n",
file, line, left_size * 8, right_size * 8);
else
printf ("%s:%d: numeric comparison failure\n", file, line);
report (" left", left_expr, left_value, left_positive, left_size);
report ("right", right_expr, right_value, right_positive, right_size);
errno = saved_errno;
}
#endif
+8
View File
@@ -25,6 +25,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
__BEGIN_DECLS
@@ -77,6 +78,13 @@ void xclose (int);
/* Write the buffer. Retry on short writes. */
void xwrite (int, const void *, size_t);
/* On CHERI targets ensure the mmap returned capability has RW permissions. */
#ifdef PROT_MAX
# define PROT_MAX_RW PROT_MAX (PROT_READ | PROT_WRITE)
#else
# define PROT_MAX_RW 0
#endif
/* Invoke mmap with a zero file offset. */
void *xmmap (void *addr, size_t length, int prot, int flags, int fd);
void xmprotect (void *addr, size_t length, int prot);
+8 -2
View 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
@@ -39,7 +39,7 @@ gen-as-const-headers += dl-link.sym
tests-internal += tst-ifunc-arg-1 tst-ifunc-arg-2
ifeq (yes,$(aarch64-variant-pcs))
ifeq (yesyesno,$(aarch64-variant-pcs)$(build-shared)$(aarch64-purecap))
tests += tst-vpcs
modules-names += tst-vpcs-mod
LDFLAGS-tst-vpcs-mod.so = -Wl,-z,lazy
@@ -68,3 +68,9 @@ endif
ifeq ($(subdir),malloc)
sysdep_malloc_debug_routines = __mtag_tag_zero_region __mtag_tag_region
endif
ifeq (yes,$(aarch64-purecap))
ifeq ($(subdir),stdio-common)
tests += tst-printf-cap
endif
endif
+21
View File
@@ -54,6 +54,13 @@
model, __ATOMIC_RELAXED); \
})
# define __arch_compare_and_exchange_bool_128_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
!__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
model, __ATOMIC_RELAXED); \
})
# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
@@ -86,6 +93,14 @@
__oldval; \
})
# define __arch_compare_and_exchange_val_128_int(mem, newval, oldval, model) \
({ \
typeof (*mem) __oldval = (oldval); \
__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
model, __ATOMIC_RELAXED); \
__oldval; \
})
/* Compare and exchange with "acquire" semantics, ie barrier after. */
@@ -118,6 +133,9 @@
# define __arch_exchange_64_int(mem, newval, model) \
__atomic_exchange_n (mem, newval, model)
# define __arch_exchange_128_int(mem, newval, model) \
__atomic_exchange_n (mem, newval, model)
# define atomic_exchange_acq(mem, value) \
__atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
@@ -139,6 +157,9 @@
# define __arch_exchange_and_add_64_int(mem, value, model) \
__atomic_fetch_add (mem, value, model)
# define __arch_exchange_and_add_128_int(mem, value, model) \
__atomic_fetch_add (mem, value, model)
# define atomic_exchange_and_add_acq(mem, value) \
__atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
__ATOMIC_ACQUIRE)
+4 -1
View File
@@ -27,7 +27,10 @@
/* Jump buffer contains:
x19-x28, x29(fp), x30(lr), (x31)sp, d8-d15. Other registers are not
saved. */
# ifndef __CHERI_PURE_CAPABILITY__
__extension__ typedef unsigned long long __jmp_buf [22];
# else
__extension__ typedef __uintcap_t __jmp_buf [22];
# endif
#endif
#endif
+1 -1
View File
@@ -17,7 +17,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifdef __LP64__
#if defined __LP64__ || defined __CHERI_PURE_CAPABILITY__
# define __WORDSIZE 64
#else
# define __WORDSIZE 32
Vendored Regular → Executable
+45 -9
View File
@@ -1,10 +1,6 @@
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
# Local configure fragment for sysdeps/aarch64.
# Static PIE is supported.
$as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
# We check to see if the compiler and flags are
# selecting the big endian ABI and if they are then
# we set libc_cv_aarch64_be to yes which causes
@@ -167,16 +163,56 @@ rm -f conftest*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_be" >&5
$as_echo "$libc_cv_aarch64_be" >&6; }
# Check for purecap ABI too, an alternative name is l64pc128.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for purecap ABI" >&5
$as_echo_n "checking for purecap ABI... " >&6; }
if ${libc_cv_aarch64_purecap+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __CHERI_PURE_CAPABILITY__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "yes" >/dev/null 2>&1; then :
libc_cv_aarch64_purecap=yes
else
libc_cv_aarch64_purecap=no
fi
rm -f conftest*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_purecap" >&5
$as_echo "$libc_cv_aarch64_purecap" >&6; }
config_vars="$config_vars
aarch64-purecap = $libc_cv_aarch64_purecap"
libc_aarch64_be=""
if test $libc_cv_aarch64_be = yes; then
$as_echo "#define HAVE_AARCH64_BE 1" >>confdefs.h
config_vars="$config_vars
default-abi = lp64_be"
else
config_vars="$config_vars
default-abi = lp64"
libc_aarch64_be="_be"
fi
libc_aarch64_abi="lp64"
if test $libc_cv_aarch64_purecap = yes; then
libc_aarch64_abi="purecap"
# The purecap abi requires relocations because objects may not be
# within bounds for PCC. This means static-pie is not supported.
$as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h
else
# Static PIE is supported. Hidden variables only need relocations
# in PIE with -mcmodel=large, but that's unsupported.
$as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
fi
config_vars="$config_vars
default-abi = $libc_aarch64_abi$libc_aarch64_be"
# Only consider BTI supported if -mbranch-protection=bti is
# on by default in the compiler and the linker produces
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
+24 -6
View File
@@ -1,9 +1,6 @@
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# Local configure fragment for sysdeps/aarch64.
# Static PIE is supported.
AC_DEFINE(SUPPORT_STATIC_PIE)
# We check to see if the compiler and flags are
# selecting the big endian ABI and if they are then
# we set libc_cv_aarch64_be to yes which causes
@@ -17,13 +14,34 @@ AC_CACHE_CHECK([for big endian],
yes
#endif
], libc_cv_aarch64_be=yes, libc_cv_aarch64_be=no)])
# Check for purecap ABI too, an alternative name is l64pc128.
AC_CACHE_CHECK([for purecap ABI],
[libc_cv_aarch64_purecap],
[AC_EGREP_CPP(yes,[#ifdef __CHERI_PURE_CAPABILITY__
yes
#endif
], libc_cv_aarch64_purecap=yes, libc_cv_aarch64_purecap=no)])
LIBC_CONFIG_VAR([aarch64-purecap], [$libc_cv_aarch64_purecap])
libc_aarch64_be=""
if test $libc_cv_aarch64_be = yes; then
AC_DEFINE(HAVE_AARCH64_BE)
LIBC_CONFIG_VAR([default-abi], [lp64_be])
else
LIBC_CONFIG_VAR([default-abi], [lp64])
libc_aarch64_be="_be"
fi
libc_aarch64_abi="lp64"
if test $libc_cv_aarch64_purecap = yes; then
libc_aarch64_abi="purecap"
# The purecap abi requires relocations because objects may not be
# within bounds for PCC. This means static-pie is not supported.
AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC)
else
# Static PIE is supported. Hidden variables only need relocations
# in PIE with -mcmodel=large, but that's unsupported.
AC_DEFINE(SUPPORT_STATIC_PIE)
fi
LIBC_CONFIG_VAR([default-abi], [$libc_aarch64_abi$libc_aarch64_be])
# Only consider BTI supported if -mbranch-protection=bti is
# on by default in the compiler and the linker produces
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
+8
View File
@@ -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)
+2 -1
View File
@@ -36,7 +36,8 @@
static inline int __attribute__ ((unused))
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
{
return ehdr->e_machine == EM_AARCH64;
return ehdr->e_machine == EM_AARCH64
&& (ehdr->e_flags & EF_AARCH64_CHERI_PURECAP) == 0;
}
/* Return the run-time load address of the shared object. */
View File
+9
View File
@@ -22,6 +22,15 @@
#include <elf.h>
#include <cpu-features.h>
#ifdef __CHERI_PURE_CAPABILITY__
# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
elf_machine_rela_relative (map, relative)
#define D_PTR_RW(map, i) \
(dl_relocate_ld (map) ? (map)->i->d_un.d_ptr \
: dl_rw_ptr ((map), (map)->i->d_un.d_ptr))
#endif
struct La_aarch64_regs;
struct La_aarch64_retval;
+1 -1
View File
@@ -20,7 +20,7 @@
struct link_map_machine
{
ElfW(Addr) plt; /* Address of .plt */
elfptr_t plt; /* Address of .plt */
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
bool bti_fail; /* Failed to enable Branch Target Identification. */
};
+6
View File
@@ -0,0 +1,6 @@
ld {
GLIBC_PRIVATE {
# in ld.so, but used by libc.so too.
_dl_symbol_address;
}
}
+108
View File
@@ -0,0 +1,108 @@
/* 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 <sysdep.h>
#include <jmpbuf-offsets.h>
#include <stap-probe.h>
/* __longjmp(jmpbuf, val) */
ENTRY (__longjmp)
cfi_def_cfa(c0, 0)
cfi_offset(c19, JB_X19<<4)
cfi_offset(c20, JB_X20<<4)
cfi_offset(c21, JB_X21<<4)
cfi_offset(c22, JB_X22<<4)
cfi_offset(c23, JB_X23<<4)
cfi_offset(c24, JB_X24<<4)
cfi_offset(c25, JB_X25<<4)
cfi_offset(c26, JB_X26<<4)
cfi_offset(c27, JB_X27<<4)
cfi_offset(c28, JB_X28<<4)
cfi_offset(c29, JB_X29<<4)
cfi_offset(c30, JB_LR<<4)
cfi_offset(q8, JB_D8<<4)
cfi_offset(q9, JB_D9<<4)
cfi_offset(q10, JB_D10<<4)
cfi_offset(q11, JB_D11<<4)
cfi_offset(q12, JB_D12<<4)
cfi_offset(q13, JB_D13<<4)
cfi_offset(q14, JB_D14<<4)
cfi_offset(q15, JB_D15<<4)
ldp c19, c20, [c0, #JB_X19<<4]
ldp c21, c22, [c0, #JB_X21<<4]
ldp c23, c24, [c0, #JB_X23<<4]
ldp c25, c26, [c0, #JB_X25<<4]
ldp c27, c28, [c0, #JB_X27<<4]
ldp c29, c30, [c0, #JB_X29<<4]
/* longjmp probe takes 3 arguments, address of jump buffer as
first argument (8@x0), return value as second argument (-4@x1),
and target address (8@x30), respectively. */
LIBC_PROBE (longjmp, 3, 8@c0, -4@c1, 8@c30)
ldp q8, q9, [c0, #JB_D8<<4]
ldp q10, q11, [c0, #JB_D10<<4]
ldp q12, q13, [c0, #JB_D12<<4]
ldp q14, q15, [c0, #JB_D14<<4]
/* Originally this was implemented with a series of
.cfi_restore() directives.
The theory was that cfi_restore should revert to previous
frame value is the same as the current value. In practice
this doesn't work, even after cfi_restore() gdb continues
to try to recover a previous frame value offset from x0,
which gets stuffed after a few more instructions. The
cfi_same_value() mechanism appears to work fine. */
cfi_same_value(c19)
cfi_same_value(c20)
cfi_same_value(c21)
cfi_same_value(c22)
cfi_same_value(c23)
cfi_same_value(c24)
cfi_same_value(c25)
cfi_same_value(c26)
cfi_same_value(c27)
cfi_same_value(c28)
cfi_same_value(c29)
cfi_same_value(c30)
cfi_same_value(q8)
cfi_same_value(q9)
cfi_same_value(q10)
cfi_same_value(q11)
cfi_same_value(q12)
cfi_same_value(q13)
cfi_same_value(q14)
cfi_same_value(q15)
ldr c5, [c0, #JB_SP<<4]
mov csp, c5
/* longjmp_target probe takes 3 arguments, address of jump buffer
as first argument (8@x0), return value as second argument (-4@x1),
and target address (8@x30), respectively. */
LIBC_PROBE (longjmp_target, 3, 8@c0, -4@c1, 8@c30)
cmp x1, #0
mov x0, #1
csel x0, x1, x0, ne
/* Use br instead of ret because ret is guaranteed to mispredict */
br c30
END (__longjmp)
+36
View File
@@ -0,0 +1,36 @@
#include <stdint.h>
#include <ldsodefs.h>
#include <cheri_perms.h>
static inline uintptr_t
morello_relative (uint64_t base, uintptr_t cap_rx, uintptr_t cap_rw,
const ElfW(Rela) *reloc, void *reloc_addr)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
/* Fragment identified by r_offset has the following information:
| 64-bit: address | 56-bits: length | 8-bits: permissions | */
unsigned long loc = u64_reloc_addr[0];
unsigned long len = u64_reloc_addr[1] & ((1UL << 56) - 1);
unsigned long perm = u64_reloc_addr[1] >> 56;
uintptr_t value;
/* Permissions field is encoded as:
4 = executable, 2 = read/write, 1 = read-only. */
if (perm == 2)
value = __builtin_cheri_address_set (cap_rw, base + loc);
else
value = __builtin_cheri_address_set (cap_rx, base + loc);
value = __builtin_cheri_bounds_set_exact (value, len);
value = value + reloc->r_addend;
if (perm == 1)
value = __builtin_cheri_perms_and (value, CAP_PERM_MASK_R);
/* Seal executable capabilities with MORELLO_RB. */
if (perm == 4)
value = __builtin_cheri_seal_entry (value);
return value;
}
+84
View File
@@ -0,0 +1,84 @@
/* 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/>. */
#ifndef _AARCH64_MORELLO_CHERI_PERMS_H
#define _AARCH64_MORELLO_CHERI_PERMS_H
/* Capability permission bits. These are defined in the Arm Architecture
Reference Manual Suplement- Morello for A-Profile Architecture:
https://developer.arm.com/documentation/ddi0606/latest */
#define CAP_PERM_LOAD (1 << 17)
#define CAP_PERM_STORE (1 << 16)
#define CAP_PERM_EXECUTE (1 << 15)
#define CAP_PERM_LOAD_CAP (1 << 14)
#define CAP_PERM_STORE_CAP (1 << 13)
#define CAP_PERM_STORE_LOCAL (1 << 12)
#define CAP_PERM_SEAL (1 << 11)
#define CAP_PERM_UNSEAL (1 << 10)
#define CAP_PERM_SYSTEM (1 << 9)
#define CAP_PERM_BRANCH_SEALED_PAIR (1 << 8)
#define CAP_PERM_COMPARTMENT_ID (1 << 7)
#define CAP_PERM_MUTABLE_LOAD (1 << 6)
#define CAP_PERM_EXECUTIVE (1 << 1)
#define CAP_PERM_GLOBAL (1 << 0)
/* Used with __builtin_cheri_perms_and. */
#define CAP_PERM_MASK_BASE (-1UL ^ ( \
CAP_PERM_LOAD | \
CAP_PERM_STORE | \
CAP_PERM_EXECUTE | \
CAP_PERM_LOAD_CAP | \
CAP_PERM_MUTABLE_LOAD | \
CAP_PERM_STORE_CAP | \
CAP_PERM_STORE_LOCAL | \
CAP_PERM_EXECUTIVE | \
CAP_PERM_SYSTEM | \
CAP_PERM_SEAL | \
CAP_PERM_UNSEAL | \
CAP_PERM_COMPARTMENT_ID))
#define CAP_PERM_MASK_R ( \
CAP_PERM_MASK_BASE | \
CAP_PERM_LOAD | \
CAP_PERM_LOAD_CAP | \
CAP_PERM_MUTABLE_LOAD)
#define CAP_PERM_MASK_RW ( \
CAP_PERM_MASK_R | \
CAP_PERM_STORE | \
CAP_PERM_STORE_CAP | \
CAP_PERM_STORE_LOCAL)
#define CAP_PERM_MASK_RX ( \
CAP_PERM_MASK_R | \
CAP_PERM_EXECUTE | \
CAP_PERM_EXECUTIVE | \
CAP_PERM_SYSTEM)
#define STACK_CAP_PERM_PCS ( \
CAP_PERM_LOAD | \
CAP_PERM_STORE | \
CAP_PERM_LOAD_CAP | \
CAP_PERM_STORE_CAP | \
CAP_PERM_MUTABLE_LOAD)
/* Check if stack is valid according to stack PCS rules. Only permissions
are checked, seal and invalid tag cause fault on access. */
#define STACK_CAP_CHECK(stack, size) \
({unsigned long __perm = __builtin_cheri_perms_get (stack); \
(__perm & (CAP_PERM_GLOBAL|CAP_PERM_STORE_LOCAL)) \
&& (__perm & STACK_CAP_PERM_PCS) == STACK_CAP_PERM_PCS;})
#endif
+93
View File
@@ -0,0 +1,93 @@
/* Special .init and .fini section support for Morello.
Copyright (C) 1995-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.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
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/>. */
/* crti.S puts a function prologue at the beginning of the .init and
.fini sections and defines global symbols for those addresses, so
they can be called as functions. The symbols _init and _fini are
magic and cause the linker to emit DT_INIT and DT_FINI. */
#include <sysdep.h>
#include <libc-symbols.h>
#ifndef PREINIT_FUNCTION
# define PREINIT_FUNCTION __gmon_start__
#endif
#ifndef PREINIT_FUNCTION_WEAK
# define PREINIT_FUNCTION_WEAK 1
#endif
#if PREINIT_FUNCTION_WEAK
weak_extern (PREINIT_FUNCTION)
#else
.hidden PREINIT_FUNCTION
#endif
#if PREINIT_FUNCTION_WEAK
.align 2
.type call_weak_fn, %function
call_weak_fn:
adrp c0, :got:PREINIT_FUNCTION
ldr c0, [c0, #:got_lo12:PREINIT_FUNCTION]
cbz x0, 1f
b PREINIT_FUNCTION
1:
RET
.size call_weak_fn, .-call_weak_fn
#endif
.section .init,"ax",%progbits
.align 2
.global _init
.hidden _init
.type _init, %function
_init:
stp c29, c30, [csp, -32]!
mov c29, csp
#if PREINIT_FUNCTION_WEAK
bl call_weak_fn
#else
bl PREINIT_FUNCTION
#endif
.section .fini,"ax",%progbits
.align 2
.global _fini
.hidden _fini
.type _fini, %function
_fini:
stp c29, c30, [csp, -32]!
mov c29, csp
+48
View File
@@ -0,0 +1,48 @@
/* Special .init and .fini section support for Morello.
Copyright (C) 1995-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.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
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/>. */
/* crtn.S puts function epilogues in the .init and .fini sections
corresponding to the prologues in crti.S. */
#include <sysdep.h>
.section .init,"ax",%progbits
ldp c29, c30, [csp], 32
RET
.section .fini,"ax",%progbits
ldp c29, c30, [csp], 32
RET
+68
View File
@@ -0,0 +1,68 @@
/* Machine-dependent ELF indirect relocation inline functions.
AArch64 version.
Copyright (C) 2012-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/>. */
#ifndef _DL_IREL_H
#define _DL_IREL_H
#include <stdio.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sysdep.h>
#include <sys/ifunc.h>
#define ELF_MACHINE_IRELA 1
static inline uintptr_t
__attribute ((always_inline))
elf_ifunc_invoke (uintptr_t addr)
{
__ifunc_arg_t arg;
arg._size = sizeof (arg);
arg._hwcap = GLRO(dl_hwcap);
arg._hwcap2 = GLRO(dl_hwcap2);
return ((uintptr_t (*) (uint64_t, const __ifunc_arg_t *)) (addr))
(GLRO(dl_hwcap) | _IFUNC_ARG_HWCAP, &arg);
}
#include <cheri-rel.h>
static inline void
__attribute ((always_inline))
elf_irela (const ElfW(Rela) *reloc)
{
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
if (__glibc_likely (r_type == MORELLO_R(IRELATIVE)))
{
struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
void *reloc_addr = (void *) dl_rw_ptr (main_map, reloc->r_offset);
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
uint64_t base = main_map->l_addr;
uintptr_t cap_rx = main_map->l_map_start;
uintptr_t cap_rw = main_map->l_rw_start;
uintptr_t value
= morello_relative (base, cap_rx, cap_rw, reloc, reloc_addr);
*cap_reloc_addr = elf_ifunc_invoke (value);
}
else
__libc_fatal ("Unexpected reloc type in static binary.\n");
}
#endif
+473
View File
@@ -0,0 +1,473 @@
/* Copyright (C) 1995-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/>. */
#ifndef dl_machine_h
#define dl_machine_h
#define ELF_MACHINE_NAME "aarch64"
#include <sysdep.h>
#include <tls.h>
#include <dl-tlsdesc.h>
#include <dl-static-tls.h>
#include <dl-irel.h>
#include <dl-machine-rel.h>
#include <cpu-features.c>
/* Translate a processor specific dynamic tag to the index in l_info array. */
#define DT_AARCH64(x) (DT_AARCH64_##x - DT_LOPROC + DT_NUM)
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int __attribute__ ((unused))
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
{
return ehdr->e_machine == EM_AARCH64
&& (ehdr->e_flags & EF_AARCH64_CHERI_PURECAP) != 0;
}
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int __attribute__ ((unused))
elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
int lazy, int profile)
{
if (l->l_info[DT_JMPREL] && lazy)
{
uintptr_t *got;
extern void _dl_runtime_resolve (ElfW(Word));
extern void _dl_runtime_profile (ElfW(Word));
got = (uintptr_t *) D_PTR_RW (l, l_info[DT_PLTGOT]);
if (got[1])
{
l->l_mach.plt = dl_rx_ptr (l, got[1]);
}
got[1] = (uintptr_t) l;
/* The got[2] entry contains the address of a function which gets
called to get the address of a so far unresolved function and
jump to it. The profiling extension of the dynamic linker allows
to intercept the calls to collect information. In this case we
don't store the address in the GOT so that all future calls also
end in this function. */
if ( profile)
{
got[2] = (uintptr_t) &_dl_runtime_profile;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
/* Say that we really want profiling and the timers are
started. */
GL(dl_profile_map) = l;
}
else
{
/* This function will get called to fix up the GOT entry
indicated by the offset on the stack, and then jump to
the resolved address. */
got[2] = (uintptr_t) &_dl_runtime_resolve;
}
}
return lazy;
}
/* Runtime _DYNAMIC without dynamic relocations. */
static void * __attribute__ ((unused))
elf_machine_runtime_dynamic (void)
{
void *p;
asm (""
".weak _DYNAMIC\n"
".hidden _DYNAMIC\n"
"adrp %0, _DYNAMIC\n"
"add %0, %0, :lo12:_DYNAMIC\n" : "=r"(p));
return p;
}
/* PCC relative access to ehdr before relocations are processed. */
static const ElfW(Ehdr) *
elf_machine_ehdr (void)
{
const void *p;
asm (""
".weak __ehdr_start\n"
".hidden __ehdr_start\n"
"adrp %0, __ehdr_start\n"
"add %0, %0, :lo12:__ehdr_start\n" : "=r"(p));
return p;
}
/* Set up ld.so root capabilities and base address from args. */
static void __attribute__ ((unused))
elf_machine_rtld_base_setup (struct link_map *map, void *args)
{
uintptr_t *sp;
long argc;
uintptr_t cap_rx, cap_rw, cap_exe_rx, cap_exe_rw;
unsigned long ldso_base = 0;
sp = args;
argc = sp[0];
/* Skip argv. */
sp += argc + 2;
/* Skip environ. */
for (; *sp; sp++);
sp++;
cap_rx = cap_rw = cap_exe_rx = cap_exe_rw = 0;
for (; *sp != AT_NULL; sp += 2)
{
long t = sp[0];
if (t == AT_BASE)
ldso_base = sp[1];
if (t == AT_CHERI_INTERP_RX_CAP)
cap_rx = sp[1];
if (t == AT_CHERI_INTERP_RW_CAP)
cap_rw = sp[1];
if (t == AT_CHERI_EXEC_RX_CAP)
cap_exe_rx = sp[1];
if (t == AT_CHERI_EXEC_RW_CAP)
cap_exe_rw = sp[1];
}
/* Check if ldso is the executable. */
if (ldso_base == 0)
{
cap_rx = cap_exe_rx;
cap_rw = cap_exe_rw;
ldso_base = cap_rx; /* Assume load segments start at vaddr 0. */
}
cap_rx = __builtin_cheri_perms_and (cap_rx, CAP_PERM_MASK_RX);
cap_rw = __builtin_cheri_perms_and (cap_rw, CAP_PERM_MASK_RW);
map->l_addr = ldso_base;
map->l_map_start = cap_rx;
map->l_rw_start = cap_rw;
/* Set up the RW ranges of ld.so, required for symbolic relocations. */
const ElfW(Ehdr) *ehdr = elf_machine_ehdr ();
const ElfW(Phdr) *phdr = (const void *) ehdr + ehdr->e_phoff;
if (sizeof *phdr != ehdr->e_phentsize)
__builtin_trap ();
for (const ElfW(Phdr) *ph = phdr; ph < phdr + ehdr->e_phnum; ph++)
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W))
{
uintptr_t allocend = map->l_addr + ph->p_vaddr + ph->p_memsz;
if (map->l_rw_count >= DL_MAX_RW_COUNT)
__builtin_trap ();
map->l_rw_range[map->l_rw_count].start = map->l_addr + ph->p_vaddr;
map->l_rw_range[map->l_rw_count].end = allocend;
map->l_rw_count++;
}
}
/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it. */
#define RTLD_START asm (".globl _dl_start");
#define elf_machine_type_class(type) \
(((type) == MORELLO_R(JUMP_SLOT) \
|| (type) == MORELLO_R(TPREL128) \
|| (type) == MORELLO_R(TLSDESC)) * ELF_RTYPE_CLASS_PLT)
#define ELF_MACHINE_JMP_SLOT MORELLO_R(JUMP_SLOT)
#define DL_PLATFORM_INIT dl_platform_init ()
static inline void __attribute__ ((unused))
dl_platform_init (void)
{
if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
/* Avoid an empty string which would disturb us. */
GLRO(dl_platform) = NULL;
#ifdef SHARED
/* init_cpu_features has been called early from __libc_start_main in
static executable. */
init_cpu_features (&GLRO(dl_aarch64_cpu_features));
#endif
}
static inline uintptr_t
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
const ElfW(Rela) *reloc,
uintptr_t *reloc_addr,
uintptr_t value)
{
return *reloc_addr = value;
}
/* Return the final value of a plt relocation. */
static inline uintptr_t
elf_machine_plt_value (struct link_map *map,
const ElfW(Rela) *reloc,
uintptr_t value)
{
return value;
}
#endif
/* Names of the architecture-specific auditing callback functions. */
#define ARCH_LA_PLTENTER aarch64_gnu_pltenter
#define ARCH_LA_PLTEXIT aarch64_gnu_pltexit
#ifdef RESOLVE_MAP
# include <cheri_perms.h>
static inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
const struct r_found_version *version,
void *const reloc_addr, int skip_ifunc)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
if (r_type == MORELLO_R(RELATIVE))
*cap_reloc_addr = morello_relative (map->l_addr, map->l_map_start,
map->l_rw_start, reloc, reloc_addr);
else if (r_type == AARCH64_R(RELATIVE))
*u64_reloc_addr = map->l_addr + reloc->r_addend;
else if (__builtin_expect (r_type == R_AARCH64_NONE, 0))
return;
else
{
struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
r_type);
uintptr_t value = SYMBOL_ADDRESS (sym_map, sym, true);
if (sym != NULL
&& __glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
&& __glibc_likely (sym->st_shndx != SHN_UNDEF)
&& __glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
switch (r_type)
{
case MORELLO_R(CAPINIT):
case MORELLO_R(GLOB_DAT):
case MORELLO_R(JUMP_SLOT):
{
if (sym == NULL)
{
/* Undefined weak symbol. */
*cap_reloc_addr = value + reloc->r_addend;
break;
}
unsigned long perm_mask = CAP_PERM_MASK_RX;
switch (ELFW(ST_TYPE) (sym->st_info))
{
case STT_OBJECT:
perm_mask = CAP_PERM_MASK_R;
for (int i = 0; i < sym_map->l_rw_count; i++)
if (sym_map->l_rw_range[i].start <= value
&& sym_map->l_rw_range[i].end > value)
{
value = dl_rw_ptr (sym_map, value - sym_map->l_addr);
perm_mask = CAP_PERM_MASK_RW;
break;
}
value = __builtin_cheri_bounds_set_exact (value, sym->st_size);
break;
case STT_FUNC:
case STT_GNU_IFUNC:
/* value already has RX bounds. */
break;
default:
/* STT_NONE or unknown symbol: readonly. */
perm_mask = CAP_PERM_MASK_R;
}
value = value + reloc->r_addend;
value = __builtin_cheri_perms_and (value, perm_mask);
/* Seal capabilities, which provide execute permission, with MORELLO_RB. */
if (perm_mask == CAP_PERM_MASK_RX)
value = __builtin_cheri_seal_entry (value);
*cap_reloc_addr = value;
}
break;
# ifndef RTLD_BOOTSTRAP
case AARCH64_R(ABS64):
*u64_reloc_addr = value + reloc->r_addend;
break;
case MORELLO_R(IRELATIVE):
{
uintptr_t value = morello_relative (map->l_addr,
map->l_map_start,
map->l_rw_start,
reloc,
reloc_addr);
if (__glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
*cap_reloc_addr = value;
}
break;
case MORELLO_R(TLSDESC):
{
struct tlsdesc volatile *td = reloc_addr;
if (! sym)
{
td->pair.off = reloc->r_addend;
td->entry = _dl_tlsdesc_undefweak;
}
else
{
# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
# else
if (!TRY_STATIC_TLS (map, sym_map))
{
size_t size = td->pair.size;
if (size == 0)
size = sym->st_size;
struct tlsdesc_dynamic_arg *arg = _dl_make_tlsdesc_dynamic
(sym_map, sym->st_value + reloc->r_addend);
arg->tlsinfo.ti_size = size;
td->arg = arg;
td->entry = _dl_tlsdesc_dynamic;
}
else
# endif
{
td->pair.off = sym->st_value + sym_map->l_tls_offset
+ reloc->r_addend;
if (td->pair.size == 0)
td->pair.size = sym->st_size;
td->entry = _dl_tlsdesc_return;
}
}
}
break;
case MORELLO_R(TPREL128):
{
CHECK_STATIC_TLS (map, sym_map);
u64_reloc_addr[0] = sym->st_value + reloc->r_addend
+ sym_map->l_tls_offset;
if (u64_reloc_addr[1] == 0)
u64_reloc_addr[1] = sym->st_size;
}
break;
# endif /* !RTLD_BOOTSTRAP */
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
}
}
}
static inline void
__attribute__ ((always_inline))
elf_machine_rela_relative (struct link_map *map, const ElfW(Rela) *reloc)
{
ElfW(Addr) l_addr = map->l_addr;
uintptr_t cap_rx = map->l_map_start;
uintptr_t cap_rw = map->l_rw_start;
void *const reloc_addr
= (void *) __builtin_cheri_address_set (cap_rw, l_addr + reloc->r_offset);
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
if (r_type == MORELLO_R(RELATIVE))
*cap_reloc_addr = morello_relative (l_addr, cap_rx, cap_rw,
reloc, reloc_addr);
else
*u64_reloc_addr = l_addr + reloc->r_addend;
}
static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr,
const ElfW(Rela) *reloc,
int skip_ifunc)
{
void *reloc_addr = (void *) dl_rw_ptr (map, reloc->r_offset);
uintptr_t *__attribute__((may_alias)) cap_reloc_addr = reloc_addr;
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == MORELLO_R(JUMP_SLOT), 1))
{
if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
{
/* Check the symbol table for variant PCS symbols. */
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
const ElfW (Sym) *symtab =
(const void *)D_PTR (map, l_info[DT_SYMTAB]);
const ElfW (Sym) *sym = &symtab[symndx];
if (__glibc_unlikely (sym->st_other & STO_AARCH64_VARIANT_PCS))
{
/* Avoid lazy resolution of variant PCS symbols. */
const struct r_found_version *version = NULL;
if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
const ElfW (Half) *vernum =
(const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
version = &map->l_versions[vernum[symndx] & 0x7fff];
}
elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
skip_ifunc);
return;
}
}
if (map->l_mach.plt == 0)
*cap_reloc_addr = dl_rx_ptr (map, *cap_reloc_addr);
else
*cap_reloc_addr = map->l_mach.plt;
}
else if (__builtin_expect (r_type == MORELLO_R(TLSDESC), 1))
{
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
const ElfW (Sym) *sym = &symtab[symndx];
const struct r_found_version *version = NULL;
if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
const ElfW (Half) *vernum =
(const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
version = &map->l_versions[vernum[symndx] & 0x7fff];
}
/* Always initialize TLS descriptors completely, because lazy
initialization requires synchronization at every TLS access. */
elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
skip_ifunc);
}
else if (__glibc_unlikely (r_type == MORELLO_R(IRELATIVE)))
{
uintptr_t value = morello_relative (map->l_addr, map->l_map_start,
map->l_rw_start, reloc, reloc_addr);
if (__glibc_likely (!skip_ifunc))
value = elf_ifunc_invoke (value);
*cap_reloc_addr = value;
}
else
_dl_reloc_bad_type (map, r_type, 1);
}
#endif
+61
View File
@@ -0,0 +1,61 @@
/* Function to access r_debug structure. 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 <stdint.h>
#include <link.h>
static int
E(callback) (struct dl_phdr_info *info, size_t size, void *data)
{
/* Assume phdr covers the load segments. */
const void *phdr = info->dlpi_phdr;
uintptr_t *p = data;
unsigned long addr = *p;
unsigned long base = __builtin_cheri_base_get (phdr);
unsigned long len = __builtin_cheri_length_get (phdr);
if (addr - base >= len)
return 0;
*p = __builtin_cheri_address_set ((uintptr_t) phdr, addr);
return 1;
}
/* Return a valid runtime pointer to r_debug instead of an address since
that's how this function is used despite its generic prototype.
Assume the lookup is for the main exe and return uintptr_t type. */
static inline uintptr_t
E(r_debug_address) (ElfW(Dyn) *d)
{
if (d->d_tag != DT_DEBUG)
return 0;
uintptr_t p = d->d_un.d_ptr;
if (dl_iterate_phdr (E(callback), &p) == 1)
return p;
return 0;
}
/* Return the offset of the struct r_debug before relocation. */
static inline EW(Addr)
E(r_debug_offset) (EW(Dyn) *d, int fd, EW(Addr) offset)
{
if (d->d_tag == DT_DEBUG)
return (EW(Addr)) d->d_un.d_ptr;
return 0;
}

Some files were not shown because too many files have changed in this diff Show More