Compare commits

...
Author SHA1 Message Date
Szabolcs Nagy 33cb9de5cb cheri: malloc: exact capability check in free/realloc
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.
2023-04-05 15:29:59 +01:00
Szabolcs Nagy 47e61ba772 TODO(vdso): aarch64: morello: disable VDSO loading
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.
2023-02-21 16:48:20 +00:00
Szabolcs Nagy b63904f34f TODO(uapi): aarch64: morello: update HWCAP2_MORELLO 2023-02-02 10:53:47 +00:00
Szabolcs Nagy 807b692012 cheri: malloc: Use memcpy for obstack internal copy
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.
2023-01-06 10:03:51 +00:00
Szabolcs Nagy bbce0c75f3 cheri: malloc: Fix realloc to copy all relevant bytes
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.
2022-12-19 14:59:06 +00:00
Szabolcs Nagy dc23cc8021 cheri: malloc: Set fixed mmap_threshold for capability narrowing
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.
2022-12-09 11:30:55 +00:00
Szabolcs Nagy da7a5b5f4d cheri: malloc: Set __always_fail_morecore
Morello linux does not support brk syscall, so fail early in the malloc
implementation instead of trying to use the syscall which always fails.
2022-12-08 17:41:46 +00:00
Szabolcs Nagy 7701243cce aarch64: morello: malloc: better lookup table resize logic
Capability narrowing uses a lookup table and the old logic could
cause unnecessary resizes after deletes with the smallest lookup
table size.
2022-12-08 17:41:46 +00:00
Szabolcs Nagy 1861652b2e cheri: malloc: bump OBSTACK_INTERFACE_VERSION
The obstack version should have been bumped after

  commit 2fd4de4b15
  [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).
2022-12-08 17:27:31 +00:00
Szabolcs Nagy ae90dd111b morello: Provide documentation about the morello port. 2022-11-22 14:35:46 +00:00
Szabolcs Nagy c38427f52d 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-11-22 14:31:25 +00:00
Szabolcs Nagy de51f7328e cheri: malloc: add tunable to turn narrowing off 2022-11-22 14:31:25 +00:00
Szabolcs Nagy bd8fac4e28 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-11-22 14:31:25 +00:00
Szabolcs Nagy d7d9ee6edc 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-11-22 14:31:25 +00:00
Szabolcs Nagy 32c64139ee 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-11-22 14:31:25 +00:00
Szabolcs Nagy e0bde77854 cheri: use getauxptr in iconv/tst-gconv-init-failure test
On CHERI targets getauxval cannot return a valid pointer.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo a05a3def72 cheri: elf: Fix tst-auxv for Morello 2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 1eb01283dd cheri: Update libc.abilist for getauxptr
Updates libc.abilist files for getauxptr to version 2.37.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo f1d4e42835 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 4661ab7a69 support: Fix TEST_COMPARE for uintptr_t.
TEST_COMPARE should allow comparison between two capability values.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo eb7d21e59b cheri: stdio-common: Add test for %#p printf modifier
Testcase for printing capabilities.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 36d565f7e3 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 5e606fb79c 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-11-22 14:31:25 +00:00
Szabolcs Nagy 040bc860fe cheri: Fix sigevent ABI
Adjust padding to accommodate pointer size and alignment increase.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy abb1d6bb41 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).

Note: this is morello specific and does not work for generic cheri.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 3e833b93fd 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-11-22 14:31:25 +00:00
Szabolcs Nagy 9d6a71514d 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-11-22 14:31:25 +00:00
Szabolcs Nagy 44388a14fc TODO(api): cheri: elfptr_t in public api for unwinder
TODO: needs agreement across cheri libcs
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 4deaee41ce TODO(uapi): cheri: start: restrict auxv capability permissions
TODO: not needed with full pcuabi
2022-11-22 14:31:25 +00:00
Szabolcs Nagy cf6c44c38c cheri: Update the static tls requirement of the libc
Larger requirement because pointers are bigger.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 3715670ec0 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-11-22 14:31:25 +00:00
Szabolcs Nagy 096943551e aarch64: morello: add D_PTR_RW
Writable version of D_PTR, required for updating GOT[1] and GOT[2].
2022-11-22 14:31:25 +00:00
Szabolcs Nagy b9af312764 aarch64: morello: 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-11-22 14:31:25 +00:00
Szabolcs Nagy d94c03efc5 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.

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.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 24071d2e2f aarch64: morello: add lazy binding entry code 2022-11-22 14:31:25 +00:00
Szabolcs Nagy d0cc3969d4 cheri: elf: 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-11-22 14:31:25 +00:00
Szabolcs Nagy 681ddc91e1 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-11-22 14:31:25 +00:00
Szabolcs Nagy 647e35b6ab cheri: elf: Use elfptr_t for function symbol fixup
Propagate capabilities during lazy binding and IFUNC fixup in dlsym.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 046ce0eb11 cheri: elf: Prepare support for dynamic relocation processing
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.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 82f650eec8 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 025e8cb8d9 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-11-22 14:31:25 +00:00
Szabolcs Nagy 10247e0d2f 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-11-22 14:31:25 +00:00
Szabolcs Nagy c14096c2d3 aarch64: elf: avoid loading incompatible binaries
Prevent lp64 ld.so loading purecap binaries.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy e252e5f082 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-11-22 14:31:25 +00:00
Szabolcs Nagy 81c2de89c6 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-11-22 14:31:25 +00:00
Szabolcs Nagy 0b5f254b4d cheri: elf: Setup per module RX and RW capabilities
_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.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 0946809134 cheri: elf: change l_entry to be elfptr_t
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.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy b2b6a773fe aarch64: morello: add purecap 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.

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).
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 42a7a4f7b8 aarch64: morello: rtld: define DL_RO_DYN_SECTION
The dynamic section cannot be relocated to hold pointers in place.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 41965d796f 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-11-22 14:31:25 +00:00
Szabolcs Nagy 3fb3ff7f38 aarch64: morello: disable the vpcs test
The asm code of the test is for lp64 ABI only.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 2f33e8ec62 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo adf9bd54e9 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-11-22 14:31:25 +00:00
Szabolcs Nagy 8b79bc92fa 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-11-22 14:31:25 +00:00
Szabolcs Nagy 3244a1fc19 cheri: malloc: align up without breaking capability in memalign 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 0f2a4c9573 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-11-22 14:31:25 +00:00
Szabolcs Nagy cd345f5c03 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-11-22 14:31:25 +00:00
Szabolcs Nagy c0ba8ad1fe 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-11-22 14:31:25 +00:00
Szabolcs Nagy cf95053a83 cheri: fix qsort for capabilities
On capability targets avoid copying pointers via unsigned long.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy bcc70e4b2b 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-11-22 14:31:25 +00:00
Szabolcs Nagy 1b8d019265 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-11-22 14:31:25 +00:00
Szabolcs Nagy 8f6565fa27 cheri: Fix capability permissions of PROT_NONE maps in test code 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 8e860da0db cheri: Fix capability permissions of PROT_NONE map in locarchive 2022-11-22 14:31:25 +00:00
Szabolcs Nagy cb78f7d9d3 cheri: nptl: Fix thread stack capability permissions 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 83cc56b97a aarch64: morello: nptl: fix thread pointer setup 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 1ffce991bd aarch64: morello: nptl: fix pthread types for 128 bit pointers 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 0400bcd764 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-11-22 14:31:25 +00:00
Szabolcs Nagy 5042604a1e cheri: nptl: fix thread ID types for capabilities 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 7cbc4d39fe cheri: Implement 128-bit atomics
Arm Morello requires 128-bit atomics.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy faee37cd4c cheri: elf: Use elfptr_t in _dl_protect_relro
Derive the start of the relro area from the RW capability of the dso.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 9bf00c58bc cheri: fix static linking TLS setup
Use the per module RW capability to access the TLS initimage.
The bounds are not restricted for now.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy a5750ba400 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) and
the pointers are derived from the RX pointer of the elf module.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 90c5142f77 cheri: Setup RX, RW capabilities for static linking
At least tls image access requires RX capability of the main link_map.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 055042833f cheri: 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-11-22 14:31:25 +00:00
Szabolcs Nagy f70a0f9a14 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-11-22 14:31:25 +00:00
Szabolcs Nagy 607b660f89 cheri: elf: elfptr_t l_map_start in link_map struct
Use a capability for the load segment start that covers all load
segments so pointers can be derived from it.

It should have RX permission and a separate capability used for
writable pointers.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 4960cacb70 cheri: Introduce elfptr_t int type that can hold pointers
Use elfptr_t when ElfW(Addr) represents a runtime pointer (may be
dereferenced or pointers may be derived from it).
2022-11-22 14:31:25 +00:00
Szabolcs Nagy b4e28743ec 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-11-22 14:31:25 +00:00
Szabolcs Nagy 7f6564cd80 cheri: fix static linking early allocation
Store mmap result to intptr_t instead of long.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 871fb8be01 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-11-22 14:31:25 +00:00
Szabolcs Nagy 0b888aef9a aarch64: morello: add purecap start code
Written in C so the self relocation code in crt1.o is easier to
maintain.

The purecap ELF entry is special: passes separate argc, argv, envp,
auxv in registers instead of on the stack.

For each module there will be separate RW and RX capabilities that
cover the writable and all load segments respectively. The relative
reloc processing code is prepared for such separate capabilities.

The static link detection (for self relocation) is not ideal, it
relies on relocations that don't work in PIC, so it is ifdefed out
for Scrt1.o. (Currently adrp of undefined weak symbol is not fixed
up by the linker to be 0 so we use movz to detect the presence of
__rela_dyn_start.)
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 60c96035ff 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 4b5b494ecc aarch64: morello: purecap crti.S and crtn.S
Purecap ABI versions of crti.S and crtn.S.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo c5a8ab5ffa 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-11-22 14:31:25 +00:00
Szabolcs Nagy 93efaa5bdc cheri: elf: use elfptr_t for auxv parsing 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 4b0cb26b3b cheri: elf: Adjust Elf64_auxv_t for capabilities
The Elf64_auxv_t needs to be adjusted for the new capability size.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 88e0b1d81b cheri: elf: Add new AT_* auxv type definitions
Follows the morello pure capability user ABI of linux.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 61de2a5e84 elf: add EF_AARCH64_CHERI_PURECAP 2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 56d37dff38 elf: add Arm Morello relocations to elf.h 2022-11-22 14:31:25 +00:00
Szabolcs Nagy d816620531 cheri: Fix pselect signal mask argument
The signal mask argument is passed as a struct with a pointer and size
in the linux syscall abi, but the types used in glibc were wrong for
CHERI due to an x32 specific hack.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 655faf81b2 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).

capability permissions are roughly emulated too.

