| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
| |
Capability narrowing uses a lookup table from an address to the
internally used wide capability. Keep the narrow capability in the
table instead of just the address and check it. This allows free
and realloc to check their input and only accept capabilities
exactly matching what was returned by malloc.
When a user adds restrictions on top of malloc returned capabilities
(e.g. narrower bounds), realloc could bypass those restrictions when
it simply looked up the internal wide capability for the address.
|
|
|
|
|
|
|
|
| |
Once the kernel starts providing a VDSO, old binaries should continue
to work (without using the new VDSO). For this we set the vdso to 0
independently of auxv, otherwise glibc attempts to load it even if the
target has no vdso symbols specified and the load can crash since the
setup code is not purecap compatible.
|
| |
|
|
|
|
|
|
|
|
|
| |
Internally obstack used a backward word at a time copy. This can be
an aliasing violation and likely slower than memcpy on most targets.
The code is a badly written memcpy with performance issues such as
the h->object_base indirection cannot be hoisted out of the loop.
On CHERI architecture this is needed for copying pointers correctly.
|
|
|
|
|
|
|
|
|
|
| |
New code in realloc that handles when new allocation is needed for
alignment reasons (for capability narrowing) used the wrong size in
memcpy (size was off by SIZE_SZ unless memory tagging was enabled)
and used wrongly tagged pointer for untagging the old memory.
Due to this bug realloc sometimes failed to copy tail bytes of an old
allocation to the new allocation when capability narrowing is enabled.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Capability narrowing requires extra alignment for large allocations,
this can cause significant heap fragmentation so ensure large
allocations use a single mmap and unmaped on free. The fragmentation
is bug 14581.
This patch disables dynamic mmap threshold when cap_narrowing is
enabled and uses a threshold of 256 kbytes on morello (which means
at most 64 byte alignment requirement on the heap). The dynamic
threshold could quickly grow very big and stay there making the
fragmentation issue common.
|
|
|
|
|
| |
Morello linux does not support brk syscall, so fail early in the malloc
implementation instead of trying to use the syscall which always fails.
|
|
|
|
|
|
| |
Capability narrowing uses a lookup table and the old logic could
cause unnecessary resizes after deletes with the smallest lookup
table size.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The obstack version should have been bumped after
commit 2fd4de4b15a66f821057af90714145d2c034a609
[BZ #321]
which changed a ptrdiff_t struct member into a union of ptrdiff_t and a
pointer and thus changed the ABI on targets where ptrdiff_t and pointer
have different size or alignment. This affects CHERI targets.
Old versions of obstack are used in the wild and conflict with the one
provided by glibc so at least on CHERI targets it has to be bumped.
On other targets we don't bump the version as it changes compile time
behaviour (the ABI remains backward compatible either way).
|
| |
|
|
|
|
|
| |
malloc/tst-malloc-backtrace tests heap corruption.
malloc/tst-dynarray uses malloc_debug wrappers that access internals.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
__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.
|
|
|
|
| |
On CHERI targets getauxval cannot return a valid pointer.
|
| |
|
|
|
|
| |
Updates libc.abilist files for getauxptr to version 2.37.
|
|
|
|
|
|
|
| |
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
|
|
|
|
| |
TEST_COMPARE should allow comparison between two capability values.
|
|
|
|
| |
Testcase for printing 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.
|
|
|
|
|
| |
In pthread_attr_setstack fail with EINVAL if the input stack does not
meet the PCS constraints.
|
|
|
|
| |
Adjust padding to accommodate pointer size and alignment increase.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
Note: this is morello specific and does not work for generic cheri.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
TODO: needs agreement across cheri libcs
|
|
|
|
| |
TODO: not needed with full pcuabi
|
|
|
|
| |
Larger requirement because pointers are bigger.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
Writable version of D_PTR, required for updating GOT[1] and GOT[2].
|
|
|
|
|
|
|
|
|
| |
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.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
RELATIVE and IRELATIVE relocs use a helper function from cheri-rel.h
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)
void elf_machine_rtld_base_setup (struct link_map *map, void *args)
The ld.so load address and RX, RW capabilities are derived from auxv
and the RW ranges are set up based on the ld.so program headers early.
__tls_get_addr should return a bounded pointer instead of fixing it in
_dl_make_tlsdesc_dynamic, this is done in a separate patch.
|
| |
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
| |
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.)
|
|
|
|
| |
Propagate capabilities during lazy binding and IFUNC fixup in dlsym.
|
|
|
|
|
|
|
|
| |
Type of relocation addresses must be changed from ElfW(Addr) to
elfptr_t to cover both traditional and CHERI ABIs.
And relative relocation processing must have access to the link_map
to derive pointers from the right per module capability.
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
|
|
|
|
| |
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).
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
Prevent lp64 ld.so loading purecap binaries.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Instead of
map->l_addr + offset
use
dl_rx_ptr (map, offset)
dl_rw_ptr (map, offset)
depending on RX or RW permission requirement.
|
|
|
|
|
| |
Ensure mmap returns pointers with RWX permission covering all segments.
These pointers later get restricted to RX and RW permission.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
_dl_map_segments must use capabilities, this required changes beyond
the obvious elfptr_t changes:
- Ensure map_end is derived from map_start,
- Use strict mmap bounds with MAP_FIXED: c->mapend is aligned up to
pagesize which may be out of bounds of l_map_start (covering the
load segments, but bounds are not aligned up), so use c->dataend
instead.
Propagate l_map_start and l_rw_start capabilities of ld.so and exe that
come from auxv, and ensure they are not recomputed incorrectly by ld.so.
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.
|
|
|
|
|
|
|
|
|
|
|
|
| |
It is simpler and more consistent to make l_entry a capability
throughout instead of leaving it as an address and converting before
use:
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.
Functions returning a pointer to the user entry are also changed to
use elfptr_t.
|
|
|
|
|
|
|
|
|
| |
The purecap version of aarch64 dl-start.S. Note: self relocation of
ld.so is handled by the rtld bootstrap code.
The ldso internal _dl_start still expects continuous argc, argv, envp,
auxv, so that's emulated (since the purecap ELF entry passes them in
separate registers).
|
|
|
|
| |
The dynamic section cannot be relocated to hold pointers in place.
|
|
|
|
|
|
| |
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.
|