TODO: kernel should do this
2022-11-22 14:31:25 +00:00
Szabolcs Nagy ded659bdea TODO(uapi): aarch64: morello: add HWCAP2_MORELLO
TODO: this is the value in the 5.18 kernel, will change later.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy fba741bfba TODO(uapi): aarch64: morello: use non-ifunc gettimeofday
TODO: Remove this once morello has vdso gettimeofday.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy a909a33a81 TODO(uapi): aarch64: morello: make brk always fail
TODO: drop this once linux brk always fails.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy b811a41c57 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-11-22 14:31:25 +00:00
Szabolcs Nagy 2b0a2bff60 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-11-22 14:31:25 +00:00
Szabolcs Nagy 868b753880 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-11-22 14:31:25 +00:00
Szabolcs Nagy 04d2fec011 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-11-22 14:31:25 +00:00
Szabolcs Nagy ea32619881 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 6642c41779 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-11-22 14:31:25 +00:00
Szabolcs Nagy 666bf6a0fa aarch64: fix VDSO setup to only apply to known ABIs
New syscall ABI requires different VDSO support code.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy e1a82e3984 TODO(api): cheri: fix syscall return type
TODO: this affects API (syscall return type is long)
so breaks portability and requires doc updates.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 2d432f9815 aarch64: morello: string: memcpy
from arm optimized-routines morello branch.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 8d8d807e96 aarch64: morello: string: memset
memset from arm optimized-routines morello branch.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 780a9a68ba aarch64: morello: string: dummy c memcmp 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 92800f675f aarch64: morello: string: dummy c memchr 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 1c3eed557e aarch64: morello: string: dummy c memrchr 2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo 20829a45c1 aarch64: morello: purecap rawmemchr
Modified rawmemchr to support Arm Morello Capabilities.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 479ccba5b1 aarch64: morello: string: dummy c strchrnul 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 1e3d999b59 aarch64: morello: string: dummy c strlen 2022-11-22 14:31:25 +00:00
Szabolcs Nagy f0170f034e aarch64: morello: string: dummy c strnlen 2022-11-22 14:31:25 +00:00
Szabolcs Nagy ae42378808 aarch64: morello: string: dummy c strcpy and stpcpy 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 595e1c3b2e aarch64: morello: string: dummy c strcmp 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 0e0b1ae9d1 aarch64: morello: string: dummy c strncmp 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 4ec714ea87 aarch64: morello: string: dummy c strchr 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 3ad99c9112 aarch64: morello: string: dummy c strrchr 2022-11-22 14:31:25 +00:00
Szabolcs Nagy f750e14d55 aarch64: morello: string: dummy c strspn
avoids out of bound access of the generic implementation.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 69711df0c6 aarch64: morello: string: dummy c strcspn
avoids out of bounds access of the generic implementation.
2022-11-22 14:31:25 +00:00
Carlos Eduardo Seo c7f259679a aarch64: morello: update sysdep.h for purecap ABI
Add macro definitions for purecap ABI in sysdep.h.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy c75b4885df 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-11-22 14:31:25 +00:00
Carlos Eduardo Seo 039f2bdd89 cheri: __LP64__ is not defined for purecap ABI
There is no ideal ABI macro, so we assume __CHERI_PURE_CAPABILITY__
implies 64 bit long, 64 bit address and 128 bit pointer.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy e5b22d23d1 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-11-22 14:31:25 +00:00
Szabolcs Nagy 58759a422f aarch64: morello: use separate c++-types.data
The c++ mangling ABI for intptr_t and pthread_t are different on
morello.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy aef25bb30d aarch64: morello: use separate localplt data for morello
There is no longer PLT reference to matherr in libm.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 3f6b5d8644 aarch64: morello: Add separate lp64 and morello linux abilists
The base symbol version is 2.36.
2022-11-22 14:31:26 +00:00
Szabolcs Nagy 695bf0b81e aarch64: morello: Add purecap abi-variants on linux 2022-11-22 14:31:25 +00:00
Szabolcs Nagy 76bf2cf7a5 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-11-22 14:31:25 +00:00
Szabolcs Nagy e5dd73fc82 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-11-22 14:31:25 +00:00
Szabolcs Nagy 7381b20495 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-11-22 14:31:25 +00:00
Szabolcs Nagy 341b7670c8 aarch64: Use fewer ifdefs in bits/fcntl.h
This simplifies adding the Morello purecap abi target.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 78c03c7974 aarch64: cleanup MOVL definition in sysdep.h
PTR_REG is for ILP32, there is no point using it under __LP64__.
2022-11-22 14:31:25 +00:00
Szabolcs Nagy 8d04c0e9e9 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-11-22 14:31:25 +00:00
Szabolcs Nagy ad946943ce 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-11-22 14:31:25 +00:00
Szabolcs Nagy fe37bbda29 Fix stdlib/test-dlclose-exit-race to not hang
Use the standard wrapper that kills the test after a timeout.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 7ae55dc0aa Fix resource/bug-ulimit1 test
ulimit is a variadic function and the second argument must have type
long (or unsigned long).
2022-11-22 14:24:26 +00:00
Szabolcs Nagy d4a845daaf Fix elf/tst-dlmopen-twice to support enough link namespaces
The test dlmopens 10 namespaces recursively, which requires a glibc
tunable setting, otherwise it may run out of static TLS.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 69ecb7b4a3 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-11-22 14:24:26 +00:00
Szabolcs Nagy 2a287534c1 Fix malloc/tst-scratch_buffer OOB access
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-11-22 14:24:26 +00:00
Szabolcs Nagy 65c576e7e5 Fix off-by-one OOB read in elf/tst-tls20
The int mods[nmods] array on the stack was overread by one.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 44d649d3c4 Fix off-by-one OOB write 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-11-22 14:24:26 +00:00
Szabolcs Nagy 4054cc2093 Use uintptr_t in string/tester for pointer alignment
The code assumed unsigned long can represent pointers.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 1e5c704ec7 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-11-22 14:24:26 +00:00
Szabolcs Nagy eee747d8cc elf: Fix alloca size in _dl_debug_vdprintf
The alloca size did not consider the optional width parameter for
padding which could cause buffer underflow. The width is currently used
e.g. by _dl_map_object_from_fd which passes 2 * sizeof(void *) which
can be larger than the alloca buffer size on targets where
sizeof(void *) >= 2 * sizeof(unsigned long).

Even if large width is not used on existing targets it is better to fix
the formatting code to avoid surprises.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 8491c1adc9 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 hence it uses unsigned long for the alignment offset.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 5ba5d609c1 malloc: Use uintptr_t in alloc_buffer
The values represnt pointers and not sizes. The members of struct
alloc_buffer are already uintptr_t.
2022-11-22 14:24:26 +00:00
Carlos Eduardo Seo 17034ac2bf malloc: Use uintptr_t for pointer alignment
Avoid integer casts that assume unsigned long can represent pointers.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 13de83e5cf Use uintptr_t in fts for pointer alignment
The code assumed unsigned long can represent pointers.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 6349c03d42 Fix invalid pointer dereference in wcpcpy_chk
The src pointer is const and points to a different object, so accessing
dest via src is invalid.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy aecfbacba2 Fix invalid pointer dereference in wcscpy_chk
The src pointer is const and points to a different object, so accessing
dest via src is invalid.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy c505926c31 aarch64: Fix the 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-11-22 14:24:26 +00:00
Szabolcs Nagy b8020168b5 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-11-22 14:24:26 +00:00
Szabolcs Nagy 26be8f8a56 scripts: Use bool in tunables initializer
The initializer for a tunable_t set the bool initialized flag to NULL.
This causes a build failure when pointer to bool conversion warns.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 1fb0a36902 Fix OOB read in stdlib thousand grouping parsing [BZ #29727]
__correctly_grouped_prefixmb only worked with thousands_len == 1,
otherwise it read past the end of cp or thousands.

This affects scanf formats like %'d, %'f and the internal but
exposed __strto{l,ul,f,d,..}_internal with grouping flag set
and an LC_NUMERIC locale where thousands_len > 1.

Avoid OOB access by considering thousands_len when initializing cp.
This fixes bug 29727.

Found by the morello port with strict bounds checking where

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

crashed using a locale with thousands_len==3.
2022-11-22 14:24:26 +00:00
Szabolcs Nagy 5aa16bb318 math: Fix asin and acos invalid exception with old gcc
This works around a gcc issue where it const folded inf/inf into nan,
preventing the invalid exception to be signalled.

(x-x)/(x-x) is more robust against optimizations and works for all
out of bounds values including x==nan.

The gcc issue https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95115
should be fixed on release branches starting from gcc-10, but it is
better to change the code in case glibc is built with older gcc.
2022-11-22 14:24:26 +00:00
Vladislav Khmelevsky 2ba9801d9f elf: Fix rtld-audit trampoline for aarch64
This patch fixes two problems with audit:

  1. The DL_OFFSET_RV_VPCS offset was mixed up with DL_OFFSET_RG_VPCS,
     resulting in x2 register value nulling in RG structure.

  2. We need to preserve the x8 register before function call, but
     don't have to save it's new value and restore it before return.

Anyway the final restore was using OFFSET_RV instead of OFFSET_RG value
which is wrong (althoug doesn't affect anything).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit eb4181e9f4)
2022-11-22 10:45:11 -03:00
Florian Weimer 0f90d6204d Linux: Support __IPC_64 in sysvctl *ctl command arguments (bug 29771)
Old applications pass __IPC_64 as part of the command argument because
old glibc did not check for unknown commands, and passed through the
arguments directly to the kernel, without adding __IPC_64.
Applications need to continue doing that for old glibc compatibility,
so this commit enables this approach in current glibc.

For msgctl and shmctl, if no translation is required, make
direct system calls, as we did before the time64 changes.  If
translation is required, mask __IPC_64 from the command argument.

For semctl, the union-in-vararg argument handling means that
translation is needed on all architectures.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 22a46dee24)
2022-11-11 18:45:04 +01:00
Paul Eggert 70410f2286 mktime: improve heuristic for ca-1986 Indiana DST
This patch syncs mktime.c from Gnulib, fixing a
problem reported by Mark Krenz <https://bugs.gnu.org/48085>,
and it should fix BZ#29035 too.
* time/mktime.c (__mktime_internal): Be more generous about
accepting arguments with the wrong value of tm_isdst, by falling
back to a one-hour DST difference if we find no nearby DST that is
unusual.  This fixes a problem where "1986-04-28 00:00 EDT" was
rejected when TZ="America/Indianapolis" because the nearest DST
timestamp occurred in 1970, a temporal distance too great for the
old heuristic.  This also also narrows the search a bit, which
is a minor performance win.

(cherry picked from commit 83859e1115)
2022-11-08 22:46:32 -05:00
Sergei Trofimovich 36cc06341a Makerules: fix MAKEFLAGS assignment for upcoming make-4.4 [BZ# 29564]
make-4.4 will add long flags to MAKEFLAGS variable:

    * WARNING: Backward-incompatibility!
      Previously only simple (one-letter) options were added to the MAKEFLAGS
      variable that was visible while parsing makefiles.  Now, all options
      are available in MAKEFLAGS.

This causes locale builds to fail when long options are used:

    $ make --shuffle
    ...
    make  -C localedata install-locales
    make: invalid shuffle mode: '1662724426r'

The change fixes it by passing eash option via whitespace and dashes.
That way option is appended to both single-word form and whitespace
separated form.

While at it fixed --silent mode detection in $(MAKEFLAGS) by filtering
out --long-options. Otherwise options like --shuffle flag enable silent
mode unintentionally. $(silent-make) variable consolidates the checks.

Resolves: BZ# 29564

CC: Paul Smith <psmith@gnu.org>
CC: Siddhesh Poyarekar <siddhesh@gotplt.org>
Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 2d7ed98add)
2022-11-08 22:46:32 -05:00
caiyinyu 2fce85f67c LoongArch: Fix ABI related macros in elf.h to keep consistent with binutils[1].
[1]:
https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=c4a7e6b56218e1d5a858682186b542e2eae01a4a;hp=0d94a8735055432029237612a6eb9165db1ec9dd
[2]:
Reference: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version
2022-11-03 21:07:41 +08:00
Aurelien Jarno dd4131c832 linux: Fix fstatat on MIPSn64 (BZ #29730)
Commit 6e8a0aac2f ("time: Fix overflow itimer tests on 32-bit
systems") changed in_time_t_range to assume a 32-bit time_t. This broke
fstatat on MIPSn64 that was using it with a 64-bit time_t due to
difference between stat and stat64. This commit fix that by adding a
MIPSn64 specific version, which bypasses the EOVERFLOW tests.

Resolves: BZ #29730

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 7457b7eef8)
2022-11-02 16:41:56 +01:00
Xi Ruoyao 4c6a78adda longlong.h: update from GCC for LoongArch clz/ctz support
Update longlong.h to GCC r13-3269.  Keep our local change (prefer https
for gnu.org URL).
2022-10-28 15:06:38 +08:00
Adhemerval Zanella a1dc0be03c elf: Reinstate on DL_DEBUG_BINDINGS _dl_lookup_symbol_x
The prelink removal done by 6628c742b2 wrongly removed the debug
support.

Checked on x86_64-linux-gnu.

(cherry picked from commit 891a7958a2)
2022-10-26 10:03:00 -03:00
Adhemerval Zanella 7b7dfbb0cb linux: Fix generic struct_stat for 64 bit time (BZ# 29657)
The generic Linux struct_stat misses the conditionals to use
bits/struct_stat_time64_helper.h in the __USE_TIME_BITS64 for
architecture that uses __TIMESIZE == 32 (currently csky and nios2).

Since newer ports should not support 32 bit time_t, the generic
implementation should be used as default.

For arm, hppa, and sh a copy of default struct_stat is added,
while for csky and nios a new one based on generic is used, along
with conditionals to use bits/struct_stat_time64_helper.h.

The default struct_stat is also replaced with the generic one.

Checked on aarch64-linux-gnu and arm-linux-gnueabihf.

(cherry picked from commit 7a6ca82f80)
2022-10-25 16:13:11 -03:00
Aurelien Jarno 9273b2d0e9 Avoid undefined behaviour in ibm128 implementation of llroundl (BZ #29488)
Detecting an overflow edge case depended on signed overflow of a long
long. Replace the additions and the overflow checks by
__builtin_add_overflow().

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
(cherry picked from commit 2b5478569e)
2022-10-24 20:57:57 +02:00
Michael Hudson-Doyle b357157361 Fix BZ #29463 in the ibm128 implementation of y1l too
Avoid moving code across SET_RESTORE_ROUNDL in order to fix
[BZ #29463].

Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
(cherry picked from commit b6e37b7805)
2022-10-24 20:56:41 +02:00
Florian Weimer 19535f3b57 elf: Do not completely clear reused namespace in dlmopen (bug 29600)
The data in the _ns_debug member must be preserved, otherwise
_dl_debug_initialize enters an infinite loop.  To be conservative,
only clear the libc_map member for now, to fix bug 29528.

Fixes commit d0e357ff45
("elf: Call __libc_early_init for reused namespaces (bug 29528)"),
by reverting most of it.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 2c42257314)
2022-10-14 11:03:31 +02:00
Florian Weimer 908454129d nss: Use shared prefix in IPv4 address in tst-reload1
Otherwise, sorting based on the longest-matching prefix in
getaddrinfo can reorder the addresses in ways the test does not
expect, depending on the IPv4 address of the host.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c02e29a0ba)
2022-10-13 14:28:28 +02:00
Florian Weimer 2681d38caf nss: Fix tst-nss-files-hosts-long on single-stack hosts (bug 24816)
getent implicitly passes AI_ADDRCONFIG to getaddrinfo by default.
Use --no-addrconfig to suppress that, so that both IPv4 and IPv6
lookups succeed even if the address family is not supported by the
host.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit c75d20b5b2)
2022-10-13 14:28:25 +02:00
Florian Weimer 700d3281f9 nss: Implement --no-addrconfig option for getent
The ahosts, ahostsv4, ahostsv6 commands unconditionally pass
AI_ADDRCONFIG to getaddrinfo, which is not always desired.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit a623f13adf)
2022-10-13 14:27:02 +02:00
Michael Hudson-Doyle 3e27919274 Ensure calculations happen with desired rounding mode in y1lf128
math/test-float128-y1 fails on x86_64 and ppc64el with gcc 12 and -O3,
because code inside a block guarded by SET_RESTORE_ROUNDL is being moved
after the rounding mode has been restored. Use math_force_eval to
prevent this (and insert some math_opt_barrier calls to prevent code
from being moved before the rounding mode is set).

Fixes #29463

Reviewed-By: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
(cherry picked from commit 2b274fd8c9)
2022-10-09 13:05:19 +02:00
Siddhesh Poyarekar 2bd815d834 nscd: Drop local address tuple variable [BZ #29607]
When a request needs to be resent (e.g. due to insufficient buffer
space), the references to subsequent tuples in the local variable are
stale and should not be used.  This used to work by accident before, but
since 1d495912a it no longer does.  Instead of trying to reset it, just
let gethostbyname4_r write into TUMPBUF6 for us, thus maintaining a
consistent state at all times.  This is now consistent with what is done
in gaih_inet for getaddrinfo.

Resolves: BZ #29607
Reported-by: Holger Hoffstätte <holger@applied-asynchrony.com>
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 6e33e5c4b7)
2022-10-04 18:43:50 -04:00
Aurelien Jarno 2d8ef784bd x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations
The AVX2 strrchr and wcsrchr implementation uses the 'blsmsk'
instruction which belongs to the BMI1 CPU feature and the 'shrx'
instruction, which belongs to the BMI2 CPU feature.

Fixes: df7e295d18 ("x86: Optimize {str|wcs}rchr-avx2")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit 7e8283170c)
2022-10-03 23:47:50 +02:00
Aurelien Jarno 923c3f3c37 x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation
The AVX2 memrchr implementation uses the 'shlxl' instruction, which
belongs to the BMI2 CPU feature and uses the 'lzcnt' instruction, which
belongs to the LZCNT CPU feature.

Fixes: af5306a735 ("x86: Optimize memrchr-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit 3c0c78afab)
2022-10-03 23:47:50 +02:00
Aurelien Jarno d9196d4f3f x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations
The AVX2 memchr, rawmemchr and wmemchr implementations use the 'bzhi'
and 'sarx' instructions, which belongs to the BMI2 CPU feature.

Fixes: acfd088a19 ("x86: Optimize memchr-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit e3e7fab7fe)
2022-10-03 23:47:50 +02:00
Aurelien Jarno d8bf4388df x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations
The AVX2 wcs(n)cmp implementations use the 'bzhi' instruction, which
belongs to the BMI2 CPU feature.

NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
as BSF if the CPU doesn't support TZCNT, and produces the same result
for non-zero input.

Partially fixes: b77b06e0e2 ("x86: Optimize strcmp-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit f31a5a884e)
2022-10-03 23:47:49 +02:00
Aurelien Jarno 29c577e0f5 x86-64: Require BMI2 for AVX2 strncmp implementation
The AVX2 strncmp implementations uses the 'bzhi' instruction, which
belongs to the BMI2 CPU feature.

NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
as BSF if the CPU doesn't support TZCNT, and produces the same result
for non-zero input.

Partially fixes: b77b06e0e2 ("x86: Optimize strcmp-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit fc7de1d9b9)
2022-10-03 23:47:49 +02:00
Aurelien Jarno 7afbd1e56a x86-64: Require BMI2 for AVX2 strcmp implementation
The AVX2 strcmp implementation uses the 'bzhi' instruction, which
belongs to the BMI2 CPU feature.

NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
as BSF if the CPU doesn't support TZCNT, and produces the same result
for non-zero input.

Partially fixes: b77b06e0e2 ("x86: Optimize strcmp-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit 4d64c64457)
2022-10-03 23:47:49 +02:00
Aurelien Jarno 46479e5d10 x86-64: Require BMI2 for AVX2 str(n)casecmp implementations
The AVX2 str(n)casecmp implementations use the 'bzhi' instruction, which
belongs to the BMI2 CPU feature.

NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
as BSF if the CPU doesn't support TZCNT, and produces the same result
for non-zero input.

Partially fixes: b77b06e0e2 ("x86: Optimize strcmp-avx2.S")
Partially resolves: BZ #29611

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit 10f79d3670)
2022-10-03 23:47:49 +02:00
Aurelien Jarno 18bec23cbb x86: include BMI1 and BMI2 in x86-64-v3 level
The "System V Application Binary Interface AMD64 Architecture Processor
Supplement" mandates the BMI1 and BMI2 CPU features for the x86-64-v3
level.

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit b80f16adbd)
2022-10-03 23:47:49 +02:00
John David Anglin cdc496eb55 hppa: undef __ASSUME_SET_ROBUST_LIST
QEMU does not support support set_robust_list. Thus, we need
to enable detection of set_robust_list system call.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2022-10-01 20:09:10 +00:00
John David Anglin d1d8379bff hppa: Fix initialization of dp register [BZ 29635]
After upgrading glibc to Debian 2.35-1, gdb faulted on
startup and dropped core in a function call in the main
application.  This was caused by not initializing the
global dp register for the main application early enough.

Restore the code to initialize dp in _dl_start_user.
It was removed when code was added to initialize dp in
elf_machine_runtime_setup.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2022-10-01 19:53:30 +00:00
Adhemerval Zanella 76e05613ee stdlib: Fix __getrandom_nocancel type and arc4random usage (BZ #29638)
Using an unsigned type prevents the fallback to be used if kernel
does not support getrandom syscall.

Checked on x86_64-linux-gnu.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 13db9ee2cb)
2022-09-30 15:32:51 -03:00
Jörg Sonnenberger 227c903587 get_nscd_addresses: Fix subscript typos [BZ #29605]
Fix the subscript on air->family, which was accidentally set to COUNT
when it should have remained as I.

Resolves: BZ #29605

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c9226c03da)
2022-09-28 12:48:47 -04:00
Adhemerval Zanella 2628500f5d m68k: Enforce 4-byte alignment on internal locks (BZ #29537)
A new internal definition, __LIBC_LOCK_ALIGNMENT, is used to force
the 4-byte alignment only for m68k, other architecture keep the
natural alignment of the type used internally (and hppa does not
require 16-byte alignment for kernel-assisted CAS).

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit aeb4d2e981)
2022-09-21 12:01:47 -03:00
Florian Weimer 52c037f357 gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
It's possible that inode numbers are outside the 32-bit range.
The existing code only handles the in-libc case correctly, and
still uses the legacy interfaces when building iconv.

Suggested-by: Helge Deller <deller@gmx.de>
(cherry picked from commit f97905f246)
2022-09-21 12:12:52 +02:00
Florian Weimer da5f134f6d elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937)
The implementation in _dl_close_worker requires that the first
element of l_initfini is always this very map (“We are always the
zeroth entry, and since we don't include ourselves in the
dependency analysis start at 1.”).  Rather than fixing that
assumption, this commit adds an implementation of the force_first
argument to the new dependency sorting algorithm.  This also means
that the directly dlopen'ed shared object is always initialized last,
which is the least surprising behavior in the presence of cycles.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 1df71d32fe)
2022-09-20 11:06:05 +02:00
Florian Weimer d1241cf001 elf: Rename _dl_sort_maps parameter from skip to force_first
The new implementation will not be able to skip an arbitrary number
of objects.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit dbb75513f5)
2022-09-20 11:04:44 +02:00
Florian Weimer 7a3f8c8a7a scripts/dso-ordering-test.py: Generate program run-time dependencies
The main program needs to depend on all shared objects, even objects
that have link-time dependencies among shared objects.  Filtering
out shared objects that already have an link-time dependencies is not
necessary here; make will do this automatically.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 183d997372)
2022-09-20 11:04:44 +02:00
Javier Pello 4b95b6e8bb elf: Fix hwcaps string size overestimation
Commit dad90d5282 added glibc-hwcaps
support for LD_LIBRARY_PATH and, for this, it adjusted the total
string size required in _dl_important_hwcaps. However, in doing so
it inadvertently altered the calculation of the size required for
the power set strings, as the computation of the power set string
size depended on the first value assigned to the total variable,
which is later shifted, resulting in overallocation of string
space. Fix this now by using a different variable to hold the
string size required for glibc-hwcaps.

Signed-off-by: Javier Pello <devel@otheo.eu>
(cherry picked from commit a23820f605)
2022-09-15 14:44:49 +02:00
Florian Weimer df51334828 elf: Run tst-audit-tlsdesc, tst-audit-tlsdesc-dlopen everywhere
The test is valid for all TLS models, but we want to make a reasonable
effort to test the GNU2 model specifically.  For example, aarch64
defaults to GNU2, but does not have -mtls-dialect=gnu2, and the test
was not run there.

Suggested-by: Martin Coufal <mcoufal@redhat.com>
(cherry picked from commit dd2315a866)

Fixes early backport commit 924e4f3eaa
("elf: Call __libc_early_init for reused namespaces (bug 29528)");
it had a wrong conflict resolution.
2022-09-13 19:57:43 +02:00
Florian Weimer 5d885617ce NEWS: Note bug 12154 and bug 29305 as fixed 2022-09-13 13:22:27 +02:00
Florian Weimer a7fa604f30 resolv: Fix building tst-resolv-invalid-cname for earlier C standards
This fixes this compiler error:

tst-resolv-invalid-cname.c: In function ‘test_mode_to_string’:
tst-resolv-invalid-cname.c:164:10: error: label at end of compound statement
     case test_mode_num:
          ^~~~~~~~~~~~~

Fixes commit 9caf782276
("resolv: Add new tst-resolv-invalid-cname").

(cherry picked from commit d09aa4a172)
2022-09-13 12:56:24 +02:00
Florian Weimer c5cdb39c20 nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces
Introduce struct alloc_buffer to this function, and use it and
struct ns_rr_cursor in gaih_getanswer_slice.  Adjust gaih_getanswer
and gaih_getanswer_noaaaa accordingly.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 1d495912a7)
2022-09-13 12:56:24 +02:00
Florian Weimer e2ec6a8db3 resolv: Add new tst-resolv-invalid-cname
This test checks resolution through CNAME chains that do not contain
host names (bug 12154).

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 9caf782276)
2022-09-13 12:56:24 +02:00
Florian Weimer 7a236dc44a nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154)
If the name is not a host name, skip adding it to the result, instead
of reporting query failure.  This fixes bug 12154 for getaddrinfo.

This commit still keeps the old parsing code, and only adjusts when
a host name is copied.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 32b599ac8c)
2022-09-13 12:56:24 +02:00
Florian Weimer 78c8ef21fa nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305)
Allocate the pointer arrays only at the end, when their sizes
are known.  This addresses bug 29305.

Skip over invalid names instead of failing lookups.  This partially
fixes bug 12154 (for gethostbyname, fixing getaddrinfo requires
different changes).

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit d101d836e7)
2022-09-13 12:56:24 +02:00
Florian Weimer 5165080fec nss_dns: Remove remnants of IPv6 address mapping
res_use_inet6 always returns false since commit 3f8b44be0a
("resolv: Remove support for RES_USE_INET6 and the inet6 option").

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit a7fc30b522)
2022-09-13 12:56:24 +02:00
Florian Weimer 77f523c473 nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr
The simplification takes advantage of the split from getanswer_r.
It fixes various aliases issues, and optimizes NSS buffer usage.
The new DNS packet parsing helpers are used, too.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit e32547d661)
2022-09-13 12:56:24 +02:00
Florian Weimer b714ab7e3c nss_dns: Split getanswer_ptr from getanswer_r
And expand the use of name_ok and qtype in getanswer_ptr (the
former also in getanswer_r).

After further cleanups, not much code will be shared between the
two functions.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 0dcc43e998)
2022-09-13 12:56:24 +02:00
Florian Weimer f0e9657067 resolv: Add DNS packet parsing helpers geared towards wire format
The public parser functions around the ns_rr record type produce
textual domain names, but usually, this is not what we need while
parsing DNS packets within glibc.  This commit adds two new helper
functions, __ns_rr_cursor_init and __ns_rr_cursor_next, for writing
packet parsers, and struct ns_rr_cursor, struct ns_rr_wire as
supporting types.

In theory, it is possible to avoid copying the owner name
into the rname field in __ns_rr_cursor_next, but this would need
more functions that work on compressed names.

Eventually, __res_context_send could be enhanced to preserve the
result of the packet parsing that is necessary for matching the
incoming UDP packets, so that this works does not have to be done
twice.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 857c890d9b)
2022-09-13 12:56:24 +02:00
Florian Weimer adb69f8ffe resolv: Add internal __ns_name_length_uncompressed function
This function is useful for checking that the question name is
uncompressed (as it should be).

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 78b1a4f0e4)
2022-09-13 12:56:24 +02:00
Florian Weimer 20ec40a51d resolv: Add the __ns_samebinaryname function
During packet parsing, only the binary name is available.  If the name
equality check is performed before conversion to text, we can sometimes
skip the last step.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 394085a34d)
2022-09-13 12:56:24 +02:00
Florian Weimer 3c9b4004e2 resolv: Add internal __res_binary_hnok function
During package parsing, only the binary representation is available,
and it is convenient to check that directly for conformance with host
name requirements.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c79327bf00)
2022-09-13 12:56:24 +02:00
Florian Weimer bffc33e90e resolv: Add tst-resolv-aliases
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 87aa98aa80)
2022-09-13 12:56:24 +02:00
Florian Weimer 9d7eebde8f resolv: Add tst-resolv-byaddr for testing reverse lookup
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 0b99828d54)
2022-09-13 12:56:24 +02:00
Fabian Vogt c399271c10 nscd: Fix netlink cache invalidation if epoll is used [BZ #29415]
Processes cache network interface information such as whether IPv4 or IPv6
are enabled. This is only checked again if the "netlink timestamp" provided
by nscd changed, which is triggered by netlink socket activity.

However, in the epoll handler for the netlink socket, it was missed to
assign the new timestamp to the nscd database. The handler for plain poll
did that properly, copy that over.

This bug caused that e.g. processes which started before network
configuration got unusuable addresses from getaddrinfo, like IPv6 only even
though only IPv4 is available:
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1041

It's a bit hard to reproduce, so I verified this by checking the timestamp
on calls to __check_pf manually. Without this patch it's stuck at 1, now
it's increasing on network changes as expected.

Signed-off-by: Fabian Vogt <fvogt@suse.de>
(cherry picked from commit 02ca25fef2)
2022-09-06 18:34:18 +02:00
Siddhesh Poyarekar b46412fb17 Add NEWS entry for CVE-2022-39046
(cherry picked from commit 76fe56020e)
2022-09-06 09:36:54 -04:00
Adhemerval Zanella 645d94808a syslog: Remove extra whitespace between timestamp and message (BZ#29544)
The rfc3164 clear states that a single space character must follow
the timestamp field.

Checked on x86_64-linux-gnu.
2022-09-05 09:50:03 -03:00
Adhemerval Zanella b3736d1a3c elf: Restore how vDSO dependency is printed with LD_TRACE_LOADED_OBJECTS (BZ #29539)
The d7703d3176 changed how vDSO like
dependencies are printed, instead of just the name and address it
follows other libraries mode and prints 'name => path'.

Unfortunately, this broke some ldd consumer that uses the output to
filter out the program's dependencies.  For instance CMake
bundleutilities module [1], where GetPrequirite uses the regex to filter
out 'name => path' [2].

This patch restore the previous way to print just the name and the
mapping address.

Checked on x86_64-linux-gnu.

[1] https://github.com/Kitware/CMake/tree/master/Tests/BundleUtilities
[2] https://github.com/Kitware/CMake/blob/master/Modules/GetPrerequisites.cmake#L733

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 1e903124ce)
2022-08-31 09:10:53 -03:00
Raphael Moreira Zinsly 3c791f2031 Apply asm redirections in wchar.h before first use
Similar to d0fa09a770, but for wchar.h.  Fixes [BZ #27087] by applying
all long double related asm redirections before using functions in
bits/wchar2.h.
Moves the function declarations from wcsmbs/bits/wchar2.h to a new file
wcsmbs/bits/wchar2-decl.h that will be included first in wcsmbs/wchar.h.

Tested with build-many-glibcs.py.
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

(cherry picked from commit c7509d49c4)
2022-08-31 09:03:41 +02:00
Florian Weimer 924e4f3eaa elf: Call __libc_early_init for reused namespaces (bug 29528)
libc_map is never reset to NULL, neither during dlclose nor on a
dlopen call which reuses the namespace structure.  As a result, if a
namespace is reused, its libc is not initialized properly.  The most
visible result is a crash in the <ctype.h> functions.

To prevent similar bugs on namespace reuse from surfacing,
unconditionally initialize the chosen namespace to zero using memset.

(cherry picked from commit d0e357ff45)
2022-08-30 16:31:03 +02:00
Adhemerval Zanella b0e7888d1f syslog: Fix large messages (BZ#29536)
The a583b6add4 change did not handle large messages that
would require a heap allocation correctly, where the message itself
is not take in consideration.

This patch fixes it and extend the tst-syslog to check for large
messages as well.

Checked on x86_64-linux-gnu.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 52a5be0df4)
2022-08-30 09:03:14 -03:00
Florian Weimer 3bd3c612e9 Linux: Fix enum fsconfig_command detection in <sys/mount.h>
The #ifdef FSOPEN_CLOEXEC check did not work because the macro
was always defined in this header prior to the check, so that
the <linux/mount.h> contents did not matter.

Fixes commit 774058d729
("linux: Fix sys/mount.h usage with kernel headers").

(cherry picked from commit 2955ef4b7c)
2022-08-24 10:01:29 -03:00
Adhemerval Zanella bb1e8b0ca9 linux: Fix sys/mount.h usage with kernel headers
Now that kernel exports linux/mount.h and includes it on linux/fs.h,
its definitions might clash with glibc exports sys/mount.h.  To avoid
the need to rearrange the Linux header to be always after glibc one,
the glibc sys/mount.h is changed to:

  1. Undefine the macros also used as enum constants.  This covers prior
     inclusion of <linux/mount.h> (for instance MS_RDONLY).

  2. Include <linux/mount.h> based on the usual __has_include check
     (needs to use __has_include ("linux/mount.h") to paper over GCC
     bugs.

  3. Define enum fsconfig_command only if FSOPEN_CLOEXEC is not defined.
     (FSOPEN_CLOEXEC should be a very close proxy.)

  4. Define struct mount_attr if MOUNT_ATTR_SIZE_VER0 is not defined.
     (Added in the same commit on the Linux side.)

This patch also adds some tests to check if including linux/fs.h and
linux/mount.h after and before sys/mount.h does work.

Checked on x86_64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 774058d729)
2022-08-24 10:01:29 -03:00
Adhemerval Zanella d48813227b linux: Use compile_c_snippet to check linux/mount.h availability
Checked on x86_64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit e1226cdc6b)
2022-08-24 10:01:29 -03:00
Adhemerval Zanella 4dad97e2a2 linux: Mimic kernel defition for BLOCK_SIZE
To avoid possible warnings if the kernel header is included before
sys/mount.h.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit c68b6044bc)
2022-08-24 10:01:29 -03:00
Adhemerval Zanella 1cc5513114 linux: Use compile_c_snippet to check linux/pidfd.h availability
Instead of tying to a specific kernel version.

Checked on x86_64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 1542019b69)
2022-08-24 10:01:29 -03:00
Adhemerval Zanella 0062e7dd1c glibcextract.py: Add compile_c_snippet
It might be used on tests to check if a snippet build with the provided
compiler and flags.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 841afa116e)
2022-08-24 10:01:27 -03:00
Arjun Shankar 5c62874f42 NEWS: Add entry for bug 28846 2022-08-22 18:21:49 +02:00
Arjun Shankar d13a7a6f10 socket: Check lengths before advancing pointer in CMSG_NXTHDR
The inline and library functions that the CMSG_NXTHDR macro may expand
to increment the pointer to the header before checking the stride of
the increment against available space.  Since C only allows incrementing
pointers to one past the end of an array, the increment must be done
after a length check.  This commit fixes that and includes a regression
test for CMSG_FIRSTHDR and CMSG_NXTHDR.

The Linux, Hurd, and generic headers are all changed.

Tested on Linux on armv7hl, i686, x86_64, aarch64, ppc64le, and s390x.

[BZ #28846]

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 9c443ac455)
2022-08-22 16:32:13 +02:00
Florian Weimer 8b139cd4f1 alpha: Fix generic brk system call emulation in __brk_call (bug 29490)
The kernel special-cases the zero argument for alpha brk, and we can
use that to restore the generic Linux error handling behavior.

Fixes commit b57ab258c1 ("Linux:
Introduce __brk_call for invoking the brk system call").

(cherry picked from commit e7ad26ee3c)
2022-08-22 11:11:02 +02:00
Florian Weimer e982657073 Linux: Terminate subprocess on late failure in tst-pidfd (bug 29485)
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit f82e05ebb2)
2022-08-16 07:30:25 +02:00
Noah Goldstein 302bc33bc5 elf: Replace strcpy call with memcpy [BZ #29454]
GCC normally does this optimization for us in
strlen_pass::handle_builtin_strcpy but only for optimized
build. To avoid needing to include strcpy.S in the rtld build to
support the debug build, just do the optimization by hand.

(cherry picked from commit 483cfe1a6a)
2022-08-11 22:11:14 +08:00
Joseph Myers ac47d8f6cf Update syscall lists for Linux 5.19
Linux 5.19 has no new syscalls, but enables memfd_secret in the uapi
headers for RISC-V.  Update the version number in syscall-names.list
to reflect that it is still current for 5.19 and regenerate the
arch-syscall.h headers with build-many-glibcs.py update-syscalls.

Tested with build-many-glibcs.py.

(cherry picked from commit fccadcdf5b)
2022-08-05 23:46:44 +02: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
355 changed files with 13935 additions and 1643 deletions
+17 -1
View File
@@ -43,6 +43,22 @@ else
$(error objdir must be defined by the build-directory Makefile)
endif
# Did we request 'make -s' run? "yes" or "no".
# Starting from make-4.4 MAKEFLAGS now contains long
# options like '--shuffle'. To detect presence of 's'
# we pick first word with short options. Long options
# are guaranteed to come after whitespace. We use '-'
# prefix to always have a word before long options
# even if no short options were passed.
# Typical MAKEFLAGS values to watch for:
# "rs --shuffle=42" (silent)
# " --shuffle" (not silent)
ifeq ($(findstring s, $(firstword -$(MAKEFLAGS))),)
silent-make := no
else
silent-make := yes
endif
# Root of the sysdeps tree.
sysdep_dir := $(..)sysdeps
export sysdep_dir := $(sysdep_dir)
@@ -917,7 +933,7 @@ endif
# umpteen zillion filenames along with it (we use `...' instead)
# but we don't want this echoing done when the user has said
# he doesn't want to see commands echoed by using -s.
ifneq "$(findstring s,$(MAKEFLAGS))" "" # if -s
ifeq ($(silent-make),yes) # if -s
+cmdecho := echo >/dev/null
else # not -s
+cmdecho := echo
+3 -3
View File
@@ -794,7 +794,7 @@ endif
# Maximize efficiency by minimizing the number of rules.
.SUFFIXES: # Clear the suffix list. We don't use suffix rules.
# Don't define any builtin rules.
MAKEFLAGS := $(MAKEFLAGS)r
MAKEFLAGS := $(MAKEFLAGS) -r
# Generic rule for making directories.
%/:
@@ -811,7 +811,7 @@ MAKEFLAGS := $(MAKEFLAGS)r
.PRECIOUS: $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
# Use the verbose option of ar and tar when not running silently.
ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s
ifeq ($(silent-make),no) # if not -s
verbose := v
else # -s
verbose :=
@@ -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
+43
View File
@@ -5,6 +5,49 @@ 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
Major new features:
* The getent tool now supports the --no-addrconfig option. The output of
getent with --no-addrconfig may contain addresses of families not
configured on the current host i.e. as-if you had not passed
AI_ADDRCONFIG to getaddrinfo calls.
Security related changes:
CVE-2022-39046: When the syslog function is passed a crafted input
string larger than 1024 bytes, it reads uninitialized memory from the
heap and prints it to the target log file, potentially revealing a
portion of the contents of the heap.
The following bugs are resolved with this release:
[12154] Do not fail DNS resolution for CNAMEs which are not host names
[24816] Fix tst-nss-files-hosts-long on single-stack hosts
[28846] CMSG_NXTHDR may trigger -Wstrict-overflow warning
[29305] Conserve NSS buffer space during DNS packet parsing
[29415] nscd: Fix netlink cache invalidation if epoll is used
[28937] New DSO dependency sorter does not put new map first if in a cycle
[29446] _dlopen now ignores dl_caller argument in static mode
[29485] Linux: Terminate subprocess on late failure in tst-pidfd
[29490] alpha: New __brk_call implementation is broken
[29463] math/test-float128-y1 fails on x86_64
[29488] test-ibm128-llround fails on ppc64el when built with gcc-12 and -O2
or higher
[29528] elf: Call __libc_early_init for reused namespaces
[29537] libc: [2.34 regression]: Alignment issue on m68k when using
[29539] libc: LD_TRACE_LOADED_OBJECTS changed how vDSO library are
[29583] Use 64-bit interfaces in gconv_parseconfdir
[29600] Do not completely clear reused namespace in dlmopen
[29607] nscd repeatably crashes calling __strlen_avx2 when hosts cache is
enabled
[29638] libc: stdlib: arc4random fallback is never used
[29657] libc: Incorrect struct stat for 64-bit time on linux/generic
platforms
[29730] broken y2038 support in fstatat on MIPS N64
[29771] Restore IPC_64 support in sysvipc *ctl functions
Version 2.36
Major new features:
+33 -7
View File
@@ -245,6 +245,12 @@ struct cmsghdr
+ CMSG_ALIGN (sizeof (struct cmsghdr)))
#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
/* Given a length, return the additional padding necessary such that
len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */
#define __CMSG_PADDING(len) ((sizeof (size_t) \
- ((len) & (sizeof (size_t) - 1))) \
& (sizeof (size_t) - 1))
extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
struct cmsghdr *__cmsg) __THROW;
#ifdef __USE_EXTERN_INLINES
@@ -254,18 +260,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
_EXTERN_INLINE struct cmsghdr *
__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
{
/* We may safely assume that __cmsg lies between __mhdr->msg_control and
__mhdr->msg_controllen because the user is required to obtain the first
cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs
via CMSG_NXTHDR, setting lengths along the way. However, we don't yet
trust the value of __cmsg->cmsg_len and therefore do not use it in any
pointer arithmetic until we check its value. */
unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control;
unsigned char * __cmsg_ptr = (unsigned char *) __cmsg;
size_t __size_needed = sizeof (struct cmsghdr)
+ __CMSG_PADDING (__cmsg->cmsg_len);
/* The current header is malformed, too small to be a full header. */
if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
/* The kernel header does this so there may be a reason. */
return (struct cmsghdr *) 0;
/* There isn't enough space between __cmsg and the end of the buffer to
hold the current cmsg *and* the next one. */
if (((size_t)
(__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr)
< __size_needed)
|| ((size_t)
(__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr
- __size_needed)
< __cmsg->cmsg_len))
return (struct cmsghdr *) 0;
/* Now, we trust cmsg_len and can use it to find the next header. */
__cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
+ CMSG_ALIGN (__cmsg->cmsg_len));
if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
+ __mhdr->msg_controllen)
|| ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
> ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
/* No more entries. */
return (struct cmsghdr *) 0;
return __cmsg;
}
#endif /* Use `extern inline'. */
+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 *
+32 -16
View File
@@ -374,6 +374,8 @@ tests += \
tst-align \
tst-align2 \
tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@@ -408,6 +410,7 @@ tests += \
tst-dlmopen4 \
tst-dlmopen-dlerror \
tst-dlmopen-gethostbyname \
tst-dlmopen-twice \
tst-dlopenfail \
tst-dlopenfail-2 \
tst-dlopenrpath \
@@ -765,6 +768,8 @@ modules-names += \
tst-alignmod3 \
tst-array2dep \
tst-array5dep \
tst-audit-tlsdesc-mod1 \
tst-audit-tlsdesc-mod2 \
tst-audit11mod1 \
tst-audit11mod2 \
tst-audit12mod1 \
@@ -798,6 +803,7 @@ modules-names += \
tst-auditmanymod7 \
tst-auditmanymod8 \
tst-auditmanymod9 \
tst-auditmod-tlsdesc \
tst-auditmod1 \
tst-auditmod9a \
tst-auditmod9b \
@@ -834,6 +840,8 @@ modules-names += \
tst-dlmopen1mod \
tst-dlmopen-dlerror-mod \
tst-dlmopen-gethostbyname-mod \
tst-dlmopen-twice-mod1 \
tst-dlmopen-twice-mod2 \
tst-dlopenfaillinkmod \
tst-dlopenfailmod1 \
tst-dlopenfailmod2 \
@@ -990,23 +998,8 @@ modules-names += tst-gnu2-tls1mod
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
tst-gnu2-tls1mod.so-no-z-defs = yes
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
endif # $(have-mtls-dialect-gnu2)
tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen
modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc
$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so \
$(shared-thread-library)
CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so
$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
endif
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
tests += tst-protected1a tst-protected1b
@@ -2967,3 +2960,26 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
&& grep -q '^status: 127$$' $@; \
$(evaluate-test)
$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so \
$(shared-thread-library)
ifeq (yes,$(have-mtls-dialect-gnu2))
# The test is valid for all TLS types, but we want to exercise GNU2
# TLS if possible.
CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
endif
$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so
$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
tst-dlmopen-twice-ENV = GLIBC_TUNABLES=glibc.rtld.nns=10
$(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \
$(objpfx)tst-dlmopen-twice-mod2.so
+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);
+3 -2
View File
@@ -509,8 +509,9 @@ _dl_load_cache_lookup (const char *name)
we are accessing. Therefore we must make the copy of the
mapping data without using malloc. */
char *temp;
temp = alloca (strlen (best) + 1);
strcpy (temp, best);
size_t best_len = strlen (best) + 1;
temp = alloca (best_len);
memcpy (temp, best, best_len);
return __strdup (temp);
}
+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
+5 -3
View File
@@ -193,7 +193,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
/* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
and a "/" suffix once stored in the result. */
hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1;
size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
size_t hwcaps_sz = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
+ hwcaps_counts.total_length);
/* Count the number of bits set in the masked value. */
@@ -229,11 +229,12 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
assert (m == cnt);
/* Determine the total size of all strings together. */
size_t total;
if (cnt == 1)
total += temp[0].len + 1;
total = temp[0].len + 1;
else
{
total += temp[0].len + temp[cnt - 1].len + 2;
total = temp[0].len + temp[cnt - 1].len + 2;
if (cnt > 2)
{
total <<= 1;
@@ -255,6 +256,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
/* This is the overall result, including both glibc-hwcaps
subdirectories and the legacy hwcaps subdirectories using the
power set construction. */
total += hwcaps_sz;
struct r_strlenpair *overall_result
= malloc (*sz * sizeof (*result) + total);
if (overall_result == NULL)
+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 ("\
+17
View File
@@ -854,6 +854,23 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
if (__glibc_unlikely (current_value.m->l_used == 0))
current_value.m->l_used = 1;
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS))
{
const char *reference_name = undef_map->l_name;
_dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
DSO_FILENAME (reference_name),
undef_map->l_ns,
DSO_FILENAME (current_value.m->l_name),
current_value.m->l_ns,
protected ? "protected" : "normal", undef_name);
if (version)
_dl_debug_printf_c (" [%s]\n", version->name);
else
_dl_debug_printf_c ("\n");
}
*ref = current_value.s;
return LOOKUP_VALUE (current_value.m);
}
+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)
+1
View File
@@ -850,6 +850,7 @@ no more namespaces available for dlmopen()"));
++GL(dl_nns);
}
GL(dl_ns)[nsid].libc_map = NULL;
_dl_debug_update (nsid)->r_state = RT_CONSISTENT;
}
/* Never allow loading a DSO in a namespace which is empty. Such
+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;
+29 -15
View File
@@ -27,12 +27,12 @@
If FOR_FINI is true, this is called for finishing an object. */
static void
_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
unsigned int skip, bool for_fini)
bool force_first, bool for_fini)
{
/* Allows caller to do the common optimization of skipping the first map,
usually the main binary. */
maps += skip;
nmaps -= skip;
maps += force_first;
nmaps -= force_first;
/* A list of one element need not be sorted. */
if (nmaps <= 1)
@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
static void
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
unsigned int skip __attribute__ ((unused)), bool for_fini)
bool force_first, bool for_fini)
{
struct link_map *first_map = maps[0];
for (int i = nmaps - 1; i >= 0; i--)
maps[i]->l_visited = 0;
@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
Adjusting the order so that maps[0] is last traversed naturally avoids
this problem.
Further, the old "optimization" of skipping the main object at maps[0]
from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
no longer valid, since traversing along object dependency-links
may "find" the main object even when it is not included in the initial
order (e.g. a dlopen()'ed shared object can have circular dependencies
linked back to itself). In such a case, traversing N-1 objects will
create a N-object result, and raise problems.
To summarize, just passing in the full list, and iterating from back
to front makes things much more straightforward. */
@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
}
memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
/* Skipping the first object at maps[0] is not valid in general,
since traversing along object dependency-links may "find" that
first object even when it is not included in the initial order
(e.g., a dlopen'ed shared object can have circular dependencies
linked back to itself). In such a case, traversing N-1 objects
will create a N-object result, and raise problems. Instead,
force the object back into first place after sorting. This naive
approach may introduce further dependency ordering violations
compared to rotating the cycle until the first map is again in
the first position, but as there is a cycle, at least one
violation is already present. */
if (force_first && maps[0] != first_map)
{
int i;
for (i = 0; maps[i] != first_map; ++i)
;
assert (i < nmaps);
memmove (&maps[1], maps, i * sizeof (maps[0]));
maps[0] = first_map;
}
}
void
@@ -286,7 +300,7 @@ _dl_sort_maps_init (void)
void
_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
unsigned int skip, bool for_fini)
bool force_first, bool for_fini)
{
/* It can be tempting to use a static function pointer to store and call
the current selected sorting algorithm routine, but experimentation
@@ -296,9 +310,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
input cases. A simple if-case with direct function calls appears to
be the fastest. */
if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
_dl_sort_maps_original (maps, nmaps, skip, for_fini);
_dl_sort_maps_original (maps, nmaps, force_first, for_fini);
else
_dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
_dl_sort_maps_dfs (maps, nmaps, force_first, for_fini);
}
#endif /* HAVE_TUNABLES. */
+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
View File
@@ -64,3 +64,10 @@ output: b>a>{}<a<b
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
# Test that even in the presence of dependency loops involving dlopen'ed
# object, that object is initialized last (and not unloaded prematurely).
# Final destructor order is indeterminate due to the cycle.
tst-bz28937: {+a;+b;-b;+c;%c};a->a1;a->a2;a2->a;b->b1;c->a1;c=>a1
output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1
+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) \
+50 -2
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 */
@@ -4085,8 +4130,11 @@ enum
#define R_NDS32_TLS_DESC 119
/* LoongArch ELF Flags */
#define EF_LARCH_ABI 0x07
#define EF_LARCH_ABI_LP64D 0x03
#define EF_LARCH_ABI_MODIFIER_MASK 0x07
#define EF_LARCH_ABI_SOFT_FLOAT 0x01
#define EF_LARCH_ABI_SINGLE_FLOAT 0x02
#define EF_LARCH_ABI_DOUBLE_FLOAT 0x03
#define EF_LARCH_OBJABI_V1 0x40
/* LoongArch specific dynamic relocations */
#define R_LARCH_NONE 0
+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");
+1 -1
View File
@@ -52,7 +52,7 @@ $(objpfx)rtld-libc.a: $(foreach dir,$(rtld-subdirs),\
mv -f $@T $@
# Use the verbose option of ar and tar when not running silently.
ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s
ifeq ($(silent-make),no) # if not -s
verbose := v
else # -s
verbose :=
+76 -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);
@@ -2122,6 +2176,12 @@ dl_main (const ElfW(Phdr) *phdr,
if (l->l_faked)
/* The library was not found. */
_dl_printf ("\t%s => not found\n", l->l_libname->name);
else if (strcmp (l->l_libname->name, l->l_name) == 0)
/* Print vDSO like libraries without duplicate name. Some
consumers depend of this format. */
_dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name,
(int) sizeof l->l_map_start * 2,
(size_t) l->l_map_start);
else
_dl_printf ("\t%s => %s (0x%0*Zx)\n",
DSO_FILENAME (l->l_libname->name),
@@ -2194,7 +2254,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)
{
+37
View File
@@ -0,0 +1,37 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
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 <stdio.h>
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlmopen-twice-mod1.so loaded");
fflush (stdout);
}
static void __attribute__ ((destructor))
fini (void)
{
puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
fflush (stdout);
}
/* Large allocation. The second module does not have this, so it
should load libc at a different address. */
char large_allocate[16 * 1024 * 1024];
+50
View File
@@ -0,0 +1,50 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
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 <ctype.h>
#include <stdio.h>
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlmopen-twice-mod2.so loaded");
fflush (stdout);
}
static void __attribute__ ((destructor))
fini (void)
{
puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
fflush (stdout);
}
int
run_check (void)
{
puts ("info: about to call isalpha");
fflush (stdout);
volatile char ch = 'a';
if (!isalpha (ch))
{
puts ("error: isalpha ('a') is not true");
fflush (stdout);
return 1;
}
return 0;
}
+54
View File
@@ -0,0 +1,54 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
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 <stdio.h>
#include <support/check.h>
#include <support/xdlfcn.h>
/* Run the test multiple times, to check finding a new namespace while
another namespace is already in use. This used to trigger bug 29600. */
static void
recurse (int depth)
{
if (depth == 0)
return;
printf ("info: running at depth %d\n", depth);
void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so",
RTLD_NOW);
xdlclose (handle);
handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
int (*run_check) (void) = xdlsym (handle, "run_check");
TEST_COMPARE (run_check (), 0);
recurse (depth - 1);
xdlclose (handle);
}
static int
do_test (void)
{
/* First run the test without nesting. */
recurse (1);
/* Then with nesting. The constant needs to be less than the
glibc.rtld.nns tunable (which is between 1 and DL_NNS). */
recurse (10);
return 0;
}
#include <support/test-driver.c>
+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);
}
+8 -8
View File
@@ -29,14 +29,14 @@
# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr)
# define asprintf __asprintf
# define opendir __opendir
# define readdir __readdir
# define readdir64 __readdir64
# define closedir __closedir
# define mempcpy __mempcpy
# define struct_stat struct __stat64_t64
# define lstat __lstat64_time64
# define struct_stat64 struct __stat64_t64
# define lstat64 __lstat64_time64
# define feof_unlocked __feof_unlocked
#else
# define struct_stat struct stat
# define struct_stat64 struct stat64
#endif
/* Name of the file containing the module information in the directories
@@ -148,8 +148,8 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
DIR *confdir = opendir (buf);
if (confdir != NULL)
{
struct dirent *ent;
while ((ent = readdir (confdir)) != NULL)
struct dirent64 *ent;
while ((ent = readdir64 (confdir)) != NULL)
{
if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
continue;
@@ -161,12 +161,12 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
{
char *conf;
struct_stat st;
struct_stat64 st;
if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
continue;
if (ent->d_type != DT_UNKNOWN
|| (lstat (conf, &st) != -1 && S_ISREG (st.st_mode)))
|| (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
found |= read_conf_file (conf, dir, dir_len);
free (conf);
+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,
+5 -5
View File
@@ -248,9 +248,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 +282,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. */
{
+106
View File
@@ -55,6 +55,12 @@ int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
int __ns_name_unpack (const unsigned char *, const unsigned char *,
const unsigned char *, unsigned char *, size_t) __THROW;
/* Like ns_samename, but for uncompressed binary names. Return true
if the two arguments compare are equal as case-insensitive domain
names. */
_Bool __ns_samebinaryname (const unsigned char *, const unsigned char *)
attribute_hidden;
#define ns_msg_getflag(handle, flag) \
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
@@ -89,5 +95,105 @@ libc_hidden_proto (__ns_name_unpack)
extern __typeof (ns_samename) __libc_ns_samename;
libc_hidden_proto (__libc_ns_samename)
/* Packet parser helper functions. */
/* Verify that P points to an uncompressed domain name in wire format.
On success, return the length of the encoded name, including the
terminating null byte. On failure, return -1 and set errno. EOM
must point one past the last byte in the packet. */
int __ns_name_length_uncompressed (const unsigned char *p,
const unsigned char *eom) attribute_hidden;
/* Iterator over the resource records in a DNS packet. */
struct ns_rr_cursor
{
/* These members are not changed after initialization. */
const unsigned char *begin; /* First byte of packet. */
const unsigned char *end; /* One past the last byte of the packet. */
const unsigned char *first_rr; /* First resource record (or packet end). */
/* Advanced towards the end while reading the packet. */
const unsigned char *current;
};
/* Returns the RCODE field from the DNS header. */
static inline int
ns_rr_cursor_rcode (const struct ns_rr_cursor *c)
{
return c->begin[3] & 0x0f; /* Lower 4 bits at offset 3. */
}
/* Returns the length of the answer section according to the DNS header. */
static inline int
ns_rr_cursor_ancount (const struct ns_rr_cursor *c)
{
return c->begin[6] * 256 + c->begin[7]; /* 16 bits at offset 6. */
}
/* Returns the length of the authority (name server) section according
to the DNS header. */
static inline int
ns_rr_cursor_nscount (const struct ns_rr_cursor *c)
{
return c->begin[8] * 256 + c->begin[9]; /* 16 bits at offset 8. */
}
/* Returns the length of the additional data section according to the
DNS header. */
static inline int
ns_rr_cursor_adcount (const struct ns_rr_cursor *c)
{
return c->begin[10] * 256 + c->begin[11]; /* 16 bits at offset 10. */
}
/* Returns a pointer to the uncompressed question name in wire
format. */
static inline const unsigned char *
ns_rr_cursor_qname (const struct ns_rr_cursor *c)
{
return c->begin + 12; /* QNAME starts right after the header. */
}
/* Returns the question type of the first and only question. */
static inline const int
ns_rr_cursor_qtype (const struct ns_rr_cursor *c)
{
/* 16 bits 4 bytes back from the first RR header start. */
return c->first_rr[-4] * 256 + c->first_rr[-3];
}
/* Returns the clss of the first and only question (usally C_IN). */
static inline const int
ns_rr_cursor_qclass (const struct ns_rr_cursor *c)
{
/* 16 bits 2 bytes back from the first RR header start. */
return c->first_rr[-2] * 256 + c->first_rr[-1];
}
/* Initializes *C to cover the packet [BUF, BUF+LEN). Returns false
if LEN is less than sizeof (*HD), if the packet does not contain a
full (uncompressed) question, or if the question count is not 1. */
_Bool __ns_rr_cursor_init (struct ns_rr_cursor *c,
const unsigned char *buf, size_t len)
attribute_hidden;
/* Like ns_rr, but the record owner name is not decoded into text format. */
struct ns_rr_wire
{
unsigned char rname[NS_MAXCDNAME]; /* Owner name of the record. */
uint16_t rtype; /* Resource record type (T_*). */
uint16_t rclass; /* Resource record class (C_*). */
uint32_t ttl; /* Time-to-live field. */
const unsigned char *rdata; /* Start of resource record data. */
uint16_t rdlength; /* Length of the data at rdata, in bytes. */
};
/* Attempts to parse the record at C into *RR. On success, return
true, and C is advanced past the record, and RR->rdata points to
the record data. On failure, errno is set to EMSGSIZE, and false
is returned. */
_Bool __ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
attribute_hidden;
# endif /* !_ISOMAC */
#endif
+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)) \
+1
View File
@@ -0,0 +1 @@
#include <wcsmbs/bits/wchar2-decl.h>
+4
View File
@@ -43,7 +43,11 @@
remember, if any of these versions change, the libc.so major version
number must change too (so avoid it)! */
#ifdef __CHERI_PURE_CAPABILITY__
#define _GNU_OBSTACK_INTERFACE_VERSION 2 /* vs malloc/obstack.c */
#else
#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */
#endif
#define _GNU_REGEX_INTERFACE_VERSION 1 /* vs posix/regex.c */
#define _GNU_GLOB_INTERFACE_VERSION 2 /* vs posix/glob.c */
#define _GNU_GETOPT_INTERFACE_VERSION 2 /* vs posix/getopt.c and
+15 -2
View File
@@ -133,7 +133,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 +252,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];
+3
View File
@@ -70,5 +70,8 @@ libc_hidden_proto (__libc_res_nameinquery)
extern __typeof (__res_queriesmatch) __libc_res_queriesmatch;
libc_hidden_proto (__libc_res_queriesmatch)
/* Variant of res_hnok which operates on binary (but uncompressed) names. */
bool __res_binary_hnok (const unsigned char *dn) attribute_hidden;
# endif /* _RESOLV_H_ && !_ISOMAC */
#endif
+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. */
+33 -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,21 @@ ptmalloc_init (void)
tcache_key_initialize ();
#endif
#ifdef __CHERI_PURE_CAPABILITY__
__always_fail_morecore = true;
if (TUNABLE_GET_FULL (glibc, mem, cap_narrowing, int32_t, NULL) == 0)
cap_narrowing_enabled = false;
else
{
cap_narrowing_enabled = true;
# ifdef __CAP_MMAP_THRESHOLD
/* Default mmap threshold to avoid heap fragmentation. */
do_set_mmap_threshold (__CAP_MMAP_THRESHOLD);
# endif
}
#endif
cap_init ();
#ifdef USE_MTAG
if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
{
@@ -444,7 +464,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 +538,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 +546,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 +571,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 +699,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 +790,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;
+365 -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, void *narrow_oldp)
{
if (cap_narrowing_enabled)
{
if (p == NULL)
__libc_cap_put_back (oldp, narrow_oldp);
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, void *narrow_oldp)
{
if (cap_narrowing_enabled)
{
if (p == NULL)
__libc_cap_put_back (oldp, narrow_oldp);
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,10 @@ __libc_free (void *mem)
if (mem == 0) /* free(0) has no effect */
return;
void *orig_mem = mem;
mem = cap_widen (mem);
cap_drop (orig_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 +3653,9 @@ __libc_realloc (void *oldmem, size_t bytes)
if (oldmem == 0)
return __libc_malloc (bytes);
void *orig_oldmem = oldmem;
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 +3682,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 +3691,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 (orig_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 +3718,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, orig_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, orig_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, orig_oldmem))
return newmem;
size_t sz = memsize (oldp);
memcpy (newmem, oldmem, sz < bytes ? sz : bytes);
(void) tag_region (chunk2mem (oldp), 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, orig_oldmem);
}
__libc_lock_lock (ar_ptr->mutex);
@@ -3497,14 +3792,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, orig_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 +3813,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 +3843,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 +3860,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 +3880,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 +3896,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 +3922,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 +3948,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 +4021,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 +4032,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 +4068,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 +4091,7 @@ __libc_calloc (size_t n, size_t elem_size)
}
}
mem = cap_narrow (mem, sz);
return mem;
}
#endif /* IS_IN (libc) */
@@ -4978,8 +5317,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 +5473,7 @@ __malloc_usable_size (void *m)
{
if (m == NULL)
return 0;
m = cap_widen (m);
return musable (m);
}
#endif
@@ -5681,6 +6020,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);
+7 -28
View File
@@ -28,7 +28,11 @@
/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
incremented whenever callers compiled using an old obstack.h can no
longer properly call the functions in this obstack.c. */
#ifdef __CHERI_PURE_CAPABILITY__
#define OBSTACK_INTERFACE_VERSION 2
#else
#define OBSTACK_INTERFACE_VERSION 1
#endif
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself, and the installed library
@@ -53,6 +57,7 @@
# include <stdint.h>
# include <string.h>
/* Determine default alignment. */
union fooround
@@ -75,15 +80,6 @@ enum
DEFAULT_ROUNDING = sizeof (union fooround)
};
/* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work;
in such a case, redefine COPYING_UNIT to 'long' (if that works)
or 'char' as a last resort. */
# ifndef COPYING_UNIT
# define COPYING_UNIT int
# endif
/* The functions allocating more room by calling 'obstack_chunk_alloc'
jump to the handler pointed to by 'obstack_alloc_failed_handler'.
This can be set to a user defined function which should either
@@ -269,25 +265,8 @@ _obstack_newchunk (struct obstack *h, int length)
object_base =
__PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
/* Move the existing object to the new chunk.
Word at a time is fast and is safe if the object
is sufficiently aligned. */
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
{
for (i = obj_size / sizeof (COPYING_UNIT) - 1;
i >= 0; i--)
((COPYING_UNIT *) object_base)[i]
= ((COPYING_UNIT *) h->object_base)[i];
/* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
but that can cross a page boundary on a machine
which does not do strict alignment for COPYING_UNITS. */
already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
}
else
already = 0;
/* Copy remaining bytes one by one. */
for (i = already; i < obj_size; i++)
object_base[i] = h->object_base[i];
/* Move the existing object to the new chunk. */
memcpy (object_base, h->object_base, obj_size);
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
+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>
+19
View File
@@ -83,6 +83,25 @@ do_test (void)
free (p);
/* Check as above with larger size increase. */
p = malloc (34);
if (p == NULL)
FAIL_EXIT1 ("malloc (34) failed.");
memset (p, 'a', 34);
p = realloc (p, 80000);
if (p == NULL)
FAIL_EXIT1 ("realloc (p, 80000) failed.");
c = p;
ok = 1;
for (i = 0; i < 34; i++)
{
if (c[i] != 'a')
ok = 0;
}
if (ok == 0)
FAIL_EXIT1 ("first 34 bytes were not preserved");
free (p);
p = realloc (NULL, 100);
if (p == NULL)
FAIL_EXIT1 ("realloc (NULL, 100) failed.");
+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;
}
+37
View File
@@ -0,0 +1,37 @@
Morello glibc port
==================
Morello is a prototype security architecture, led by Arm, based on CHERI.
https://www.morello-project.org/
https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/
Toolchain components of the morello port are maintained in upstream branches.
The morello port is implemented as an ABI variant of the aarch64 port that is
also called the purecap ABI. Morello specific ABI documents are at:
https://github.com/ARM-software/abi-aa
https://git.morello-project.org/morello/kernel/linux/-/wikis/home
Areas with significant morello or CHERI specific changes outside the usual
target specific changes:
- Early start code including ELF entry and auxv,
- Dynamic linker and relocation processing,
- malloc with narrow capability support,
- printf %#p to pretty print capabilities.
Limitations of the morello port:
- Building requires --disable-werror.
- Profiling and --enable-profile are not supported (gprof, sprof, LD_PROFILE).
- LD_AUDIT is not supported (la_symbind, PLT hooks, require new API redesign).
- VDSO is not supported (depends on Linux work).
- static-pie is not supported (requires start code redesign).
- POSIX message queue async notify does not work (pointers passed via an fd).
- Process shared robust mutex does not work (pointers in shared memory).
- Purecap pldd only supports purecap ABI processes (not lp64).
- malloc bounds narrowing has large overhead (locks and hash table lookup).
- malloc bounds narrowing can break code expecting page granularity protection.
Use GLIBC_TUNABLES=glibc.mem.cap_narrowing=0 env var as a workaround.
- string functions are not optimized.
- Executable stack is not supported.
- Internal pointer protection and pointer mangling are disabled.
+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 */
+12 -8
View File
@@ -167,7 +167,7 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
_nl_C_locobj_ptr);
#define SYSLOG_HEADER(__pri, __timestamp, __msgoff, pid) \
"<%d>%s %n%s%s%.0d%s: ", \
"<%d>%s%n%s%s%.0d%s: ", \
__pri, __timestamp, __msgoff, \
LogTag == NULL ? __progname : LogTag, \
"[" + (pid == 0), pid, "]" + (pid == 0)
@@ -193,28 +193,32 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
mode_flags);
if (0 <= vl && vl < sizeof bufs - l)
{
buf = bufs;
bufsize = l + vl;
}
buf = bufs;
bufsize = l + vl;
va_end (apc);
}
if (buf == NULL)
{
buf = malloc (l * sizeof (char));
buf = malloc ((bufsize + 1) * sizeof (char));
if (buf != NULL)
{
/* Tell the cancellation handler to free this buffer. */
clarg.buf = buf;
if (has_ts)
__snprintf (bufs, sizeof bufs,
__snprintf (buf, l + 1,
SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
else
__snprintf (bufs, sizeof bufs,
__snprintf (buf, l + 1,
SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
va_list apc;
va_copy (apc, ap);
__vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
mode_flags);
va_end (apc);
}
else
{
+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)
+135 -22
View File
@@ -68,21 +68,19 @@ static const int priorities[] =
LOG_DEBUG
};
enum
{
ident_length = 64,
msg_length = 64
};
#define IDENT_LENGTH 64
#define MSG_LENGTH 1024
#define SYSLOG_MSG_BASE "syslog_message"
#define OPENLOG_IDENT "openlog_ident"
static char large_message[MSG_LENGTH];
struct msg_t
{
int priority;
int facility;
char ident[ident_length];
char msg[msg_length];
char ident[IDENT_LENGTH];
char msg[MSG_LENGTH];
pid_t pid;
};
@@ -147,6 +145,37 @@ check_syslog_message (const struct msg_t *msg, int msgnum, int options,
return true;
}
static void
send_syslog_large (int options)
{
int facility = LOG_USER;
int priority = LOG_INFO;
syslog (facility | priority, "%s %d %d", large_message, facility,
priority);
}
static void
send_vsyslog_large (int options)
{
int facility = LOG_USER;
int priority = LOG_INFO;
call_vsyslog (facility | priority, "%s %d %d", large_message, facility,
priority);
}
static bool
check_syslog_message_large (const struct msg_t *msg, int msgnum, int options,
pid_t pid)
{
TEST_COMPARE (msg->facility, LOG_USER);
TEST_COMPARE (msg->priority, LOG_INFO);
TEST_COMPARE_STRING (msg->msg, large_message);
return false;
}
static void
send_openlog (int options)
{
@@ -179,6 +208,17 @@ send_openlog (int options)
closelog ();
}
static void
send_openlog_large (int options)
{
/* Define a non-default IDENT and a not default facility. */
openlog (OPENLOG_IDENT, options, LOG_LOCAL0);
syslog (LOG_INFO, "%s %d %d", large_message, LOG_LOCAL0, LOG_INFO);
closelog ();
}
static bool
check_openlog_message (const struct msg_t *msg, int msgnum,
int options, pid_t pid)
@@ -189,7 +229,7 @@ check_openlog_message (const struct msg_t *msg, int msgnum,
int expected_priority = priorities[msgnum % array_length (priorities)];
TEST_COMPARE (msg->priority, expected_priority);
char expected_ident[ident_length];
char expected_ident[IDENT_LENGTH];
snprintf (expected_ident, sizeof (expected_ident), "%s%s%.0d%s:",
OPENLOG_IDENT,
options & LOG_PID ? "[" : "",
@@ -211,17 +251,43 @@ check_openlog_message (const struct msg_t *msg, int msgnum,
return true;
}
static bool
check_openlog_message_large (const struct msg_t *msg, int msgnum,
int options, pid_t pid)
{
char expected_ident[IDENT_LENGTH];
snprintf (expected_ident, sizeof (expected_ident), "%s%s%.0d%s:",
OPENLOG_IDENT,
options & LOG_PID ? "[" : "",
options & LOG_PID ? pid : 0,
options & LOG_PID ? "]" : "");
TEST_COMPARE_STRING (msg->ident, expected_ident);
TEST_COMPARE_STRING (msg->msg, large_message);
TEST_COMPARE (msg->priority, LOG_INFO);
TEST_COMPARE (msg->facility, LOG_LOCAL0);
return false;
}
static struct msg_t
parse_syslog_msg (const char *msg)
{
struct msg_t r = { .pid = -1 };
int number;
int wsb, wsa;
#define STRINPUT(size) XSTRINPUT(size)
#define XSTRINPUT(size) "%" # size "s"
/* The message in the form:
<179>Apr 8 14:51:19 tst-syslog: syslog message 176 3 */
int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d %32s %64s %*d %*d",
&number, r.ident, r.msg);
<179>Apr 8 14:51:19 tst-syslog: message 176 3 */
int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d%n %n" STRINPUT(IDENT_LENGTH)
" " STRINPUT(MSG_LENGTH) " %*d %*d",
&number, &wsb, &wsa, r.ident, r.msg);
TEST_COMPARE (n, 3);
/* It should only one space between timestamp and message. */
TEST_COMPARE (wsa - wsb, 1);
r.facility = number & LOG_FACMASK;
r.priority = number & LOG_PRIMASK;
@@ -246,7 +312,7 @@ parse_syslog_console (const char *msg)
/* The message in the form:
openlog_ident: syslog_message 128 0 */
int n = sscanf (msg, "%32s %64s %d %d",
int n = sscanf (msg, STRINPUT(IDENT_LENGTH) " " STRINPUT(MSG_LENGTH) " %d %d",
r.ident, r.msg, &facility, &priority);
TEST_COMPARE (n, 4);
@@ -281,7 +347,7 @@ check_syslog_udp (void (*syslog_send)(int), int options,
int msgnum = 0;
while (1)
{
char buf[512];
char buf[2048];
size_t l = xrecvfrom (server_udp, buf, sizeof (buf), 0,
(struct sockaddr *) &addr, &addrlen);
buf[l] = '\0';
@@ -325,7 +391,7 @@ check_syslog_tcp (void (*syslog_send)(int), int options,
int client_tcp = xaccept (server_tcp, NULL, NULL);
char buf[512], *rb = buf;
char buf[2048], *rb = buf;
size_t rbl = sizeof (buf);
size_t prl = 0; /* Track the size of the partial record. */
int msgnum = 0;
@@ -393,20 +459,34 @@ check_syslog_console_read (FILE *fp)
}
static void
check_syslog_console (void)
check_syslog_console_read_large (FILE *fp)
{
char buf[2048];
TEST_VERIFY (fgets (buf, sizeof (buf), fp) != NULL);
struct msg_t msg = parse_syslog_console (buf);
TEST_COMPARE_STRING (msg.ident, OPENLOG_IDENT ":");
TEST_COMPARE_STRING (msg.msg, large_message);
TEST_COMPARE (msg.priority, LOG_INFO);
TEST_COMPARE (msg.facility, LOG_LOCAL0);
}
static void
check_syslog_console (void (*syslog_send)(int),
void (*syslog_check)(FILE *fp))
{
xmkfifo (_PATH_CONSOLE, 0666);
pid_t sender_pid = xfork ();
if (sender_pid == 0)
{
send_openlog (LOG_CONS);
syslog_send (LOG_CONS);
_exit (0);
}
{
FILE *fp = xfopen (_PATH_CONSOLE, "r+");
check_syslog_console_read (fp);
syslog_check (fp);
xfclose (fp);
}
@@ -425,16 +505,28 @@ send_openlog_callback (void *clousure)
}
static void
check_syslog_perror (void)
send_openlog_callback_large (void *clousure)
{
int options = *(int *) clousure;
send_openlog_large (options);
}
static void
check_syslog_perror (bool large)
{
struct support_capture_subprocess result;
result = support_capture_subprocess (send_openlog_callback,
result = support_capture_subprocess (large
? send_openlog_callback_large
: send_openlog_callback,
&(int){LOG_PERROR});
FILE *mfp = fmemopen (result.err.buffer, result.err.length, "r");
if (mfp == NULL)
FAIL_EXIT1 ("fmemopen: %m");
check_syslog_console_read (mfp);
if (large)
check_syslog_console_read_large (mfp);
else
check_syslog_console_read (mfp);
xfclose (mfp);
support_capture_subprocess_check (&result, "tst-openlog-child", 0,
@@ -462,10 +554,31 @@ do_test (void)
check_syslog_tcp (send_openlog, LOG_PID, check_openlog_message);
/* Check the LOG_CONS option. */
check_syslog_console ();
check_syslog_console (send_openlog, check_syslog_console_read);
/* Check the LOG_PERROR option. */
check_syslog_perror ();
check_syslog_perror (false);
/* Similar tests as before, but with a large message to trigger the
syslog path that uses dynamically allocated memory. */
memset (large_message, 'a', sizeof large_message - 1);
large_message[sizeof large_message - 1] = '\0';
check_syslog_udp (send_syslog_large, 0, check_syslog_message_large);
check_syslog_tcp (send_syslog_large, 0, check_syslog_message_large);
check_syslog_udp (send_vsyslog_large, 0, check_syslog_message_large);
check_syslog_tcp (send_vsyslog_large, 0, check_syslog_message_large);
check_syslog_udp (send_openlog_large, 0, check_openlog_message_large);
check_syslog_tcp (send_openlog_large, 0, check_openlog_message_large);
check_syslog_udp (send_openlog_large, LOG_PID, check_openlog_message_large);
check_syslog_tcp (send_openlog_large, LOG_PID, check_openlog_message_large);
check_syslog_console (send_openlog_large, check_syslog_console_read_large);
check_syslog_perror (true);
return 0;
}
+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;
+2 -3
View File
@@ -110,11 +110,10 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
"gethostbyname4_r");
if (fct4 != NULL)
{
struct gaih_addrtuple atmem;
struct gaih_addrtuple *at;
while (1)
{
at = &atmem;
at = NULL;
rc6 = 0;
herrno = 0;
status[1] = DL_CALL_FCT (fct4, (key, &at,
@@ -137,7 +136,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
goto next_nip;
/* We found the data. Count the addresses and the size. */
for (const struct gaih_addrtuple *at2 = at = &atmem; at2 != NULL;
for (const struct gaih_addrtuple *at2 = at; at2 != NULL;
at2 = at2->next)
{
++naddrs;
+2 -1
View File
@@ -2284,7 +2284,8 @@ main_loop_epoll (int efd)
sizeof (buf))) != -1)
;
__bump_nl_timestamp ();
dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
= __bump_nl_timestamp ();
}
# endif
else
+10 -1
View File
@@ -58,6 +58,8 @@ static const struct argp_option args_options[] =
{
{ "service", 's', N_("CONFIG"), 0, N_("Service configuration to be used") },
{ "no-idn", 'i', NULL, 0, N_("disable IDN encoding") },
{ "no-addrconfig", 'A', NULL, 0,
N_("do not filter out unsupported IPv4/IPv6 addresses (with ahosts*)") },
{ NULL, 0, NULL, 0, NULL },
};
@@ -79,6 +81,9 @@ static struct argp argp =
/* Additional getaddrinfo flags for IDN encoding. */
static int idn_flags = AI_IDN | AI_CANONIDN;
/* Set to 0 by --no-addrconfig. */
static int addrconfig_flags = AI_ADDRCONFIG;
/* Print the version information. */
static void
print_version (FILE *stream, struct argp_state *state)
@@ -346,7 +351,7 @@ ahosts_keys_int (int af, int xflags, int number, char *key[])
struct addrinfo hint;
memset (&hint, '\0', sizeof (hint));
hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME
hint.ai_flags = (AI_V4MAPPED | addrconfig_flags | AI_CANONNAME
| idn_flags | xflags);
hint.ai_family = af;
@@ -905,6 +910,10 @@ parse_option (int key, char *arg, struct argp_state *state)
idn_flags = 0;
break;
case 'A':
addrconfig_flags = 0;
break;
default:
return ARGP_ERR_UNKNOWN;
}
+5 -4
View File
@@ -28,14 +28,15 @@ do_test (void)
{
int ret;
/* Run getent to fetch the IPv4 address for host test4.
This forces /etc/hosts to be parsed. */
ret = system("getent ahostsv4 test4");
/* Run getent to fetch the IPv4 address for host test4. This forces
/etc/hosts to be parsed. Use --no-addrconfig to return addresses
even in an IPv6-only environment. */
ret = system("getent --no-addrconfig ahostsv4 test4");
if (ret != 0)
FAIL_EXIT1("ahostsv4 failed");
/* Likewise for IPv6. */
ret = system("getent ahostsv6 test6");
ret = system("getent --no-addrconfig ahostsv6 test6");
if (ret != 0)
FAIL_EXIT1("ahostsv6 failed");
+4 -4
View File
@@ -43,12 +43,12 @@ static struct passwd pwd_table_1[] = {
static const char *hostaddr_5[] =
{
"ABCD", "abcd", "1234", NULL
"ABCd", "ABCD", "ABC4", NULL
};
static const char *hostaddr_15[] =
{
"4321", "ghij", NULL
"4321", "4322", NULL
};
static const char *hostaddr_25[] =
@@ -86,12 +86,12 @@ static const char *hostaddr_6[] =
static const char *hostaddr_16[] =
{
"7890", "a1b2", NULL
"7890", "7891", NULL
};
static const char *hostaddr_26[] =
{
"qwer", "tyui", NULL
"qwer", "qweR", NULL
};
static struct hostent host_table_2[] = {
+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;
+23
View File
@@ -40,12 +40,16 @@ routines := \
inet_pton \
ns_makecanon \
ns_name_compress \
ns_name_length_uncompressed \
ns_name_ntop \
ns_name_pack \
ns_name_pton \
ns_name_skip \
ns_name_uncompress \
ns_name_unpack \
ns_rr_cursor_init \
ns_rr_cursor_next \
ns_samebinaryname \
ns_samename \
nsap_addr \
nss_dns_functions \
@@ -89,9 +93,12 @@ tests += \
tst-ns_name_pton \
tst-res_hconf_reorder \
tst-res_hnok \
tst-resolv-aliases \
tst-resolv-basic \
tst-resolv-binary \
tst-resolv-byaddr \
tst-resolv-edns \
tst-resolv-invalid-cname \
tst-resolv-network \
tst-resolv-noaaaa \
tst-resolv-nondecimal \
@@ -104,6 +111,18 @@ tests += \
tests-internal += tst-resolv-txnid-collision
tests-static += tst-resolv-txnid-collision
# Likewise for __ns_samebinaryname.
tests-internal += tst-ns_samebinaryname
tests-static += tst-ns_samebinaryname
# Likewise for __ns_name_length_uncompressed.
tests-internal += tst-ns_name_length_uncompressed
tests-static += tst-ns_name_length_uncompressed
# Likewise for struct ns_rr_cursor and its functions.
tests-internal += tst-ns_rr_cursor
tests-static += tst-ns_rr_cursor
# These tests need libdl.
ifeq (yes,$(build-shared))
tests += \
@@ -258,8 +277,10 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
$(gen-locales) $(objpfx)tst-no-libidn2.so
$(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
@@ -267,6 +288,8 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
$(shared-thread-library)
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
$(shared-thread-library)
$(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \
$(shared-thread-library)
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
-3
View File
@@ -146,6 +146,3 @@ res_libc.c is home-brewn, although parts of it are taken from res_data.c.
res_hconf.c and res_hconf.h were contributed by David Mosberger, and
do not come from BIND.
The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are
leftovers from BIND 4.9.7.
-69
View File
@@ -1,69 +0,0 @@
/*
* ++Copyright++ 1985, 1988, 1993
* -
* Copyright (c) 1985, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#include <string.h>
#include <arpa/nameser.h>
static void
map_v4v6_address (const char *src, char *dst)
{
u_char *p = (u_char *) dst;
int i;
/* Move the IPv4 part to the right position. */
memcpy (dst + 12, src, INADDRSZ);
/* Mark this ipv6 addr as a mapped ipv4. */
for (i = 0; i < 10; i++)
*p++ = 0x00;
*p++ = 0xff;
*p = 0xff;
}
-84
View File
@@ -1,84 +0,0 @@
/*
* ++Copyright++ 1985, 1988, 1993
* -
* Copyright (c) 1985, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#include <arpa/nameser.h>
#include <sys/socket.h>
typedef union {
int32_t al;
char ac;
} align;
static int
map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
{
char **ap;
if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
return 0;
hp->h_addrtype = AF_INET6;
hp->h_length = IN6ADDRSZ;
for (ap = hp->h_addr_list; *ap; ap++)
{
int i = sizeof (align) - ((u_long) *bpp % sizeof (align));
if (*lenp < (i + IN6ADDRSZ))
/* Out of memory. */
return 1;
*bpp += i;
*lenp -= i;
map_v4v6_address (*ap, *bpp);
*ap = *bpp;
*bpp += IN6ADDRSZ;
*lenp -= IN6ADDRSZ;
}
return 0;
}
+72
View File
@@ -0,0 +1,72 @@
/* Skip over an uncompressed name in wire format.
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 <arpa/nameser.h>
#include <errno.h>
#include <stdbool.h>
int
__ns_name_length_uncompressed (const unsigned char *p,
const unsigned char *eom)
{
const unsigned char *start = p;
while (true)
{
if (p == eom)
{
/* Truncated packet: no room for label length. */
__set_errno (EMSGSIZE);
return -1;
}
unsigned char b = *p;
++p;
if (b == 0)
{
/* Root label. */
size_t length = p - start;
if (length > NS_MAXCDNAME)
{
/* Domain name too long. */
__set_errno (EMSGSIZE);
return -1;
}
return length;
}
if (b <= 63)
{
/* Regular label. */
if (b <= eom - p)
p += b;
else
{
/* Truncated packet: label incomplete. */
__set_errno (EMSGSIZE);
return -1;
}
}
else
{
/* Compression reference or corrupted label length. */
__set_errno (EMSGSIZE);
return -1;
}
}
}
+62
View File
@@ -0,0 +1,62 @@
/* Initialize a simple DNS packet parser.
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 <arpa/nameser.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
bool
__ns_rr_cursor_init (struct ns_rr_cursor *c,
const unsigned char *buf, size_t len)
{
c->begin = buf;
c->end = buf + len;
/* Check for header size and 16-bit question count value (it must be 1). */
if (len < 12 || buf[4] != 0 || buf[5] != 1)
{
__set_errno (EMSGSIZE);
c->current = c->end;
return false;
}
c->current = buf + 12;
int consumed = __ns_name_length_uncompressed (c->current, c->end);
if (consumed < 0)
{
__set_errno (EMSGSIZE);
c->current = c->end;
c->first_rr = NULL;
return false;
}
c->current += consumed;
/* Ensure there is room for question type and class. */
if (c->end - c->current < 4)
{
__set_errno (EMSGSIZE);
c->current = c->end;
c->first_rr = NULL;
return false;
}
c->current += 4;
c->first_rr = c->current;
return true;
}
+74
View File
@@ -0,0 +1,74 @@
/* Simple DNS record parser without textual name decoding.
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 <arpa/nameser.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
bool
__ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
{
rr->rdata = NULL;
/* Extract the record owner name. */
int consumed = __ns_name_unpack (c->begin, c->end, c->current,
rr->rname, sizeof (rr->rname));
if (consumed < 0)
{
memset (rr, 0, sizeof (*rr));
__set_errno (EMSGSIZE);
return false;
}
c->current += consumed;
/* Extract the metadata. */
struct
{
uint16_t rtype;
uint16_t rclass;
uint32_t ttl;
uint16_t rdlength;
} __attribute__ ((packed)) metadata;
_Static_assert (sizeof (metadata) == 10, "sizeof metadata");
if (c->end - c->current < sizeof (metadata))
{
memset (rr, 0, sizeof (*rr));
__set_errno (EMSGSIZE);
return false;
}
memcpy (&metadata, c->current, sizeof (metadata));
c->current += sizeof (metadata);
/* Endianess conversion. */
rr->rtype = ntohs (metadata.rtype);
rr->rclass = ntohs (metadata.rclass);
rr->ttl = ntohl (metadata.ttl);
rr->rdlength = ntohs (metadata.rdlength);
/* Extract record data. */
if (c->end - c->current < rr->rdlength)
{
memset (rr, 0, sizeof (*rr));
__set_errno (EMSGSIZE);
return false;
}
rr->rdata = c->current;
c->current += rr->rdlength;
return true;
}
+55
View File
@@ -0,0 +1,55 @@
/* Compare two binary domain names for quality.
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 <arpa/nameser.h>
#include <stdbool.h>
/* Convert ASCII letters to upper case. */
static inline int
ascii_toupper (unsigned char ch)
{
if (ch >= 'a' && ch <= 'z')
return ch - 'a' + 'A';
else
return ch;
}
bool
__ns_samebinaryname (const unsigned char *a, const unsigned char *b)
{
while (*a != 0 && *b != 0)
{
if (*a != *b)
/* Different label length. */
return false;
int labellen = *a;
++a;
++b;
for (int i = 0; i < labellen; ++i)
{
if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b))
/* Different character in label. */
return false;
++a;
++b;
}
}
/* Match if both names are at the root label. */
return *a == 0 && *b == 0;
}
+471 -729
View File
File diff suppressed because it is too large Load Diff
+9 -5
View File
@@ -138,6 +138,12 @@ binary_leading_dash (const unsigned char *dn)
return dn[0] > 0 && dn[1] == '-';
}
bool
__res_binary_hnok (const unsigned char *dn)
{
return !binary_leading_dash (dn) && binary_hnok (dn);
}
/* Return 1 if res_hnok is a valid host name. Labels must only
contain [0-9a-zA-Z_-] characters, and the name must not start with
a '-'. The latter is to avoid confusion with program options. */
@@ -145,11 +151,9 @@ int
___res_hnok (const char *dn)
{
unsigned char buf[NS_MAXCDNAME];
if (!printable_string (dn)
|| __ns_name_pton (dn, buf, sizeof (buf)) < 0
|| binary_leading_dash (buf))
return 0;
return binary_hnok (buf);
return (printable_string (dn)
&& __ns_name_pton (dn, buf, sizeof (buf)) >= 0
&& __res_binary_hnok (buf));
}
versioned_symbol (libc, ___res_hnok, res_hnok, GLIBC_2_34);
versioned_symbol (libc, ___res_hnok, __libc_res_hnok, GLIBC_PRIVATE);
+135
View File
@@ -0,0 +1,135 @@
/* Test __ns_name_length_uncompressed.
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 <arpa/nameser.h>
#include <array_length.h>
#include <errno.h>
#include <stdio.h>
#include <support/check.h>
#include <support/next_to_fault.h>
/* Reference implementation based on other building blocks. */
static int
reference_length (const unsigned char *p, const unsigned char *eom)
{
unsigned char buf[NS_MAXCDNAME];
int n = __ns_name_unpack (p, eom, p, buf, sizeof (buf));
if (n < 0)
return n;
const unsigned char *q = buf;
if (__ns_name_skip (&q, array_end (buf)) < 0)
return -1;
if (q - buf != n)
/* Compressed name. */
return -1;
return n;
}
static int
do_test (void)
{
{
unsigned char buf[] = { 3, 'w', 'w', 'w', 0, 0, 0 };
TEST_COMPARE (reference_length (buf, array_end (buf)), sizeof (buf) - 2);
TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)),
sizeof (buf) - 2);
TEST_COMPARE (reference_length (array_end (buf) - 1, array_end (buf)), 1);
TEST_COMPARE (__ns_name_length_uncompressed (array_end (buf) - 1,
array_end (buf)), 1);
buf[4] = 0xc0; /* Forward compression reference. */
buf[5] = 0x06;
TEST_COMPARE (reference_length (buf, array_end (buf)), -1);
TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), -1);
}
struct support_next_to_fault ntf = support_next_to_fault_allocate (300);
/* Buffer region with all possible bytes at start and end. */
for (int length = 1; length <= 300; ++length)
{
unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
unsigned char *start = end - length;
memset (start, 'X', length);
for (int first = 0; first <= 255; ++first)
{
*start = first;
for (int last = 0; last <= 255; ++last)
{
start[length - 1] = last;
TEST_COMPARE (reference_length (start, end),
__ns_name_length_uncompressed (start, end));
}
}
}
/* Poor man's fuzz testing: patch two bytes. */
{
unsigned char ref[] =
{
7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'n', 'e', 't', 0, 0, 0
};
TEST_COMPARE (reference_length (ref, array_end (ref)), 13);
TEST_COMPARE (__ns_name_length_uncompressed (ref, array_end (ref)), 13);
int good = 0;
int bad = 0;
for (int length = 1; length <= sizeof (ref); ++length)
{
unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
unsigned char *start = end - length;
memcpy (start, ref, length);
for (int patch1_pos = 0; patch1_pos < length; ++patch1_pos)
{
for (int patch1_value = 0; patch1_value <= 255; ++patch1_value)
{
start[patch1_pos] = patch1_value;
for (int patch2_pos = 0; patch2_pos < length; ++patch2_pos)
{
for (int patch2_value = 0; patch2_value <= 255;
++patch2_value)
{
start[patch2_pos] = patch2_value;
int expected = reference_length (start, end);
errno = EINVAL;
int actual
= __ns_name_length_uncompressed (start, end);
if (actual > 0)
++good;
else
{
TEST_COMPARE (errno, EMSGSIZE);
++bad;
}
TEST_COMPARE (expected, actual);
}
start[patch2_pos] = ref[patch2_pos];
}
}
start[patch1_pos] = ref[patch1_pos];
}
}
printf ("info: patched inputs with success: %d\n", good);
printf ("info: patched inputs with failure: %d\n", bad);
}
support_next_to_fault_free (&ntf);
return 0;
}
#include <support/test-driver.c>
+227
View File
@@ -0,0 +1,227 @@
/* Tests for resource record parsing.
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 <arpa/nameser.h>
#include <string.h>
#include <support/check.h>
#include <support/next_to_fault.h>
/* Reference packet for packet parsing. */
static const unsigned char valid_packet[] =
{ 0x11, 0x12, 0x13, 0x14,
0x00, 0x01, /* Question count. */
0x00, 0x02, /* Answer count. */
0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */
3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
0x00, 0x1c, /* Question type: AAAA. */
0x00, 0x01, /* Question class: IN. */
0xc0, 0x0c, /* Compression reference to QNAME. */
0x00, 0x1c, /* Record type: AAAA. */
0x00, 0x01, /* Record class: IN. */
0x12, 0x34, 0x56, 0x78, /* Record TTL. */
0x00, 0x10, /* Record data length (16 bytes). */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */
0xc0, 0x0c, /* Compression reference to QNAME. */
0x00, 0x1c, /* Record type: AAAA. */
0x00, 0x01, /* Record class: IN. */
0x11, 0x33, 0x55, 0x77, /* Record TTL. */
0x00, 0x10, /* Record data length (16 bytes). */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */
};
/* Special offsets in valid_packet. */
enum
{
offset_of_first_record = 29,
offset_of_second_record = 57,
};
/* Check that parsing valid_packet succeeds. */
static void
test_valid (void)
{
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet,
sizeof (valid_packet)));
TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
TEST_COMPARE (c.current - valid_packet, offset_of_first_record);
struct ns_rr_wire r;
TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
TEST_COMPARE (r.rtype, T_AAAA);
TEST_COMPARE (r.rclass, C_IN);
TEST_COMPARE (r.ttl, 0x12345678);
TEST_COMPARE_BLOB (r.rdata, r.rdlength,
"\x90\x91\x92\x93\x94\x95\x96\x97"
"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
TEST_COMPARE (c.current - valid_packet, offset_of_second_record);
TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
TEST_COMPARE (r.rtype, T_AAAA);
TEST_COMPARE (r.rclass, C_IN);
TEST_COMPARE (r.ttl, 0x11335577);
TEST_COMPARE_BLOB (r.rdata, r.rdlength,
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
"\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
TEST_VERIFY (c.current == c.end);
}
/* Check that trying to parse a packet with a compressed QNAME fails. */
static void
test_compressed_qname (void)
{
static const unsigned char packet[] =
{ 0x11, 0x12, 0x13, 0x14,
0x00, 0x01, /* Question count. */
0x00, 0x00, /* Answer count. */
0x00, 0x00, 0x00, 0x00, /* Other counts. */
3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
0x00, 0x01, /* Question type: A. */
0x00, 0x01, /* Question class: IN. */
};
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
}
/* Check that trying to parse a packet with two questions fails. */
static void
test_two_questions (void)
{
static const unsigned char packet[] =
{ 0x11, 0x12, 0x13, 0x14,
0x00, 0x02, /* Question count. */
0x00, 0x00, /* Answer count. */
0x00, 0x00, 0x00, 0x00, /* Other counts. */
3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
0x00, 0x01, /* Question type: A. */
0x00, 0x01, /* Question class: IN. */
3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
0x00, 0x1c, /* Question type: AAAA. */
0x00, 0x01, /* Question class: IN. */
};
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
}
/* Used to check that parsing truncated packets does not over-read. */
static struct support_next_to_fault ntf;
/* Truncated packet in the second resource record. */
static void
test_truncated_one_rr (size_t length)
{
unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
unsigned char *start = end - length;
/* Produce the truncated packet. */
memcpy (start, valid_packet, length);
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
TEST_COMPARE (c.current - start, offset_of_first_record);
struct ns_rr_wire r;
TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
TEST_COMPARE (r.rtype, T_AAAA);
TEST_COMPARE (r.rclass, C_IN);
TEST_COMPARE (r.ttl, 0x12345678);
TEST_COMPARE_BLOB (r.rdata, r.rdlength,
"\x90\x91\x92\x93\x94\x95\x96\x97"
"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
TEST_COMPARE (c.current - start, offset_of_second_record);
TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
}
/* Truncated packet in the first resource record. */
static void
test_truncated_no_rr (size_t length)
{
unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
unsigned char *start = end - length;
/* Produce the truncated packet. */
memcpy (start, valid_packet, length);
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
TEST_COMPARE (c.current - start, offset_of_first_record);
struct ns_rr_wire r;
TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
}
/* Truncated packet before first resource record. */
static void
test_truncated_before_rr (size_t length)
{
unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
unsigned char *start = end - length;
/* Produce the truncated packet. */
memcpy (start, valid_packet, length);
struct ns_rr_cursor c;
TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
}
static int
do_test (void)
{
ntf = support_next_to_fault_allocate (sizeof (valid_packet));
test_valid ();
test_compressed_qname ();
test_two_questions ();
for (int length = offset_of_second_record; length < sizeof (valid_packet);
++length)
test_truncated_one_rr (length);
for (int length = offset_of_first_record; length < offset_of_second_record;
++length)
test_truncated_no_rr (length);
for (int length = 0; length < offset_of_first_record; ++length)
test_truncated_before_rr (length);
support_next_to_fault_free (&ntf);
return 0;
}
#include <support/test-driver.c>

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