Compare commits

...
Author SHA1 Message Date
Fabian Rast d9eaad3515 rtld: cache cpuid results on the stack for intel
dl_init_cacheinfo retrieves various information about cache
sizes, using the cpuid instruction on x86.
Previously, the same cpuid leaves were queried multiple times.
This behavior caused intel_check_word to prominently show up in
profiles of dynamic loader startup on the Intel(R) Xeon(R) Gold 6430.
The big performance impact could not be reproduced on other Intel cpus.

This patch reduces the number of cpuid queries on startup
by caching their results on the stack for reuse when searching for a
different cache size value.
This approach does not change the overall design of
the cache enumeration code (repeated calls to handle_* functions).
The values are cached on the stack instead of globally (e.g.
in the cpu_features global) because they are never needed after
early initialization.

The cache is only active for Intel cpus, because it has not yet
been shown through benchmarks that it meaningfully improves performance
for other processors.

Signed-off-by: Fabian Rast <fabian.rast@tum.de>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit df83fa8813)
2026-07-13 18:08:07 -07:00
Florian Weimer be1e627cd7 Linux: Only define OPEN_TREE_* macros in <sys/mount.h> if undefined (bug 33921)
There is a conditional inclusion of <linux/mount.h> earlier in the file.
If that defines the macros, do not redefine them.  This addresses build
problems as the token sequence used by the UAPI macro definitions
changes between Linux versions.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit d12b017cdd)
2026-05-02 13:57:52 +02:00
DJ Delorie 98bc06a361 include: isolate __O_CLOEXEC flag for sys/mount.h and fcntl.h
Including sys/mount.h should not implicitly include fcntl.h
as that causes namespace pollution and conflicts with kernel
headers.  It only needs O_CLOEXEC for OPEN_TREE_CLOEXEC
(although it shouldn't need that, but it's defined that way)
so we provide that define (via a private version) separately.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Tested-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 419245719c)
2026-05-02 13:57:52 +02:00
Florian Weimer 3e13579841 Use pending character state in IBM1390, IBM1399 character sets (CVE-2026-4046)
Follow the example in iso-2022-jp-3.c and use the __count state
variable to store the pending character.  This avoids restarting
the conversion if the output buffer ends between two 4-byte UCS-4
code points, so that the assert reported in the bug can no longer
happen.

Even though the fix is applied to ibm1364.c, the change is only
effective for the two HAS_COMBINED codecs for IBM1390, IBM1399.

The test case was mostly auto-generated using
claude-4.6-opus-high-thinking, and composer-2-fast shows up in the
log as well.  During review, gpt-5.4-xhigh flagged that the original
version of the test case was not exercising the new character
flush logic.

This fixes bug 33980.

Assisted-by: LLM
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit d6f08d1cf0)
2026-04-20 23:01:20 +02:00
Xi Ruoyao 0dc95ae109 elf: parse /proc/self/maps as the last resort to find the gap for tst-link-map-contiguous-ldso
The initialization process of libc.so calls mmap() several times and the
kernel may lay the maps into the gap.  If all pages in the gap are
occupied, the test would not be able to find the gap with mmap() and the
test would fail.

The failure reproduces most frequently on LoongArch because with the
commonly used page size (16 KiB) the gap only contains 4 pages and the
probability they are all occupied is not near to zero.

With the changes in the patch, a test run may output:

    info: ld.so link map is not contiguous
    info: object "/dev/zero" found at 0x7ffff1fe0000 - 0x7ffff1fe4000
    info: anonymous mapping found at 0x7ffff1fe4000 - 0x7ffff1fec000

Also take the chance to fix a mistake in the "object found at" message
which has puzzled me during the initial debug session.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit aed8390a6a)
2026-03-29 22:28:13 +02:00
Carlos O'Donell 9344c796f7 resolv: Check hostname for validity (CVE-2026-4438)
The processed hostname in getanswer_ptr should be correctly checked to
avoid invalid characters from being allowed, including shell
metacharacters. It is a security issue to fail to check the returned
hostname for validity.

A regression test is added for invalid metacharacters and other cases
of invalid or valid characters.

No regressions on x86_64-linux-gnu.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit e10977481f)
2026-03-29 15:05:21 +02:00
Carlos O'Donell 5663ab0b83 resolv: Count records correctly (CVE-2026-4437)
The answer section boundary was previously ignored, and the code in
getanswer_ptr would iterate past the last resource record, but not
beyond the end of the returned data.  This could lead to subsequent data
being interpreted as answer records, thus violating the DNS
specification.  Such resource records could be maliciously crafted and
hidden from other tooling, but processed by the glibc stub resolver and
acted upon by the application.  While we trust the data returned by the
configured recursive resolvers, we should not trust its format and
should validate it as required.  It is a security issue to incorrectly
process the DNS protocol.

A regression test is added for response section crossing.

No regressions on x86_64-linux-gnu.

Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit 9f5f18aab4)
2026-03-29 15:05:17 +02:00
Florian Weimer c53cd6e738 posix: Run tst-wordexp-reuse-mem test
The test was not properly scheduled for execution with a Makefile
dependency.

Fixes commit 80cc58ea2d ("posix: Reset
wordexp_t fields with WRDE_REUSE (CVE-2025-15281 / BZ 33814").

(cherry picked from commit bed2db02f3)
2026-03-23 15:46:18 +01:00
Florian Weimer 2760e4c5ed iconvdata: Fix invalid pointer arithmetic in ANSI_X3.110 module
The expression inptr + 1 can technically be invalid: if inptr == inend,
inptr may point one element past the end of an array.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit e98bd0c54d)
2026-03-23 15:46:18 +01:00
Yury Khrustalev ba29a36aa3 posix: Fix invalid flags test for p{write,read}v2
Two tests fail from time to time when a new flag is added for the
p{write,read}v2 functions in a new Linux kernel:

 - misc/tst-preadvwritev2
 - misc/tst-preadvwritev64v2

This disrupts when testing Glibc on a system with a newer kernel
and it seems we can try improve testing for invalid flags setting
all the bits that are not supposed to be supported (rather than
setting only the next unsupported bit).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 58a31b4316)
2026-03-23 15:46:18 +01:00
Sergey Kolosov 60b039bf6a socket: Add new test for shutdown
This commit adds shutdown test with SHUT_RD, SHUT_WR, SHUT_RDWR for an
UNIX socket connection.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 50f5a09e68)
2026-03-23 15:46:18 +01:00
Adhemerval Zanella ce65d944e3 posix: Reset wordexp_t fields with WRDE_REUSE (CVE-2025-15281 / BZ 33814)
The wordexp fails to properly initialize the input wordexp_t when
WRDE_REUSE is used. The wordexp_t struct is properly freed, but
reuses the old wc_wordc value and updates the we_wordv in the
wrong position.  A later wordfree will then call free with an
invalid pointer.

Checked on x86_64-linux-gnu and i686-linux-gnu.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 80cc58ea2d)
2026-01-20 14:05:25 -03:00
Carlos O'Donell 831f63b94c resolv: Fix NSS DNS backend for getnetbyaddr (CVE-2026-0915)
The default network value of zero for net was never tested for and
results in a DNS query constructed from uninitialized stack bytes.
The solution is to provide a default query for the case where net
is zero.

Adding a test case for this was straight forward given the existence of
tst-resolv-network and if the test is added without the fix you observe
this failure:

FAIL: resolv/tst-resolv-network
original exit status 1
error: tst-resolv-network.c:174: invalid QNAME: \146\218\129\128
error: 1 test failures

With a random QNAME resulting from the use of uninitialized stack bytes.

After the fix the test passes.

Additionally verified using wireshark before and after to ensure
on-the-wire bytes for the DNS query were as expected.

No regressions on x86_64.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit e56ff82d50)
2026-01-16 09:31:52 -05:00
Siddhesh Poyarekar fb22fd3f5b memalign: reinstate alignment overflow check (CVE-2026-0861)
The change to cap valid sizes to PTRDIFF_MAX inadvertently dropped the
overflow check for alignment in memalign functions, _mid_memalign and
_int_memalign.  Reinstate the overflow check in _int_memalign, aligned
with the PTRDIFF_MAX change since that is directly responsible for the
CVE.  The missing _mid_memalign check is not relevant (and does not have
a security impact) and may need a different approach to fully resolve,
so it has been omitted.

CVE-Id: CVE-2026-0861
Vulnerable-Commit: 9bf8e29ca1
Reported-by: Igor Morgenstern, Aisle Research
Fixes: BZ #33796
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
(cherry picked from commit c9188d3337)
2026-01-15 22:12:04 -05:00
Florian Weimer 10c0bcb3d3 support: Exit on consistency check failure in resolv_response_add_name
Using TEST_VERIFY (crname_target != crname) instructs some analysis
tools that crname_target == crname might hold.  Under this assumption,
they report a use-after-free for crname_target->offset below, caused
by the previous free (crname).

Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit b64335ff11)
2026-01-07 14:30:01 +01:00
Florian Weimer f47dd22366 support: Fix FILE * leak in check_for_unshare_hints in test-container
The file opened via fopen is never closed.

(cherry picked from commit 20a2a75608)
2026-01-07 14:30:01 +01:00
Collin Funk 4a53354eaf sprof: fix -Wformat warnings on 32-bit hosts
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 9681f645ba)
2026-01-07 14:30:01 +01:00
DJ Delorie beb8267909 sprof: check pread size and offset for overflow
Add a bit of descriptive paranoia to the values we read from
the ELF headers and use to access data.

Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit 324084649b)
2026-01-07 14:30:01 +01:00
H.J. Lu c07002038f getaddrinfo.c: Avoid uninitialized pointer access [BZ #32465]
Add valid_decimal_value to check valid decimal value in a string to
avoid uninitialized endp in add_prefixlist and gaiconf_init as reported
by Clang 19:

./getaddrinfo.c:1884:11: error: variable 'endp' is used uninitialized whenever '||' condition is true [-Werror,-Wsometimes-uninitialized]
 1884 |       && (cp == NULL
      |           ^~~~~~~~~~
./getaddrinfo.c:1887:11: note: uninitialized use occurs here
 1887 |       && *endp == '\0'
      |           ^~~~
./getaddrinfo.c:1884:11: note: remove the '||' if its condition is always false
 1884 |       && (cp == NULL
      |           ^~~~~~~~~~
 1885 |           || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
      |           ~~
./getaddrinfo.c:1875:13: note: initialize the variable 'endp' to silence this warning
 1875 |   char *endp;
      |             ^
      |              = NULL

This fixes BZ #32465.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 33aeb88c5b)
2026-01-07 14:30:01 +01:00
Sunil K Pandey ae5fb93559 nptl: Optimize trylock for high cache contention workloads (BZ #33704)
Check lock availability before acquisition to reduce cache line
bouncing.  Significantly improves trylock throughput on multi-core
systems under heavy contention.

Tested on x86_64.

Fixes BZ #33704.

Co-authored-by: Alex M Wells <alex.m.wells@intel.com>
Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 63716823db)
2025-12-18 10:56:34 -08:00
Sachin Monga efff7cb659 ppc64le: Power 10 rawmemchr clobbers v20 (bug #33091)
Replace non-volatile(v20) by volatile(v17)
since v20 is not restored

Reviewed-by: Peter Bergner <bergner@tenstorrent.com>
(cherry picked from commit b59799f14f)
2025-11-27 11:10:11 -05:00
Sachin Monga f6becd8ae8 ppc64le: Restore optimized strncmp for power10
This patch addresses the actual cause of CVE-2025-5745

The vector non-volatile registers are not used anymore for
32 byte load and comparison operation

Additionally, the assembler workaround used earlier for the
instruction lxvp is replaced with actual instruction.

Signed-off-by: Sachin Monga <smonga@linux.ibm.com>
Co-authored-by: Paul Murphy <paumurph@redhat.com>
(cherry picked from commit 2ea943f7d4)
2025-11-21 01:56:26 -05:00
Sachin Monga 0daa4e46b8 ppc64le: Restore optimized strcmp for power10
This patch addresses the actual cause of CVE-2025-5702

The vector non-volatile registers are not used anymore for
32 byte load and comparison operation

Additionally, the assembler workaround used earlier for the
instruction lxvp is replaced with actual instruction.

Signed-off-by: Sachin Monga <smonga@linux.ibm.com>
Co-authored-by: Paul Murphy <paumurph@redhat.com>
(cherry picked from commit 9a40b1cda5)
2025-11-21 01:56:00 -05:00
Joe Ramsay 28c1de6580 AArch64: Fix instability in AdvSIMD tan
Previously presence of special-cases in one lane could affect the
results in other lanes due to unconditional scalar fallback. The old
WANT_SIMD_EXCEPT option (which has never been enabled in libmvec) has
been removed from AOR, making it easier to spot and fix this. 4%
improvement in throughput with GCC 14 on Neoverse V1. This bug is
present as far back as 2.39 (where tan was first introduced).

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 6c22823da5)
2025-11-18 16:38:18 +00:00
Joe Ramsay 03d0393343 AArch64: Optimise SVE scalar callbacks
Instead of using SVE instructions to marshall special results into the
correct lane, just write the entire vector (and the predicate) to
memory, then use cheaper scalar operations.

Geomean speedup of 16% in special intervals on Neoverse with GCC 14.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 5b82fb1882)
2025-11-18 16:38:07 +00:00
Yury Khrustalev 0d05a895f1 aarch64: fix includes in SME tests
Use the correct include for the SIGCHLD macro: signal.h

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit a9c426bcca)
(cherry picked from commit 17c3eab387)
(cherry picked from commit 215e9155ea)
(cherry picked from commit a66680adf3)
2025-11-14 10:03:08 +00:00
Yury Khrustalev c1dc4412f8 aarch64: fix cfi directives around __libc_arm_za_disable
Incorrect CFI directive corrupted call stack information
and prevented debuggers from correctly displaying call
stack information.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 2f77aec043)
(cherry picked from commit de1fe81f47)
(cherry picked from commit 5bf8ee7ad5)
(cherry picked from commit 1c0ad5ea63)
2025-11-14 10:03:08 +00:00
Yury Khrustalev d60f15dc89 aarch64: tests for SME
This commit adds tests for the following use cases relevant to handing of
the SME state:

 - fork() and vfork()
 - clone() and clone3()
 - signal handler

While most cases are trivial, the case of clone3() is more complicated since
the clone3() symbol is not public in Glibc.

To avoid having to check all possible ways clone3() may be called via other
public functions (e.g. vfork() or pthread_create()), we put together a test
that links directly with clone3.o. All the existing functions that have calls
to clone3() may not actually use it, in which case the outcome of such tests
would be unexpected. Having a direct call to the clone3() symbol in the test
allows to check precisely what we need to test: that the __arm_za_disable()
function is indeed called and has the desired effect.

Linking to clone3.o also requires linking to __arm_za_disable.o that in
turn requires the _dl_hwcap2 hidden symbol which to provide in the test
and initialise it before using.

Co-authored-by: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit ecb0fc2f0f)
(cherry picked from commit 71874f167a)
(cherry picked from commit e4ffcf32b9)
(cherry picked from commit df3bcda9ac)
2025-11-14 10:03:08 +00:00
Yury Khrustalev d1d0d09e9e aarch64: clear ZA state of SME before clone and clone3 syscalls
This change adds a call to the __arm_za_disable() function immediately
before the SVC instruction inside clone() and clone3() wrappers. It also
adds a macro for inline clone() used in fork() and adds the same call to
the vfork implementation. This sets the ZA state of SME to "off" on return
from these functions (for both the child and the parent).

The __arm_za_disable() function is described in [1] (8.1.3). Note that
the internal Glibc name for this function is __libc_arm_za_disable().

When this change was originally proposed [2,3], it generated a long
discussion where several questions and concerns were raised. Here we
will address these concerns and explain why this change is useful and,
in fact, necessary.

In a nutshell, a C library that conforms to the AAPCS64 spec [1] (pertinent
to this change, mainly, the chapters 6.2 and 6.6), should have a call to the
__arm_za_disable() function in clone() and clone3() wrappers. The following
explains in detail why this is the case.

When we consider using the __arm_za_disable() function inside the clone()
and clone3() libc wrappers, we talk about the C library subroutines clone()
and clone3() rather than the syscalls with similar names. In the current
version of Glibc, clone() is public and clone3() is private, but it being
private is not pertinent to this discussion.

We will begin with stating that this change is NOT a bug fix for something
in the kernel. The requirement to call __arm_za_disable() does NOT come from
the kernel. It also is NOT needed to satisfy a contract between the kernel
and userspace. This is why it is not for the kernel documentation to describe
this requirement. This requirement is instead needed to satisfy a pure userspace
scheme outlined in [1] and to make sure that software that uses Glibc (or any
other C library that has correct handling of SME states (see below)) conforms
to [1] without having to unnecessarily become SME-aware thus losing portability.

To recap (see [1] (6.2)), SME extension defines SME state which is part of
processor state. Part of this SME state is ZA state that is necessary to
manage ZA storage register in the context of the ZA lazy saving scheme [1]
(6.6). This scheme exists because it would be challenging to handle ZA
storage of SME in either callee-saved or caller-saved manner.

There are 3 kinds of ZA state that are defined in terms of the PSTATE.ZA
bit and the TPIDR2_EL0 register (see [1] (6.6.3)):

- "off":       PSTATE.ZA == 0
- "active":    PSTATE.ZA == 1 TPIDR2_EL0 == null
- "dormant":   PSTATE.ZA == 1 TPIDR2_EL0 != null

As [1] (6.7.2) outlines, every subroutine has exactly one SME-interface
depending on the permitted ZA-states on entry and on normal return from
a call to this subroutine. Callers of a subroutine must know and respect
the ZA-interface of the subroutines they are using. Using a subroutine
in a way that is not permitted by its ZA-interface is undefined behaviour.

In particular, clone() and clone3() (the C library functions) have the
ZA-private interface. This means that the permitted ZA-states on entry
are "off" and "dormant" and that the permitted states on return are "off"
or "dormant" (but if and only if it was "dormant" on entry).

This means that both functions in question should correctly handle both
"off" and "dormant" ZA-states on entry. The conforming states on return
are "off" and "dormant" (if inbound state was already "dormant").

This change ensures that the ZA-state on return is always "off". Note,
that, in the context of clone() and clone3(), "on return" means a point
when execution resumes at certain address after transferring from clone()
or clone3(). For the caller (we may refer to it as "parent") this is the
return address in the link register where the RET instruction jumps. For
the "child", this is the target branch address.

So, the "off" state on return is permitted and conformant. Why can't we
retain the "dormant" state? In theory, we can, but we shouldn't, here is
why.

Every subroutine with a private-ZA interface, including clone() and clone3(),
must comply with the lazy saving scheme [1] (6.7.2). This puts additional
responsibility on a subroutine if ZA-state on return is "dormant" because
this state has special meaning. The "caller" (that is the place in code
where execution is transferred to, so this include both "parent" and "child")
may check the ZA-state and use it as per the spec of the "dormant" state that
is outlined in [1] (6.6.6 and 6.6.7).

Conforming to this would require more code inside of clone() and clone3()
which hardly is desirable.

For the return to "parent" this could be achieved in theory, but given that
neither clone() nor clone3() are supposed to be used in the middle of an
SME operation, if wouldn't be useful. For the "return" to "child" this
would be particularly difficult to achieve given the complexity of these
functions and their interfaces. Most importantly, it would be illegal
and somewhat meaningless to allow a "child" to start execution in the
"dormant" ZA-state because the very essence of the "dormant" state implies
that there is a place to return and that there is some outer context that
we are allowed to interact with.

To sum up, calling __arm_za_disable() to ensure the "off" ZA-state when the
execution resumes after a call to clone() or clone3() is correct and also
the most simple way to conform to [1].

Can there be situations when we can avoid calling __arm_za_disable()?

Calling __arm_za_disable() implies certain (sufficiently small) overhead,
so one might rightly ponder avoiding making a call to this function when
we can afford not to. The most trivial cases like this (e.g. when the
calling thread doesn't have access to SME or to the TPIDR2_EL0 register)
are already handled by this function (see [1] (8.1.3 and 8.1.2)). Reasoning
about other possible use cases would require making code inside clone() and
clone3() more complicated and it would defeat the point of trying to make
an optimisation of not calling __arm_za_disable().

Why can't the kernel do this instead?

The handling of SME state by the kernel is described in [4]. In short,
kernel must not impose a specific ZA-interface onto a userspace function.
Interaction with the kernel happens (among other thing) via system calls.
In Glibc many of the system calls (notably, including SYS_clone and
SYS_clone3) are used via wrappers, and the kernel has no control of them
and, moreover, it cannot dictate how these wrappers should behave because
it is simply outside of the kernel's remit.

However, in certain cases, the kernel may ensure that a "child" doesn't
start in an incorrect state. This is what is done by the recent change
included in 6.16 kernel [5]. This is not enough to ensure that code that
uses clone() and clone3() function conforms to [1] when it runs on a
system that provides SME, hence this change.

[1]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
[2]: https://inbox.sourceware.org/libc-alpha/20250522114828.2291047-1-yury.khrustalev@arm.com
[3]: https://inbox.sourceware.org/libc-alpha/20250609121407.3316070-1-yury.khrustalev@arm.com
[4]: https://www.kernel.org/doc/html/v6.16/arch/arm64/sme.html
[5]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cde5c32db55740659fca6d56c09b88800d88fd29

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 27effb3d50)
(cherry picked from commit 256030b984)
(cherry picked from commit 889ae4bdbb)
(cherry picked from commit 899ebf3569)
2025-11-14 10:03:08 +00:00
Yury Khrustalev dbe1904b7c aarch64: define macro for calling __libc_arm_za_disable
A common sequence of instructions is used in several places
in assembly files, so define it in one place as an assembly
macro.

Note that PAC instructions are not included in the new macro
because they are redundant given how we call the arm_za_disable
function (return address is not saved on stack, so no need to
sign it).

(based on commits 6de12fc9ad
 and c0f0db2d59)

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 1a0ee26714)
(cherry picked from commit 7af8db46d2)
2025-11-14 10:03:08 +00:00
Yury Khrustalev 58cf4aa421 aarch64: update tests for SME
Add test that checks that ZA state is disabled after setjmp and sigsetjmp
Update existing SME test that uses setjmp

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 251f932624)
(cherry picked from commit 97076e0cf1)
(cherry picked from commit 51bcc73d95)
2025-11-14 10:03:08 +00:00
Yury Khrustalev 1b3bd9a9a6 aarch64: Disable ZA state of SME in setjmp and sigsetjmp
Due to the nature of the ZA state, setjmp() should clear it in the
same manner as it is already done by longjmp.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit a7f6fd976c)
(cherry picked from commit 1f57ffdf35)
(cherry picked from commit cdc1665bb1)
2025-11-14 10:03:08 +00:00
Adhemerval Zanella 38942a336b linux: Also check pkey_get for ENOSYS on tst-pkey (BZ 31996)
The powerpc pkey_get/pkey_set support was only added for 64-bit [1],
and tst-pkey only checks if the support was present with pkey_alloc
(which does not fail on powerpc32, at least running a 64-bit kernel).

Checked on powerpc-linux-gnu.

[1] https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a803367bab167f5ec4fde1f0d0ec447707c29520
Reviewed-By: Andreas K. Huettel <dilfridge@gentoo.org>

(cherry picked from commit 6b7e2e1d61)
2025-11-14 09:52:04 +00:00
Florian Weimer c74d59a656 aarch64: Do not link conform tests with -Wl,-z,force-bti (bug 33601)
If the toolchain does not default to generate BTI markers in GCC,
the main program for conform runtime tests will not have the
BTI marker that -Wl,-z,force-bti requires.  Without -Wl,-z,force-bti,
the link editor will not tell the dynamic linker to enable BTI,
and the missing BTI marker is harmless.

Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
(cherry picked from commit 75b6b263e9)
2025-11-13 15:09:34 +01:00
Jiamei Xie 323ad087a1 x86: fix wmemset ifunc stray '!' (bug 33542)
The ifunc selector for wmemset had a stray '!' in the
X86_ISA_CPU_FEATURES_ARCH_P(...) check:

  if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX2)
      && X86_ISA_CPU_FEATURES_ARCH_P (cpu_features,
                                      AVX_Fast_Unaligned_Load, !))

This effectively negated the predicate and caused the AVX2/AVX512
paths to be skipped, making the dispatcher fall back to the SSE2
implementation even on CPUs where AVX2/AVX512 are available. The
regression leads to noticeable throughput loss for wmemset.

Remove the stray '!' so the AVX_Fast_Unaligned_Load capability is
tested as intended and the correct AVX2/EVEX variants are selected.

Impact:
- On AVX2/AVX512-capable x86_64, wmemset no longer incorrectly
  falls back to SSE2; perf now shows __wmemset_evex/avx2 variants.

Testing:
- benchtests/bench-wmemset shows improved bandwidth across sizes.
- perf confirm the selected symbol is no longer SSE2.

Signed-off-by: xiejiamei <xiejiamei@hygon.com>
Signed-off-by: Li jing <lijing@hygon.cn>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 4d86b6cdd8)
2025-11-04 12:22:53 +00:00
Sunil K Pandey 58cbbd43fe x86: Detect Intel Nova Lake Processor
Detect Intel Nova Lake Processor and tune it similar to Intel Panther
Lake.  https://cdrdv2.intel.com/v1/dl/getContent/671368 Section 1.2.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit a114e29ddd)
2025-10-08 13:38:26 -07:00
Sunil K Pandey 835b1e3379 x86: Detect Intel Wildcat Lake Processor
Detect Intel Wildcat Lake Processor and tune it similar to Intel Panther
Lake.  https://cdrdv2.intel.com/v1/dl/getContent/671368 Section 1.2.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit f8dd52901b)
2025-10-08 13:38:08 -07:00
Florian Weimer 765534258e nss: Group merge does not react to ERANGE during merge (bug 33361)
The break statement in CHECK_MERGE is expected to exit the surrounding
while loop, not the do-while loop with in the macro.  Remove the
do-while loop from the macro.  It is not needed to turn the macro
expansion into a single statement due to the way CHECK_MERGE is used
(and the statement expression would cover this anyway).

Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit 0fceed2545)
2025-09-19 10:17:22 +02:00
Joseph Myers 7ce7b4b2f4 Rename new tst-sem17 test to tst-sem18
As noted by Adhemerval, we already have a tst-sem17 in nptl.

Tested for x86_64.

(cherry picked from commit c7dcf594f4)
2025-08-26 09:33:32 +02:00
Joseph Myers a6ac06abeb Avoid uninitialized result in sem_open when file does not exist
A static analyzer apparently reported an uninitialized use of the
variable result in sem_open in the case where the file is required to
exist but does not exist.

The report appears to be correct; set result to SEM_FAILED in that
case, and add a test for it.

Note: the test passes for me even without the sem_open fix, I guess
because result happens to get value SEM_FAILED (i.e. 0) when
uninitialized.

Tested for x86_64.

(cherry picked from commit f745d78e26)
2025-08-26 09:33:32 +02:00
Aurelien Jarno ff6ce67220 elf: handle addition overflow in _dl_find_object_update_1 [BZ #32245]
The remaining_to_add variable can be 0 if (current_used + count) wraps,
This is caught by GCC 14+ on hppa, which determines from there that
target_seg could be be NULL when remaining_to_add is zero, which in
turns causes a -Wstringop-overflow warning:

 In file included from ../include/atomic.h:49,
                  from dl-find_object.c:20:
 In function '_dlfo_update_init_seg',
     inlined from '_dl_find_object_update_1' at dl-find_object.c:689:30,
     inlined from '_dl_find_object_update' at dl-find_object.c:805:13:
 ../sysdeps/unix/sysv/linux/hppa/atomic-machine.h:44:4: error: '__atomic_store_4' writing 4 bytes into a region of size 0 overflows the destination [-Werror=stringop-overflow=]
    44 |    __atomic_store_n ((mem), (val), __ATOMIC_RELAXED);                        \
       |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 dl-find_object.c:644:3: note: in expansion of macro 'atomic_store_relaxed'
   644 |   atomic_store_relaxed (&seg->size, new_seg_size);
       |   ^~~~~~~~~~~~~~~~~~~~
 In function '_dl_find_object_update':
 cc1: note: destination object is likely at address zero

In practice, this is not possible as it represent counts of link maps.
Link maps have sizes larger than 1 byte, so the sum of any two link map
counts will always fit within a size_t without wrapping around.

This patch therefore adds a check on remaining_to_add == 0 and tell GCC
that this can not happen using __builtin_unreachable.

Thanks to Andreas Schwab for the investigation.

Closes: BZ #32245
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: John David Anglin <dave.anglin@bell.net>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 6c915c73d0)
2025-08-26 09:30:54 +02:00
Florian Weimer fffc2df8a3 Optimize __libc_tsd_* thread variable access
These variables are not exported, and libc.so TLS is initial-exec
anyway.  Declare these variables as hidden and use the initial-exec
TLS model.

Reviewed-by: Frédéric Bérat <fberat@redhat.com>
(cherry picked from commit a894f04d87)
2025-08-20 16:28:59 +02:00
H.J. Lu 83340b35cc i386: Add GLIBC_ABI_GNU_TLS version [BZ #33221]
On i386, programs and shared libraries with __thread usage may fail
silently at run-time against glibc without the TLS run-time fix for:

https://sourceware.org/bugzilla/show_bug.cgi?id=32996

Add GLIBC_ABI_GNU_TLS version to indicate that glibc has the working
GNU TLS run-time.  Linker can add the GLIBC_ABI_GNU_TLS version to
binaries which depend on the working TLS run-time so that such programs
and shared libraries will fail to load and run at run-time against
libc.so without the GLIBC_ABI_GNU_TLS version, instead of fail silently
at random.

This fixes BZ #33221.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit ed1b7a5a48)
2025-08-19 18:28:40 -07:00
H.J. Lu 5541edb1bd i386: Also add GLIBC_ABI_GNU2_TLS version [BZ #33129]
Since the GNU2 TLS run-time bug:

https://sourceware.org/bugzilla/show_bug.cgi?id=31372

affects both i386 and x86-64, also add GLIBC_ABI_GNU2_TLS version to i386
to indicate the working GNU2 TLS run-time.  For x86-64, the additional
GNU2 TLS run-time bug fix is needed for

https://sourceware.org/bugzilla/show_bug.cgi?id=31501

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit bd4628f3f1)
2025-08-19 18:28:33 -07:00
Florian Weimer 1f17635507 debug: Fix tst-longjmp_chk3 build failure on Hurd
Explicitly include <unistd.h> for _exit and getpid.

(cherry picked from commit 4836a9af89)
2025-08-19 09:07:57 -07:00
Florian Weimer 3b6c8ea878 debug: Wire up tst-longjmp_chk3
The test was added in commit ac8cc9e300
without all the required Makefile scaffolding.  Tweak the test
so that it actually builds (including with dynamic SIGSTKSZ).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 4b7cfcc3fb)
2025-08-19 09:07:52 -07:00
H.J. Lu 89596f46e3 i386: Update ___tls_get_addr to preserve vector registers
Compiler generates the following instruction sequence for dynamic TLS
access:

	leal	tls_var@tlsgd(,%ebx,1), %eax
	call	___tls_get_addr@PLT

CALL instruction is transparent to compiler which assumes all registers,
except for EFLAGS, AX, CX, and DX, are unchanged after CALL.  But
___tls_get_addr is a normal function which doesn't preserve any vector
registers.

1. Rename the generic __tls_get_addr function to ___tls_get_addr_internal.
2. Change ___tls_get_addr to a wrapper function with implementations for
FNSAVE, FXSAVE, XSAVE and XSAVEC to save and restore all vector registers.
3. dl-tlsdesc-dynamic.h has:

_dl_tlsdesc_dynamic:
	/* Like all TLS resolvers, preserve call-clobbered registers.
	   We need two scratch regs anyway.  */
	subl	$32, %esp
	cfi_adjust_cfa_offset (32)

It is wrong to use

	movl	%ebx, -28(%esp)
	movl	%esp, %ebx
	cfi_def_cfa_register(%ebx)
	...
	mov	%ebx, %esp
	cfi_def_cfa_register(%esp)
	movl	-28(%esp), %ebx

to preserve EBX on stack.  Fix it with:

	movl	%ebx, 28(%esp)
	movl	%esp, %ebx
	cfi_def_cfa_register(%ebx)
	...
	mov	%ebx, %esp
	cfi_def_cfa_register(%esp)
	movl	28(%esp), %ebx

4. Update _dl_tlsdesc_dynamic to call ___tls_get_addr_internal directly.
5. Add have-test-mtls-traditional to compile tst-tls23-mod.c with
traditional TLS variant to verify the fix.
6. Define DL_RUNTIME_RESOLVE_REALIGN_STACK in sysdeps/x86/sysdep.h.

This fixes BZ #32996.

Co-Authored-By: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 848f0e46f0)
2025-08-18 20:10:32 -07:00
Florian Weimer 4c2509882f elf: Preserve _rtld_global layout for the release branch
Backporting commit 97017da5ef
("elf: Introduce _dl_debug_change_state") removed the
_ns_debug member.  Keep it to preseve struct layout.
2025-08-18 13:52:02 +02:00
Florian Weimer cf0e7d512d elf: Compile _dl_debug_state separately (bug 33224)
This ensures that the compiler will not inline it, so that
debuggers which do not use the Systemtap probes can reliably
set a breakpoint on it.

Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
Tested-by: Andreas K. Huettel <dilfridge@gentoo.org>
(cherry picked from commit 620f0730f3)
2025-08-18 13:12:28 +02:00
Florian Weimer 5cd1f4b1a1 elf: Restore support for _r_debug interpositions and copy relocations
The changes in commit a93d9e03a3
("Extend struct r_debug to support multiple namespaces [BZ #15971]")
break the dyninst dynamic instrumentation tool.  It brings its
own definition of _r_debug (rather than a declaration).

Furthermore, it turns out it is rather hard to use the proposed
handshake for accessing _r_debug via DT_DEBUG. If applications want
to access _r_debug, they can do so directly if the relevant code has
been built as PIC.  To protect against harm from accidental copy
relocations due to linker relaxations, this commit restores copy
relocation support by adjusting both copies if interposition or
copy relocations are in play.  Therefore, it is possible to
use a hidden reference in ld.so to access _r_debug.

Only perform the copy relocation initialization if libc has been
loaded.  Otherwise, the ld.so search scope can be empty, and the
lookup of the _r_debug symbol mail fail.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit ea85e7d550)
2025-08-18 13:12:28 +02:00
Florian Weimer 97017da5ef elf: Introduce _dl_debug_change_state
It combines updating r_state with the debugger notification.

The second change to  _dl_open introduces an additional debugger
notification for dlmopen, but debuggers are expected to ignore it.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 8329939a37)
2025-08-18 13:12:28 +02:00
Florian Weimer 5601ad79b7 elf: Introduce separate _r_debug_array variable
It replaces the ns_debug member of the namespaces.  Previously,
the base namespace had an unused ns_debug member.

This change also fixes a concurrency issue: Now _dl_debug_initialize
only updates r_next of the previous namespace's r_debug after the new
r_debug is initialized, so that only the initialized version is
observed.  (Client code accessing _r_debug will benefit from load
dependency tracking in CPUs even without explicit barriers.)

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 7278d11f3a)
2025-08-18 13:12:28 +02:00
Florian Weimer 24c94ea84e elf: Test dlopen (NULL, RTLD_LAZY) from an ELF constructor
This call must not complete initialization of all shared objects
in the global scope because the ELF constructor which makes the call
likely has not finished initialization.  Calling more constructors
at this point would expose those to a partially constructed
dependency.

This completes the revert of commit 9897ced8e7
("elf: Run constructors on cyclic recursive dlopen (bug 31986)").

(cherry picked from commit d604f9c500)
2025-08-18 13:12:27 +02:00
Florian Weimer 79d84b5da5 elf: Fix handling of symbol versions which hash to zero (bug 29190)
This was found through code inspection.  No application impact is
known.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 46d3198094)
2025-08-18 13:12:22 +02:00
Florian Weimer 5f5c411132 elf: Second ld.so relocation only if libc.so has been loaded
Commit 8f8dd904c4 (“elf:
rtld_multiple_ref is always true”) removed some code that happened
to enable compatibility with programs that do not link against
libc.so.  Such programs cannot call dlopen or any dynamic linker
functions (except __tls_get_addr), so this is not really useful.
Still ld.so should not crash with a null-pointer dereference
or undefined symbol reference in these cases.

In the main relocation loop, call _dl_relocate_object unconditionally
because it already checks if the object has been relocated.

If libc.so was loaded, self-relocate ld.so against it and call
__rtld_mutex_init and __rtld_malloc_init_real to activate the full
implementations.  Those are available only if libc.so is there,
so skip these initialization steps if libc.so is absent.  Without
libc.so, the global scope can be completely empty.  This can cause
ld.so self-relocation to fail because if it uses symbol-based
relocations, which is why the second ld.so self-relocation is not
performed if libc.so is missing.

The previous concern regarding GOT updates through self-relocation
no longer applies because function pointers are updated
explicitly through __rtld_mutex_init and __rtld_malloc_init_real,
and not through relocation.  However, the second ld.so self-relocation
is still delayed, in case there are other symbols being used.

Fixes commit 8f8dd904c4 (“elf:
rtld_multiple_ref is always true”).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 706209867f)
2025-08-18 13:12:20 +02:00
Florian Weimer 4c9b1877fd elf: Reorder audit events in dlcose to match _dl_fini (bug 32066)
This was discovered after extending elf/tst-audit23 to cover
dlclose of the dlmopen namespace.

Auditors already experience the new order during process
shutdown (_dl_fini), so no LAV_CURRENT bump or backwards
compatibility code seems necessary.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 495b96e064)
2025-08-18 13:12:11 +02:00
Florian Weimer f407a14ff7 elf: Call la_objclose for proxy link maps in _dl_fini (bug 32065)
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit c4b160744c)
2025-08-18 13:12:11 +02:00
Florian Weimer e27601b385 elf: Signal la_objopen for the proxy link map in dlmopen (bug 31985)
Previously, the ld.so link map was silently added to the namespace.
This change produces an auditing event for it.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 8f36b14696)
2025-08-18 13:12:11 +02:00
Florian Weimer fef226255d elf: Add the endswith function to <endswith.h>
And include <stdbool.h> for a definition of bool.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit a20bc2f623)
2025-08-18 13:12:11 +02:00
Florian Weimer d21a217fa0 elf: Update DSO list, write audit log to elf/tst-audit23.out
After commit 1d5024f4f0
("support: Build with exceptions and asynchronous unwind tables
[BZ #30587]"), libgcc_s is expected to show up in the DSO
list on 32-bit Arm.  Do not update max_objs because vdso is not
tracked (and which is the reason why the test currently passes
even with libgcc_s present).

Also write the log output from the auditor to standard output,
for easier test debugging.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 4a50fdf8b2)
2025-08-18 13:12:11 +02:00
Florian Weimer 4f145bb35d elf: Switch to main malloc after final ld.so self-relocation
Before commit ee1ada1bdb
("elf: Rework exception handling in the dynamic loader
[BZ #25486]"), the previous order called the main calloc
to allocate a shadow GOT/PLT array for auditing support.
This happened before libc.so.6 ELF constructors were run, so
a user malloc could run without libc.so.6 having been
initialized fully.  One observable effect was that
environ was NULL at this point.

It does not seem to be possible at present to trigger such
an allocation, but it seems more robust to delay switching
to main malloc after ld.so self-relocation is complete.
The elf/tst-rtld-no-malloc-audit test case fails with a
2.34-era glibc that does not have this fix.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit c1560f3f75)
2025-08-18 13:12:10 +02:00
Florian Weimer 65d86471ce elf: Introduce _dl_relocate_object_no_relro
And make _dl_protect_relro apply RELRO conditionally.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit f2326c2ec0)
2025-08-18 13:12:10 +02:00
Florian Weimer 5434cc2c41 elf: Do not define consider_profiling, consider_symbind as macros
This avoids surprises when refactoring the code if these identifiers
are re-used later in the file.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit a796422045)
2025-08-18 13:12:10 +02:00
Florian Weimer b2d8c6cbe7 elf: rtld_multiple_ref is always true
For a long time, libc.so.6 has dependend on ld.so, which
means that there is a reference to ld.so in all processes,
and rtld_multiple_ref is always true.  In fact, if
rtld_multiple_ref were false, some of the ld.so setup code
would not run.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 8f8dd904c4)
2025-08-18 13:12:10 +02:00
Florian Weimer 2b89de7c91 Revert "elf: Run constructors on cyclic recursive dlopen (bug 31986)"
This reverts commit 9897ced8e7.

Adjust the test expectations in elf/tst-dlopen-auditdup-auditmod.c
accordingly.

(cherry picked from commit 95129e6b8f)
2025-08-18 13:12:07 +02:00
Florian Weimer 46e3ecad27 elf: Fix map_complete Systemtap probe in dl_open_worker
The refactoring did not take the change of variable into account.
Fixes commit 43db5e2c06
("elf: Signal RT_CONSISTENT after relocation processing in dlopen
(bug 31986)").

(cherry picked from commit ac73067cb7)
2025-08-18 13:12:01 +02:00
Florian Weimer 5f225025db elf: Signal RT_CONSISTENT after relocation processing in dlopen (bug 31986)
Previously, a la_activity audit event was generated before
relocation processing completed.  This does did not match what
happened during initial startup in elf/rtld.c (towards the end
of dl_main).  It also caused various problems if an auditor
tried to open the same shared object again using dlmopen:
If it was the directly loaded object, it had a search scope
associated with it, so the early exit in dl_open_worker_begin
was taken even though the object was unrelocated.  This caused
the r_state == RT_CONSISTENT assert to fail.  Avoidance of the
assert also depends on reversing the order of r_state update
and auditor event (already implemented in a previous commit).

At the later point, args->map can be NULL due to failure,
so use the assigned namespace ID instead if that is available.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 43db5e2c06)
2025-08-18 13:12:01 +02:00
Florian Weimer d6cc325fcf elf: Signal LA_ACT_CONSISTENT to auditors after RT_CONSISTENT switch
Auditors can call into the dynamic loader again if
LA_ACT_CONSISTENT, and  those recursive calls could observe
r_state != RT_CONSISTENT.

We should consider failing dlopen/dlmopen/dlclose if
r_state != RT_CONSISTENT.  The dynamic linker is probably not
in a state in which it can handle reentrant calls.  This
needs further investigation.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit e096b7a189)
2025-08-18 13:12:01 +02:00
Florian Weimer 6917fde6f9 elf: Run constructors on cyclic recursive dlopen (bug 31986)
This is conceptually similar to the reported bug, but does not
depend on auditing.  The fix is simple: just complete execution
of the constructors.  This exposed the fact that the link map
for statically linked executables does not have l_init_called
set, even though constructors have run.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 9897ced8e7)
2025-08-18 13:12:00 +02:00
Adam Sampson 9fa7cc6a0b ldconfig: Move endswithn into a new header file
is_gdb_python_file is doing a similar test, so it can use this helper
function as well.

Signed-off-by: Adam Sampson <ats@offog.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit ed2b8d3a86)
2025-08-18 13:11:54 +02:00
H.J. Lu 269e89bd8d x86-64: Add GLIBC_ABI_DT_X86_64_PLT [BZ #33212]
When the linker -z mark-plt option is used to add DT_X86_64_PLT,
DT_X86_64_PLTSZ and DT_X86_64_PLTENT, the r_addend field of the
R_X86_64_JUMP_SLOT relocation stores the offset of the indirect
branch instruction.  However, glibc versions without the commit:

commit f8587a6189
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri May 20 19:21:48 2022 -0700

    x86-64: Ignore r_addend for R_X86_64_GLOB_DAT/R_X86_64_JUMP_SLOT

    According to x86-64 psABI, r_addend should be ignored for R_X86_64_GLOB_DAT
    and R_X86_64_JUMP_SLOT.  Since linkers always set their r_addends to 0, we
    can ignore their r_addends.

    Reviewed-by: Fangrui Song <maskray@google.com>

won't ignore the r_addend value in the R_X86_64_JUMP_SLOT relocation.
Such programs and shared libraries will fail at run-time randomly.

Add GLIBC_ABI_DT_X86_64_PLT version to indicate that glibc is compatible
with DT_X86_64_PLT.

The linker can add the glibc GLIBC_ABI_DT_X86_64_PLT version dependency
whenever -z mark-plt is passed to the linker.  The resulting programs and
shared libraries will fail to load at run-time against libc.so without the
GLIBC_ABI_DT_X86_64_PLT version, instead of fail randomly.

This fixes BZ #33212.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 399384e0c8)
2025-08-15 22:23:51 +01:00
H.J. Lu 62ff85fd09 x86-64: Add GLIBC_ABI_GNU2_TLS version [BZ #33129]
Programs and shared libraries compiled with -mtls-dialect=gnu2 may fail
silently at run-time against glibc without the GNU2 TLS run-time fix
for:

https://sourceware.org/bugzilla/show_bug.cgi?id=31372

Add GLIBC_ABI_GNU2_TLS version to indicate that glibc has the working
GNU2 TLS run-time.  Linker can add the GLIBC_ABI_GNU2_TLS version to
binaries which depend on the working GNU2 TLS run-time:

https://sourceware.org/bugzilla/show_bug.cgi?id=33130

so that such programs and shared libraries will fail to load and run at
run-time against libc.so without the GLIBC_ABI_GNU2_TLS version, instead
of fail silently at random.

This fixes BZ #33129.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 9df8fa397d)
2025-08-15 22:20:32 +01:00
Florian Weimer f0e8d04eef libio: Test for fdopen memory leak without SEEK_END support (bug 31840)
The bug report used /dev/mem, but /proc/self/mem works as well
(if available).

(cherry picked from commit d0106b6ae2)
2025-08-15 19:31:16 +02:00
Andreas Schwab 42a8cb7560 Remove memory leak in fdopen (bug 31840)
Deallocate the memory for the FILE structure when seeking to the end fails
in append mode.

Fixes: ea33158c96 ("Fix offset caching for streams and use it for ftell (BZ #16680)")
(cherry picked from commit b2c3ee3724)
2025-08-15 19:31:08 +02:00
Joe Ramsay d1c1f78e9e math: Remove no-mathvec flag
More routines are to follow, some of which hit many failures in the
current testsuite due to wrong sign of zero (mathvec routines are not
required to get this right). Instead of disabling a large number of
tests, change the failure condition such that, for vector routines,
tests pass as long as computed == expected == 0.0, regardless of sign.

Affected tests (vector tests for expm1, log1p, sin, tan and tanh) all
still pass.

(cherry picked from commit 939e770e01)
2025-08-15 15:53:02 +00:00
Jens Remus 20d2d69a2f Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables [BZ #33234]
Commit 10a66a8e42 ("Remove <libc-tsd.h>") removed the TLS initial-exec
(IE) model attribute from the __libc_tsd_CTYPE_* thread variable declarations
and definitions.  Commit a894f04d87 ("Optimize __libc_tsd_* thread
variable access") restored it on declarations.

Restore the TLS initial-exec model attribute on __libc_tsd_CTYPE_* thread
variable definitions.

This resolves test tst-locale1 failure on s390 32-bit, when using a
GNU linker without the fix from GNU binutils commit aefebe82dc89
("IBM zSystems: Fix offset relative to static TLS").

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit e5363e6f46)
2025-08-14 12:39:11 +02:00
Florian Weimer c11950503f ctype: Fallback initialization of TLS using relocations (bug 19341, bug 32483)
This ensures that the ctype data pointers in TLS are valid
in secondary namespaces even without initialization via
__ctype_init.

Reviewed-by: Frédéric Bérat <fberat@redhat.com>
(cherry picked from commit 2745db8dd3)
2025-08-14 12:38:56 +02:00
Florian Weimer 25c537c3b3 Use proper extern declaration for _nl_C_LC_CTYPE_{class,toupper,tolower}
The existing initializers already contain explicit casts.  Keep them
due to int/uint32_t mismatch.

Reviewed-by: Frédéric Bérat <fberat@redhat.com>
(cherry picked from commit e0c0f856f5)
2025-08-14 11:49:23 +02:00
Florian Weimer fbdf9680cc Remove <libc-tsd.h>
Use __thread variables directly instead.  The macros do not save any
typing.  It seems unlikely that a future port will lack __thread
variable support.

Some of the __libc_tsd_* variables are referenced from assembler
files, so keep their names.  Previously, <libc-tls.h> included
<tls.h>, which in turn included <errno.h>, so a few direct includes
of <errno.h> are now required.

Reviewed-by: Frédéric Bérat <fberat@redhat.com>
(cherry picked from commit 10a66a8e42)
2025-08-14 11:49:20 +02:00
Carlos O'Donell fca5937510 ctype: Reformat Makefile.
Reflow and sort Makefile.

Code generation changes present due to link order changes.

No regressions on x86_64 and i686.

(cherry picked from commit 12956e0a33)
2025-08-14 11:49:13 +02:00
Florian Weimer 49f0e73fa3 elf: Handle ld.so with LOAD segment gaps in _dl_find_object (bug 31943)
Detect if ld.so not contiguous and handle that case in _dl_find_object.
Set l_find_object_processed even for initially loaded link maps,
otherwise dlopen of an initially loaded object adds it to
_dlfo_loaded_mappings (where maps are expected to be contiguous),
in addition to _dlfo_nodelete_mappings.

Test elf/tst-link-map-contiguous-ldso iterates over the loader
image, reading every word to make sure memory is actually mapped.
It only does that if the l_contiguous flag is set for the link map.
Otherwise, it finds gaps with mmap and checks that _dl_find_object
does not return the ld.so mapping for them.

The test elf/tst-link-map-contiguous-main does the same thing for
the libc.so shared object.  This only works if the kernel loaded
the main program because the glibc dynamic loader may fill
the gaps with PROT_NONE mappings in some cases, making it contiguous,
but accesses to individual words may still fault.

Test elf/tst-link-map-contiguous-libc is again slightly different
because the dynamic loader always fills the gaps with PROT_NONE
mappings, so a different form of probing has to be used.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 20681be149)
2025-08-14 08:33:55 +02:00
Florian Weimer 64488b4b31 elf: Extract rtld_setup_phdr function from dl_main
Remove historic binutils reference from comment and update
how this data is used by applications.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 2cac9559e0)
2025-08-14 08:33:23 +02:00
Florian Weimer 9833fcf7ce elf: Do not add a copy of _dl_find_object to libc.so
This reduces code size and dependencies on ld.so internals from
libc.so.

Fixes commit f4c142bb9f
("arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 96429bcc91)
2025-08-14 08:33:23 +02:00
Adhemerval Zanella fbade65338 arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)
Instead of __dl_iterate_phdr. On ARM dlfo_eh_frame/dlfo_eh_count
maps to PT_ARM_EXIDX vaddr start / length.

On a Neoverse N1 machine with 160 cores, the following program:

  $ cat test.c
  #include <stdlib.h>
  #include <pthread.h>
  #include <assert.h>

  enum {
    niter = 1024,
    ntimes = 128,
  };

  static void *
  tf (void *arg)
  {
    int a = (int) arg;

    for (int i = 0; i < niter; i++)
      {
        void *p[ntimes];
        for (int j = 0; j < ntimes; j++)
  	p[j] = malloc (a * 128);
        for (int j = 0; j < ntimes; j++)
  	free (p[j]);
      }

    return NULL;
  }

  int main (int argc, char *argv[])
  {
    enum { nthreads = 16 };
    pthread_t t[nthreads];

    for (int i = 0; i < nthreads; i ++)
      assert (pthread_create (&t[i], NULL, tf, (void *) i) == 0);

    for (int i = 0; i < nthreads; i++)
      {
        void *r;
        assert (pthread_join (t[i], &r) == 0);
        assert (r == NULL);
      }

    return 0;
  }
  $ arm-linux-gnueabihf-gcc -fsanitize=address test.c -o test

Improves from ~15s to 0.5s.

Checked on arm-linux-gnueabihf.

(cherry picked from commit f4c142bb9f)
2025-08-14 08:33:18 +02:00
Luna Lamb 392e6cf1e8 AArch64: Improve codegen in SVE log1p
Improves memory access, reformat evaluation scheme to pack coefficients.
5% improvement in throughput microbenchmark on Neoverse V1.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit da196e6134)
2025-08-11 15:38:19 +00:00
Dylan Fleming 3a78a276a3 AArch64: Optimize inverse trig functions
Improve performance of Inverse trig functions by altering how coefficients are
loaded.

Performance improvement on Neoverse V1:
SVE     acos   14%
AdvSIMD acos   6%

AdvSIMD asin   6%
SVE     asin   5%
AdvSIMD asinf  2%

AdvSIMD atanf  22%
SVE     atanf  20%
SVE     atan   11%
AdvSIMD atan   5%

SVE     atan2  7%
SVE     atan2f 4%
AdvSIMD atan2f 3%
AdvSIMD atan2  2%

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 1e84509e00)
2025-08-11 15:38:06 +00:00
Wilco Dijkstra b6ea8902a7 AArch64: Avoid memset ifunc in cpu-features.c [BZ #33112]
During early startup memcpy or memset must not be called since many targets
use ifuncs for them which won't be initialized yet.  Security hardening may
use -ftrivial-auto-var-init=zero which inserts calls to memset.  Redirect
memset to memset_generic by including dl-symbol-redir-ifunc.h in cpu-features.c.
This fixes BZ #33112.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 681a24ae4d)
2025-08-11 15:12:11 +00:00
Florian Weimer b027d5b145 posix: Fix double-free after allocation failure in regcomp (bug 33185)
If a memory allocation failure occurs during bracket expression
parsing in regcomp, a double-free error may result.

Reported-by: Anastasia Belova <abelova@astralinux.ru>
Co-authored-by: Paul Eggert <eggert@cs.ucla.edu>
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
(cherry picked from commit 7ea06e9940)
2025-07-24 09:22:08 +02:00
Florian Weimer cff1042cce Fix error reporting (false negatives) in SGID tests
And simplify the interface of support_capture_subprogram_self_sgid.

Use the existing framework for temporary directories (now with
mode 0700) and directory/file deletion.  Handle all execution
errors within support_capture_subprogram_self_sgid.  In particular,
this includes test failures because the invoked program did not
exit with exit status zero.  Existing tests that expect exit
status 42 are adjusted to use zero instead.

In addition, fix callers not to call exit (0) with test failures
pending (which may mask them, especially when running with --direct).

Fixes commit 35fc356fa3
("elf: Fix subprocess status handling for tst-dlopen-sgid (bug 32987)").

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3a3fb2ed83)
2025-06-20 10:55:29 +02:00
Florian Weimer 1924d341c0 support: Pick group in support_capture_subprogram_self_sgid if UID == 0
When running as root, it is likely that we can run under any group.
Pick a harmless group from /etc/group in this case.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 2f769cec44)
2025-06-20 10:55:26 +02:00
Carlos O'Donell 06a70769fd ppc64le: Revert "powerpc: Optimized strcmp for power10" (CVE-2025-5702)
This reverts commit 3367d8e180

Reason for revert: Power10 strcmp clobbers non-volatile vector
registers (Bug 33056)

Tested on ppc64le without regression.

(cherry picked from commit 15808c77b3)
2025-06-17 07:28:38 -04:00
Carlos O'Donell 3875045da5 ppc64le: Revert "powerpc : Add optimized memchr for POWER10" (Bug 33059)
This reverts commit b9182c793c

Reason for revert: Power10 memchr clobbers v20 vector register
(Bug 33059)

This is not a security issue, unlike CVE-2025-5745 and
CVE-2025-5702.

Tested on ppc64le without regression.

(cherry picked from commit a7877bb668)
2025-06-17 07:26:23 -04:00
Carlos O'Donell c6240a11f7 ppc64le: Revert "powerpc: Fix performance issues of strcmp power10" (CVE-2025-5702)
This reverts commit 90bcc8721e

This change is in the chain of the final revert that fixes the CVE
i.e. 3367d8e180

Reason for revert: Power10 strcmp clobbers non-volatile vector
registers (Bug 33056)

Tested on ppc64le with no regressions.

(cherry picked from commit c22de63588)
2025-06-17 07:23:13 -04:00
Florian Weimer 2caef2827f elf: Fix subprocess status handling for tst-dlopen-sgid (bug 32987)
This should really move into support_capture_subprogram_self_sgid.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 35fc356fa3)
2025-05-21 08:54:20 +02:00
Sunil K Pandey 9e25c0f445 x86_64: Fix typo in ifunc-impl-list.c.
Fix wcsncpy and wcpncpy typo in ifunc-impl-list.c.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit f2aeb6ff94)
2025-05-20 16:49:32 -07:00
Florian Weimer ca99d55315 elf: Test case for bug 32976 (CVE-2025-4802)
Check that LD_LIBRARY_PATH is ignored for AT_SECURE statically
linked binaries, using support_capture_subprogram_self_sgid.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit d8f7a79335)
2025-05-20 19:52:02 +02:00
Florian Weimer 71ddb11ccd support: Add support_record_failure_barrier
This can be used to stop execution after a TEST_COMPARE_BLOB
failure, for example.

(cherry picked from commit d0b8aa6de4)
2025-05-20 19:52:02 +02:00
Florian Weimer abdeb4b520 support: Use const char * argument in support_capture_subprogram_self_sgid
The function does not modify the passed-in string, so make this clear
via the prototype.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit f0c09fe616)
2025-05-20 19:52:02 +02:00
Florian Weimer 147bed0a71 elf: Keep using minimal malloc after early DTV resize (bug 32412)
If an auditor loads many TLS-using modules during startup, it is
possible to trigger DTV resizing.  Previously, the DTV was marked
as allocated by the main malloc afterwards, even if the minimal
malloc was still in use.  With this change, _dl_resize_dtv marks
the resized DTV as allocated with the minimal malloc.

The new test reuses TLS-using modules from other auditing tests.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit aa3d7bd529)
2025-05-16 16:52:54 +02:00
H.J. Lu 4e5ee49a43 sysdeps/unix/sysv/linux/x86_64/Makefile: Add the end marker
Add the end marker to tests, tests-container and modules-names.

(cherry picked from commit e6350be7e9)
2025-05-14 16:24:59 +02:00
H.J. Lu 37b30b6a68 sysdeps/x86_64/Makefile (tests): Add the end marker
(cherry picked from commit 71d133c500)
2025-05-14 16:24:59 +02:00
H.J. Lu 9fe51d34bb sort-makefile-lines.py: Allow '_' in name and "^# name"
'_' is used in Makefile variable names and many variables end with
"^# name".  Relax sort-makefile-lines.py to allow '_' in name and
"^# name" as variable end.  This fixes BZ #31385.

(cherry picked from commit 6a2512bf16)
2025-05-14 16:24:59 +02:00
Arjun Shankar 14ec225d85 libio: Correctly link tst-popen-fork against libpthread
tst-popen-fork failed to build for Hurd due to not being linked with
libpthread.  This commit fixes that.

Tested with build-many-glibcs.py for i686-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 6a290b2895)
2025-05-14 16:24:59 +02:00
Arjun Shankar 1dcfb9479d libio: Fix a deadlock after fork in popen
popen modifies its file handler book-keeping under a lock that wasn't
being taken during fork.  This meant that a concurrent popen and fork
could end up copying the lock in a "locked" state into the fork child,
where subsequently calling popen would lead to a deadlock due to the
already (spuriously) held lock.

This commit fixes the deadlock by appropriately taking the lock before
fork, and releasing/resetting it in the parent/child after the fork.

A new test for concurrent popen and fork is also added.  It consistently
hangs (and therefore fails via timeout) without the fix applied.
Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 9f0d2c0ee6)
2025-05-14 16:24:58 +02:00
H.J. Lu e31ac9a639 libio: Sort test variables in Makefile
Sort test variables in libio/Makefile using scripts/sort-makefile-lines.py.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>

(cherry picked from commit ddf71c550a)
2025-05-14 16:24:58 +02:00
Florian Weimer 68f3f1a1d0 Linux: Switch back to assembly syscall wrapper for prctl (bug 29770)
Commit ff026950e2 ("Add a C wrapper for
prctl [BZ #25896]") replaced the assembler wrapper with a C function.
However, on powerpc64le-linux-gnu, the C variadic function
implementation requires extra work in the caller to set up the
parameter save area.  Calling a function that needs a parameter save
area without one (because the prototype used indicates the function is
not variadic) corrupts the caller's stack.   The Linux manual pages
project documents prctl as a non-variadic function.  This has resulted
in various projects over the years using non-variadic prototypes,
including the sanitizer libraries in LLVm and GCC (GCC PR 113728).

This commit switches back to the assembler implementation on most
targets and only keeps the C implementation for x86-64 x32.

Also add the __prctl_time64 alias from commit
b39ffab860 ("Linux: Add time64 alias for
prctl") to sysdeps/unix/sysv/linux/syscalls.list; it was not yet
present in commit ff026950e2.

This restores the old ABI on powerpc64le-linux-gnu, thus fixing
bug 29770.

Reviewed-By: Simon Chopin <simon.chopin@canonical.com>
(cherry picked from commit 6a04404521)
2025-05-12 13:20:44 +02:00
Florian Weimer d33d10642f nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions (bug 32786)
The new initializer and struct layout does not initialize the
__g_signals field in the old struct layout before the change in
commit c36fc50781 ("nptl: Remove
g_refs from condition variables").  Bring back fields at the end
of struct __pthread_cond_s, so that they are again zero-initialized.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit dbc5a50d12)
2025-04-29 13:26:36 -04:00
Malte Skarupke b1eb369aee nptl: Use all of g1_start and g_signals
The LSB of g_signals was unused. The LSB of g1_start was used to indicate
which group is G2. This was used to always go to sleep in pthread_cond_wait
if a waiter is in G2. A comment earlier in the file says that this is not
correct to do:

 "Waiters cannot determine whether they are currently in G2 or G1 -- but they
  do not have to because all they are interested in is whether there are
  available signals"

I either would have had to update the comment, or get rid of the check. I
chose to get rid of the check. In fact I don't quite know why it was there.
There will never be available signals for group G2, so we didn't need the
special case. Even if there were, this would just be a spurious wake. This
might have caught some cases where the count has wrapped around, but it
wouldn't reliably do that, (and even if it did, why would you want to force a
sleep in that case?) and we don't support that many concurrent waiters
anyway. Getting rid of it allows us to use one more bit, making us more
robust to wraparound.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 91bb902f58)
2025-04-29 13:26:29 -04:00
Malte Skarupke ac5da3c0e4 nptl: rename __condvar_quiesce_and_switch_g1
This function no longer waits for threads to leave g1, so rename it to
__condvar_switch_g1

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 4b79e27a50)
2025-04-29 13:26:23 -04:00
Malte Skarupke 2fdc0afd07 nptl: Fix indentation
In my previous change I turned a nested loop into a simple loop. I'm doing
the resulting indentation changes in a separate commit to make the diff on
the previous commit easier to review.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit ee6c14ed59)
2025-04-29 13:26:18 -04:00
Malte Skarupke 582c99b2c0 nptl: Use a single loop in pthread_cond_wait instaed of a nested loop
The loop was a little more complicated than necessary. There was only one
break statement out of the inner loop, and the outer loop was nearly empty.
So just remove the outer loop, moving its code to the one break statement in
the inner loop. This allows us to replace all gotos with break statements.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 929a4764ac)
2025-04-29 13:26:12 -04:00
Malte Skarupke fc2a25417d nptl: Remove g_refs from condition variables
This variable used to be needed to wait in group switching until all sleepers
have confirmed that they have woken. This is no longer needed. Nothing waits
on this variable so there is no need to track how many threads are currently
asleep in each group.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit c36fc50781)
2025-04-29 13:26:06 -04:00
Malte Skarupke 6f5ba03968 nptl: Remove unnecessary quadruple check in pthread_cond_wait
pthread_cond_wait was checking whether it was in a closed group no less than
four times. Checking once is enough. Here are the four checks:

1. While spin-waiting. This was dead code: maxspin is set to 0 and has been
   for years.
2. Before deciding to go to sleep, and before incrementing grefs: I kept this
3. After incrementing grefs. There is no reason to think that the group would
   close while we do an atomic increment. Obviously it could close at any
   point, but that doesn't mean we have to recheck after every step. This
   check was equally good as check 2, except it has to do more work.
4. When we find ourselves in a group that has a signal. We only get here after
   we check that we're not in a closed group. There is no need to check again.
   The check would only have helped in cases where the compare_exchange in the
   next line would also have failed. Relying on the compare_exchange is fine.

Removing the duplicate checks clarifies the code.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 4f7b051f8e)
2025-04-29 13:25:59 -04:00
Malte Skarupke d0da34ad30 nptl: Remove unnecessary catch-all-wake in condvar group switch
This wake is unnecessary. We only switch groups after every sleeper in a group
has been woken. Sure, they may take a while to actually wake up and may still
hold a reference, but waking them a second time doesn't speed that up. Instead
this just makes the code more complicated and may hide problems.

In particular this safety wake wouldn't even have helped with the bug that was
fixed by Barrus' patch: The bug there was that pthread_cond_signal would not
switch g1 when it should, so we wouldn't even have entered this code path.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit b42cc6af11)
2025-04-29 13:25:53 -04:00
Malte Skarupke ea13a35e37 nptl: Update comments and indentation for new condvar implementation
Some comments were wrong after the most recent commit. This fixes that.

Also fixing indentation where it was using spaces instead of tabs.

Signed-off-by: Malte Skarupke <malteskarupke@fastmail.fm>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 0cc973160c)
2025-04-29 13:25:47 -04:00
Frank Barrus 2451ef5c4a pthreads NPTL: lost wakeup fix 2
This fixes the lost wakeup (from a bug in signal stealing) with a change
in the usage of g_signals[] in the condition variable internal state.
It also completely eliminates the concept and handling of signal stealing,
as well as the need for signalers to block to wait for waiters to wake
up every time there is a G1/G2 switch.  This greatly reduces the average
and maximum latency for pthread_cond_signal.

The g_signals[] field now contains a signal count that is relative to
the current g1_start value.  Since it is a 32-bit field, and the LSB is
still reserved (though not currently used anymore), it has a 31-bit value
that corresponds to the low 31 bits of the sequence number in g1_start.
(since g1_start also has an LSB flag, this means bits 31:1 in g_signals
correspond to bits 31:1 in g1_start, plus the current signal count)

By making the signal count relative to g1_start, there is no longer
any ambiguity or A/B/A issue, and thus any checks before blocking,
including the futex call itself, are guaranteed not to block if the G1/G2
switch occurs, even if the signal count remains the same.  This allows
initially safely blocking in G2 until the switch to G1 occurs, and
then transitioning from G1 to a new G1 or G2, and always being able to
distinguish the state change.  This removes the race condition and A/B/A
problems that otherwise ocurred if a late (pre-empted) waiter were to
resume just as the futex call attempted to block on g_signal since
otherwise there was no last opportunity to re-check things like whether
the current G1 group was already closed.

By fixing these issues, the signal stealing code can be eliminated,
since there is no concept of signal stealing anymore.  The code to block
for all waiters to exit g_refs can also be removed, since any waiters
that are still in the g_refs region can be guaranteed to safely wake
up and exit.  If there are still any left at this time, they are all
sent one final futex wakeup to ensure that they are not blocked any
longer, but there is no need for the signaller to block and wait for
them to wake up and exit the g_refs region.

The signal count is then effectively "zeroed" but since it is now
relative to g1_start, this is done by advancing it to a new value that
can be observed by any pending blocking waiters.  Any late waiters can
always tell the difference, and can thus just cleanly exit if they are
in a stale G1 or G2.  They can never steal a signal from the current
G1 if they are not in the current G1, since the signal value that has
to match in the cmpxchg has the low 31 bits of the g1_start value
contained in it, and that's first checked, and then it won't match if
there's a G1/G2 change.

Note: the 31-bit sequence number used in g_signals is designed to
handle wrap-around when checking the signal count, but if the entire
31-bit wraparound (2 billion signals) occurs while there is still a
late waiter that has not yet resumed, and it happens to then match
the current g1_start low bits, and the pre-emption occurs after the
normal "closed group" checks (which are 64-bit) but then hits the
futex syscall and signal consuming code, then an A/B/A issue could
still result and cause an incorrect assumption about whether it
should block.  This particular scenario seems unlikely in practice.
Note that once awake from the futex, the waiter would notice the
closed group before consuming the signal (since that's still a 64-bit
check that would not be aliased in the wrap-around in g_signals),
so the biggest impact would be blocking on the futex until the next
full wakeup from a G1/G2 switch.

Signed-off-by: Frank Barrus <frankbarrus_sw@shaggy.cc>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 1db84775f8)
2025-04-29 13:25:40 -04:00
H.J. Lu 3463100f2d x86: Detect Intel Diamond Rapids
Detect Intel Diamond Rapids and tune it similar to Intel Granite Rapids.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit de14f1959e)
2025-04-14 08:56:31 -07:00
Sunil K Pandey e09436c2cb x86: Handle unknown Intel processor with default tuning
Enable default tuning for unknown Intel processor.

Tested on x86, no regression.

Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 9f0deff558)
2025-04-14 08:56:20 -07:00
Sunil K Pandey 7620d98186 x86: Add ARL/PTL/CWF model detection support
- Add ARROWLAKE model detection.
- Add PANTHERLAKE model detection.
- Add CLEARWATERFOREST model detection.

Intel® Architecture Instruction Set Extensions Programming Reference
https://cdrdv2.intel.com/v1/dl/getContent/671368 Section 1.2.

No regression, validated model detection on SDE.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit e53eb952b9)
2025-04-14 08:56:08 -07:00
Sunil K Pandey 765ff3d0d4 x86: Optimize xstate size calculation
Scan xstate IDs up to the maximum supported xstate ID.  Remove the
separate AMX xstate calculation.  Instead, exclude the AMX space from
the start of TILECFG to the end of TILEDATA in xsave_state_size.

Completed validation on SKL/SKX/SPR/SDE and compared xsave state size
with "ld.so --list-diagnostics" option, no regression.

Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit 70b6488551)
2025-04-14 08:55:55 -07:00
Noah Goldstein 65ae73be01 x86: Use Avoid_Non_Temporal_Memset to control non-temporal path
This is just a refactor and there should be no behavioral change from
this commit.

The goal is to make `Avoid_Non_Temporal_Memset` a more universal knob
for controlling whether we use non-temporal memset rather than having
extra logic based on vendor.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit b93dddfaf4)
2025-04-14 08:55:41 -07:00
Florian Weimer 2be36448c4 x86: Tunables may incorrectly set Prefer_PMINUB_for_stringop (bug 32047)
Fixes commit 5bcf6265f2 ("x86:
Disable non-temporal memset on Skylake Server").

Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 7a630f7d33)
2025-04-14 08:54:48 -07:00
Noah Goldstein bde201e92c x86: Disable non-temporal memset on Skylake Server
The original commit enabling non-temporal memset on Skylake Server had
erroneous benchmarks (actually done on ICX).

Further benchmarks indicate non-temporal stores may in fact by a
regression on Skylake Server.

This commit may be over-cautious in some cases, but should avoid any
regressions for 2.40.

Tested using qemu on all x86_64 cpu arch supported by both qemu +
GLIBC.

Reviewed-by: DJ Delorie <dj@redhat.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 5bcf6265f2)
2025-04-14 08:53:24 -07:00
Noah Goldstein 38a7632f2d x86: Fix value for x86_memset_non_temporal_threshold when it is undesirable
When we don't want to use non-temporal stores for memset, we set
`x86_memset_non_temporal_threshold` to SIZE_MAX.

The current code, however, we using `maximum_non_temporal_threshold`
as the upper bound which is `SIZE_MAX >> 4` so we ended up with a
value of `0`.

Fix is to just use `SIZE_MAX` as the upper bound for when setting the
tunable.
Tested-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5b54a33435)
2025-04-14 08:52:17 -07:00
Joe Damato cc59fa5dbc x86: Enable non-temporal memset tunable for AMD
In commit 46b5e98ef6 ("x86: Add seperate non-temporal tunable for
memset") a tunable threshold for enabling non-temporal memset was added,
but only for Intel hardware.

Since that commit, new benchmark results suggest that non-temporal
memset is beneficial on AMD, as well, so allow this tunable to be set
for AMD.

See:
https://docs.google.com/spreadsheets/d/1opzukzvum4n6-RUVHTGddV6RjAEil4P2uMjjQGLbLcU/edit?usp=sharing
which has been updated to include data using different stategies for
large memset on AMD Zen2, Zen3, and Zen4.

Signed-off-by: Joe Damato <jdamato@fastly.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit bef2a827a5)
2025-04-14 08:51:22 -07:00
Noah Goldstein 0da58e8be0 x86: Add seperate non-temporal tunable for memset
The tuning for non-temporal stores for memset vs memcpy is not always
the same. This includes both the exact value and whether non-temporal
stores are profitable at all for a given arch.

This patch add `x86_memset_non_temporal_threshold`. Currently we
disable non-temporal stores for non Intel vendors as the only
benchmarks showing its benefit have been on Intel hardware.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 46b5e98ef6)
2025-04-14 08:50:58 -07:00
Florian Weimer 837a36c371 x86: Link tst-gnu2-tls2-x86-noxsave{,c,xsavec} with libpthread
This fixes a test build failure on Hurd.

Fixes commit 145097dff1 ("x86: Use separate
variable for TLSDESC XSAVE/XSAVEC state size (bug 32810)").

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit c6e2895695)
2025-03-31 21:34:44 +02:00
Florian Weimer 87ab0c7f7f x86: Use separate variable for TLSDESC XSAVE/XSAVEC state size (bug 32810)
Previously, the initialization code reused the xsave_state_full_size
member of struct cpu_features for the TLSDESC state size.  However,
the tunable processing code assumes that this member has the
original XSAVE (non-compact) state size, so that it can use its
value if XSAVEC is disabled via tunable.

This change uses a separate variable and not a struct member because
the value is only needed in ld.so and the static libc, but not in
libc.so.  As a result, struct cpu_features layout does not change,
helping a future backport of this change.

Fixes commit 9b7091415a ("x86-64:
Update _dl_tlsdesc_dynamic to preserve AMX registers").

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 145097dff1)
2025-03-29 10:19:17 +01:00
Florian Weimer 60cd7123a6 x86: Skip XSAVE state size reset if ISA level requires XSAVE
If we have to use XSAVE or XSAVEC trampolines, do not adjust the size
information they need.  Technically, it is an operator error to try to
run with -XSAVE,-XSAVEC on such builds, but this change here disables
some unnecessary code with higher ISA levels and simplifies testing.

Related to commit befe2d3c4d
("x86-64: Don't use SSE resolvers for ISA level 3 or above").

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 59585ddaa2)
2025-03-29 10:19:17 +01:00
Sunil K Pandey 4cf3f9df54 x86_64: Add atanh with FMA
On SPR, it improves atanh bench performance by:

			Before		After		Improvement
reciprocal-throughput	15.1715		14.8628		2%
latency			57.1941		56.1883		2%

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c7c4a5906f)
2025-03-19 17:33:32 -07:00
Sunil K Pandey 01ed435e2e x86_64: Add sinh with FMA
On SPR, it improves sinh bench performance by:

			Before		After		Improvement
reciprocal-throughput	14.2017		11.815		17%
latency			36.4917		35.2114		4%

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit dded0d20f6)
2025-03-19 17:33:13 -07:00
Sunil K Pandey 0edcc77fe7 x86_64: Add tanh with FMA
On Skylake, it improves tanh bench performance by:

	Before 		After 		Improvement
max	110.89		95.826		14%
min	20.966		20.157		4%
mean	30.9601		29.8431		4%

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c6352111c7)
2025-03-19 17:32:59 -07:00
H.J. Lu 7ecf0d3bde x86-64: Exclude FMA4 IFUNC functions for -mapxf
When -mapxf is used to build glibc, the resulting glibc will never run
on FMA4 machines.  Exclude FMA4 IFUNC functions when -mapxf is used.
This requires GCC which defines __APX_F__ for -mapxf with commit:

1df56719bd8 x86: Define __APX_F__ for -mapxf

Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit 9e1f4aef86)
2025-03-19 17:30:18 -07:00
Michael Jeanson e1fe22368e nptl: clear the whole rseq area before registration
Due to the extensible nature of the rseq area we can't explictly
initialize fields that are not part of the ABI yet. It was agreed with
upstream that all new fields will be documented as zero initialized by
userspace. Future kernels configured with CONFIG_DEBUG_RSEQ will
validate the content of all fields during registration.

Replace the explicit field initialization with a memset of the whole
rseq area which will cover fields as they are added to future kernels.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 689a62a421)
2025-03-12 19:34:12 +00:00
Wilco Dijkstra dd8c0c3bbd math: Improve layout of exp/exp10 data
GCC aligns global data to 16 bytes if their size is >= 16 bytes.  This patch
changes the exp_data struct slightly so that the fields are better aligned
and without gaps.  As a result on targets that support them, more load-pair
instructions are used in exp.  Exp10 is improved by moving invlog10_2N later
so that neglog10_2hiN and neglog10_2loN can be loaded using load-pair.

The exp benchmark improves 2.5%, "144bits" by 7.2%, "768bits" by 12.7% on
Neoverse V2.  Exp10 improves by 1.5%.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 5afaf99edb)
2025-02-28 14:32:28 +00:00
Wilco Dijkstra a1b09e59e2 AArch64: Use prefer_sve_ifuncs for SVE memset
Use prefer_sve_ifuncs for SVE memset just like memcpy.

Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
(cherry picked from commit 0f044be1da)
2025-02-28 14:32:28 +00:00
Wilco Dijkstra d0e2133470 AArch64: Add SVE memset
Add SVE memset based on the generic memset with predicated load for sizes < 16.
Unaligned memsets of 128-1024 are improved by ~20% on average by using aligned
stores for the last 64 bytes.  Performance of random memset benchmark improves
by ~2% on Neoverse V1.

Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
(cherry picked from commit 163b1bbb76)
2025-02-28 14:32:24 +00:00
Wilco Dijkstra 0cc12d9c47 math: Improve layout of expf data
GCC aligns global data to 16 bytes if their size is >= 16 bytes.  This patch
changes the exp2f_data struct slightly so that the fields are better aligned.
As a result on targets that support them, load-pair instructions accessing
poly_scaled and invln2_scaled are now 16-byte aligned.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 44fa9c1080)
2025-02-28 14:31:33 +00:00
Wilco Dijkstra 0cd10047bf AArch64: Remove zva_128 from memset
Remove ZVA 128 support from memset - the new memset no longer
guarantees count >= 256, which can result in underflow and a
crash if ZVA size is 128 ([1]).  Since only one CPU uses a ZVA
size of 128 and its memcpy implementation was removed in commit
e162ab2bf1, remove this special
case too.

[1] https://sourceware.org/pipermail/libc-alpha/2024-November/161626.html

Reviewed-by: Andrew Pinski <quic_apinski@quicinc.com>
(cherry picked from commit a08d9a52f9)
2025-02-28 14:31:33 +00:00
Wilco Dijkstra dd1e63ab58 AArch64: Optimize memset
Improve small memsets by avoiding branches and use overlapping stores.
Use DC ZVA for copies over 128 bytes.  Remove unnecessary code for ZVA sizes
other than 64 and 128.  Performance of random memset benchmark improves by 24%
on Neoverse N1.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit cec3aef324)
2025-02-28 14:31:33 +00:00
Wilco Dijkstra 65a96a6f2b AArch64: Improve generic strlen
Improve performance by handling another 16 bytes before entering the loop.
Use ADDHN in the loop to avoid SHRN+FMOV when it terminates.  Change final
size computation to avoid increasing latency.  On Neoverse V1 performance
of the random strlen benchmark improves by 4.6%.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 3dc426b642)
2025-02-28 14:31:33 +00:00
Yat Long Poon 4073e4ee2c AArch64: Improve codegen for SVE logs
Reduce memory access by using lanewise MLA and moving constants to struct
and reduce number of MOVPRFXs.
Update maximum ULP error for double log_sve from 1 to 2.
Speedup on Neoverse V1 for log (3%), log2 (5%), and log10 (4%).

(cherry picked from commit 32d193a372)
2025-02-27 17:52:45 +00:00
Luna Lamb 78abd3ef6e AArch64: Improve codegen in SVE tans
Improves memory access.
Tan: MOVPRFX 7 -> 2, LD1RD 12 -> 5, move MOV away from return.
Tanf: MOV 2 -> 1, MOVPRFX 6 -> 3, LD1RW 5 -> 4, move mov away from return.

(cherry picked from commit aa6609feb2)
2025-02-27 17:52:35 +00:00
Joana Cruz a10183b633 AArch64: Improve codegen of AdvSIMD atan(2)(f)
Load the polynomial evaluation coefficients into 2 vectors and use lanewise MLAs.
8% improvement in throughput microbenchmark on Neoverse V1.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 6914774b9d)
2025-02-27 17:51:54 +00:00
Joana Cruz dcd1229e5b AArch64: Improve codegen of AdvSIMD logf function family
Load the polynomial evaluation coefficients into 2 vectors and use lanewise MLAs.
8% improvement in throughput microbenchmark on Neoverse V1 for log2 and log,
and 2% for log10.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit d6e034f5b2)
2025-02-27 17:51:27 +00:00
Pierre Blanchard 72156cb90b AArch64: Improve codegen in AdvSIMD logs
Remove spurious ADRP and a few MOVs.
Reduce memory access by using more indexed MLAs in polynomial.
Align notation so that algorithms are easier to compare.
Speedup on Neoverse V1 for log10 (8%), log (8.5%), and log2 (10%).
Update error threshold in AdvSIMD log (now matches SVE log).

(cherry picked from commit 8eb5ad2ebc)
2025-02-27 17:51:10 +00:00
Joe Ramsay 5e354bf4e2 AArch64: Simplify rounding-multiply pattern in several AdvSIMD routines
This operation can be simplified to use simpler multiply-round-convert
sequence, which uses fewer instructions and constants.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 16a59571e4)
2025-02-27 17:50:30 +00:00
Joe Ramsay 80df456112 aarch64: Avoid redundant MOVs in AdvSIMD F32 logs
Since the last operation is destructive, the first argument to the FMA
also has to be the first argument to the special-case in order to
avoid unnecessary MOVs. Reorder arguments and adjust special-case
bounds to facilitate this.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 8b09af572b)
2025-02-27 17:38:52 +00:00
Joe Ramsay d591876303 aarch64: Fix AdvSIMD libmvec routines for big-endian
Previously many routines used * to load from vector types stored
in the data table. This is emitted as ldr, which byte-swaps the
entire vector register, and causes bugs for big-endian when not
all lanes contain the same value. When a vector is to be used
this way, it has been replaced with an array and the load with an
explicit ld1 intrinsic, which byte-swaps only within lanes.

As well, many routines previously used non-standard GCC syntax
for vector operations such as indexing into vectors types with []
and assembling vectors using {}. This syntax should not be mixed
with ACLE, as the former does not respect endianness whereas the
latter does. Such examples have been replaced with, for instance,
vcombine_* and vgetq_lane* intrinsics. Helpers which only use the
GCC syntax, such as the v_call helpers, do not need changing as
they do not use intrinsics.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 90a6ca8b28)
2025-02-27 17:36:50 +00:00
Siddhesh Poyarekar f6d48470ae assert: Add test for CVE-2025-0395
Use the __progname symbol to override the program name to induce the
failure that CVE-2025-0395 describes.

This is related to BZ #32582

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit cdb9ba8419)
2025-02-13 12:54:51 -05:00
H.J. Lu 662516aca8 stdlib: Test using setenv with updated environ [BZ #32588]
Add a test for setenv with updated environ.  Verify that BZ #32588 is
fixed.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 8ab34497de)
2025-01-25 10:23:44 +08:00
Sam James 1432850ad8 malloc: obscure calloc use in tst-calloc
Similar to a9944a52c9 and
f9493a15ea, we need to hide calloc use from
the compiler to accommodate GCC's r15-6566-g804e9d55d9e54c change.

First, include tst-malloc-aux.h, but then use `volatile` variables
for size.

The test passes without the tst-malloc-aux.h change but IMO we want
it there for consistency and to avoid future problems (possibly silent).

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c3d1dac96b)
2025-01-24 01:11:01 +00:00
H.J. Lu c1f7bfbe08 Hide all malloc functions from compiler [BZ #32366]
Since -1 isn't a power of two, compiler may reject it, hide memalign from
Clang 19 which issues an error:

tst-memalign.c:86:31: error: requested alignment is not a power of 2 [-Werror,-Wnon-power-of-two-alignment]
   86 |   p = memalign (-1, pagesize);
      |                 ^~
tst-memalign.c:86:31: error: requested alignment must be 4294967296 bytes or smaller; maximum alignment assumed [-Werror,-Wbuiltin-assume-aligned-alignment]
   86 |   p = memalign (-1, pagesize);
      |                 ^~

Update tst-malloc-aux.h to hide all malloc functions and include it in
all malloc tests to prevent compiler from optimizing out any malloc
functions.

Tested with Clang 19.1.5 and GCC 15 20241206 for BZ #32366.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit f9493a15ea)
2025-01-24 01:10:55 +00:00
Siddhesh Poyarekar 808a84a8b8 Fix underallocation of abort_msg_s struct (CVE-2025-0395)
Include the space needed to store the length of the message itself, in
addition to the message string.  This resolves BZ #32582.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 68ee0f704c)
2025-01-22 17:08:33 +01:00
Noah Goldstein 994b129a35 x86/string: Fixup alignment of main loop in str{n}cmp-evex [BZ #32212]
The loop should be aligned to 32-bytes so that it can ideally run out
the DSB. This is particularly important on Skylake-Server where
deficiencies in it's DSB implementation make it prone to not being
able to run loops out of the DSB.

For example running strcmp-evex on 200Mb string:

32-byte aligned loop:
    - 43,399,578,766      idq.dsb_uops
not 32-byte aligned loop:
    - 6,060,139,704       idq.dsb_uops

This results in a 25% performance degradation for the non-aligned
version.

The fix is to just ensure the code layout is such that the loop is
aligned. (Which was previously the case but was accidentally dropped
in 84e7c46df).

NB: The fix was actually 64-byte alignment. This is because 64-byte
alignment generally produces more stable performance than 32-byte
aligned code (cache line crosses can affect perf), so if we are going
past 16-byte alignmnent, might as well go to 64. 64-byte alignment
also matches most other functions we over-align, so it creates a
common point of optimization.

Times are reported as ratio of Time_With_Patch /
Time_Without_Patch. Lower is better.

The values being reported is the geometric mean of the ratio across
all tests in bench-strcmp and bench-strncmp.

Note this patch is only attempting to improve the Skylake-Server
strcmp for long strings. The rest of the numbers are only to test for
regressions.

Tigerlake Results Strings <= 512:
    strcmp : 1.026
    strncmp: 0.949

Tigerlake Results Strings > 512:
    strcmp : 0.994
    strncmp: 0.998

Skylake-Server Results Strings <= 512:
    strcmp : 0.945
    strncmp: 0.943

Skylake-Server Results Strings > 512:
    strcmp : 0.778
    strncmp: 1.000

The 2.6% regression on TGL-strcmp is due to slowdowns caused by
changes in alignment of code handling small sizes (most on the
page-cross logic). These should be safe to ignore because 1) We
previously only 16-byte aligned the function so this behavior is not
new and was essentially up to chance before this patch and 2) this
type of alignment related regression on small sizes really only comes
up in tight micro-benchmark loops and is unlikely to have any affect
on realworld performance.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 483443d321)
2025-01-08 16:02:00 -08:00
Noah Goldstein 61daaa7639 x86: Improve large memset perf with non-temporal stores [RHEL-29312]
Previously we use `rep stosb` for all medium/large memsets. This is
notably worse than non-temporal stores for large (above a
few MBs) memsets.
See:
https://docs.google.com/spreadsheets/d/1opzukzvum4n6-RUVHTGddV6RjAEil4P2uMjjQGLbLcU/edit?usp=sharing
For data using different stategies for large memset on ICX and SKX.

Using non-temporal stores can be up to 3x faster on ICX and 2x faster
on SKX. Historically, these numbers would not have been so good
because of the zero-over-zero writeback optimization that `rep stosb`
is able to do. But, the zero-over-zero writeback optimization has been
removed as a potential side-channel attack, so there is no longer any
good reason to only rely on `rep stosb` for large memsets. On the flip
size, non-temporal writes can avoid data in their RFO requests saving
memory bandwidth.

All of the other changes to the file are to re-organize the
code-blocks to maintain "good" alignment given the new code added in
the `L(stosb_local)` case.

The results from running the GLIBC memset benchmarks on TGL-client for
N=20 runs:

Geometric Mean across the suite New / Old EXEX256: 0.979
Geometric Mean across the suite New / Old EXEX512: 0.979
Geometric Mean across the suite New / Old AVX2   : 0.986
Geometric Mean across the suite New / Old SSE2   : 0.979

Most of the cases are essentially unchanged, this is mostly to show
that adding the non-temporal case didn't add any regressions to the
other cases.

The results on the memset-large benchmark suite on TGL-client for N=20
runs:

Geometric Mean across the suite New / Old EXEX256: 0.926
Geometric Mean across the suite New / Old EXEX512: 0.925
Geometric Mean across the suite New / Old AVX2   : 0.928
Geometric Mean across the suite New / Old SSE2   : 0.924

So roughly a 7.5% speedup. This is lower than what we see on servers
(likely because clients typically have faster single-core bandwidth so
saving bandwidth on RFOs is less impactful), but still advantageous.

Full test-suite passes on x86_64 w/ and w/o multiarch.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5bf0ab8057)
2025-01-08 15:54:19 -08:00
Florian Weimer 2c8a7f14fa x86: Avoid integer truncation with large cache sizes (bug 32470)
Some hypervisors report 1 TiB L3 cache size.  This results
in some variables incorrectly getting zeroed, causing crashes
in memcpy/memmove because invariants are violated.

(cherry picked from commit 61c3450db9)
2024-12-17 18:52:10 +01:00
H.J. Lu 2c882bf9c1 math: Exclude internal math symbols for tests [BZ #32414]
Since internal tests don't have access to internal symbols in libm,
exclude them for internal tests.  Also make tst-strtod5 and tst-strtod5i
depend on $(libm) to support older versions of GCC which can't inline
copysign family functions.  This fixes BZ #32414.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit 5df09b4448)
2024-12-11 12:15:19 -08:00
Sam James 51da74a97e malloc: add indirection for malloc(-like) functions in tests [BZ #32366]
GCC 15 introduces allocation dead code removal (DCE) for PR117370 in
r15-5255-g7828dc070510f8. This breaks various glibc tests which want
to assert various properties of the allocator without doing anything
obviously useful with the allocated memory.

Alexander Monakov rightly pointed out that we can and should do better
than passing -fno-malloc-dce to paper over the problem. Not least because
GCC 14 already does such DCE where there's no testing of malloc's return
value against NULL, and LLVM has such optimisations too.

Handle this by providing malloc (and friends) wrappers with a volatile
function pointer to obscure that we're calling malloc (et. al) from the
compiler.

Reviewed-by: Paul Eggert <eggert@cs.ucla.edu>
(cherry picked from commit a9944a52c9)
2024-12-10 03:02:46 +00:00
H.J. Lu aa8768999e Pass -nostdlib -nostartfiles together with -r [BZ #31753]
Since -r in GCC 6/7/8 doesn't imply -nostdlib -nostartfiles, update the
link-static-libc.out rule to also pass -nostdlib -nostartfiles.  This
fixes BZ #31753.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 2be3352f0b)
2024-12-06 14:27:22 -08:00
Michael Jeanson 350db28393 nptl: initialize cpu_id_start prior to rseq registration
When adding explicit initialization of rseq fields prior to
registration, I glossed over the fact that 'cpu_id_start' is also
documented as initialized by user-space.

While current kernels don't validate the content of this field on
registration, future ones could.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
(cherry picked from commit d9f40387d3)
2024-12-06 15:40:59 +00:00
Michael Jeanson 9a0e174a39 nptl: initialize rseq area prior to registration
Per the rseq syscall documentation, 3 fields are required to be
initialized by userspace prior to registration, they are 'cpu_id',
'rseq_cs' and 'flags'. Since we have no guarantee that 'struct pthread'
is cleared on all architectures, explicitly set those 3 fields prior to
registration.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 97f60abd25)
2024-12-06 15:40:59 +00:00
Florian Weimer dcaf51b41e elf: Change ldconfig auxcache magic number (bug 32231)
In commit c628c22963 (elf: Remove
ldconfig kernel version check), the layout of auxcache entries
changed because the osversion field was removed from
struct aux_cache_file_entry.  However, AUX_CACHEMAGIC was not
changed, so existing files are still used, potentially leading
to unintended ldconfig behavior.  This commit changes AUX_CACHEMAGIC,
so that the file is regenerated.

Reported-by: DJ Delorie <dj@redhat.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 0a536f6e2f)
2024-10-29 09:42:44 +01:00
Joseph Myers b3c51635ef Make tst-strtod-underflow type-generic
The test tst-strtod-underflow covers various edge cases close to the
underflow threshold for strtod (especially cases where underflow on
architectures with after-rounding tininess detection depends on the
rounding mode).  Make it use the type-generic machinery, with
corresponding test inputs for each supported floating-point format, so
that other functions in the strtod family are tested for underflow
edge cases as well.

Tested for x86_64.

(cherry picked from commit 94ca2c0894)
2024-10-18 18:57:47 +02:00
H.J. Lu b74be22f65 Add crt1-2.0.o for glibc 2.0 compatibility tests
Starting from glibc 2.1, crt1.o contains _IO_stdin_used which is checked
by _IO_check_libio to provide binary compatibility for glibc 2.0.  Add
crt1-2.0.o for tests against glibc 2.0.  Define tests-2.0 for glibc 2.0
compatibility tests.  Add and update glibc 2.0 compatibility tests for
stderr, matherr and pthread_kill.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 5f245f3bfb)
2024-10-01 09:45:59 +08:00
Joseph Myers fcdf98f38c Add tests of more strtod special cases
There is very little test coverage of inputs to strtod-family
functions that don't contain anything that can be parsed as a number
(one test of ".y" in tst-strtod2), and none that I can see of skipping
initial whitespace.  Add some tests of these things to tst-strtod2.

Tested for x86_64.

(cherry picked from commit 378039ca57)
2024-09-27 17:25:43 +02:00
Joseph Myers 3edc0f22a6 Add more tests of strtod end pointer
Although there are some tests in tst-strtod2 and tst-strtod3 for the
end pointer provided by strtod when it doesn't parse the whole string,
they aren't very thorough.  Add tests of more such cases to
tst-strtod2.

Tested for x86_64.

(cherry picked from commit b5d3737b30)
2024-09-27 17:25:43 +02:00
Joseph Myers 988de94538 Make tst-strtod2 and tst-strtod5 type-generic
Some of the strtod tests use type-generic machinery in tst-strtod.h to
test the strto* functions for all floating types, while others only
test double even when the tests are in fact meaningful for all
floating types.

Convert tst-strtod2 and tst-strtod5 to use the type-generic machinery
so they test all floating types.  I haven't tried to convert them to
use newer test interfaces in other ways, just made the changes
necessary to use the type-generic machinery.

Tested for x86_64.

(cherry picked from commit 8de031bcb9)
2024-09-27 17:25:43 +02:00
Florian Weimer a2f7087237 powerpc64le: Build new strtod tests with long double ABI flags (bug 32145)
This fixes several test failures:

=====FAIL: stdlib/tst-strtod1i.out=====
Locale tests
all OK
Locale tests
all OK
Locale tests
strtold("1,5") returns -6,38643e+367 and not 1,5
strtold("1.5") returns 1,5 and not 1
strtold("1.500") returns 1 and not 1500
strtold("36.893.488.147.419.103.232") returns 1500 and not 3,68935e+19
Locale tests
all OK

=====FAIL: stdlib/tst-strtod3.out=====
0: got wrong results -2.5937e+4826, expected 0

=====FAIL: stdlib/tst-strtod4.out=====
0: got wrong results -6,38643e+367, expected 0
1: got wrong results 0, expected 1e+06
2: got wrong results 1e+06, expected 10

=====FAIL: stdlib/tst-strtod5i.out=====
0: got wrong results -6,38643e+367, expected 0
2: got wrong results 0, expected -0
4: got wrong results -0, expected 0
5: got wrong results 0, expected -0
6: got wrong results -0, expected 0
7: got wrong results 0, expected -0
8: got wrong results -0, expected 0
9: got wrong results 0, expected -0
10: got wrong results -0, expected 0
11: got wrong results 0, expected -0
12: got wrong results -0, expected 0
13: got wrong results 0, expected -0
14: got wrong results -0, expected 0
15: got wrong results 0, expected -0
16: got wrong results -0, expected 0
17: got wrong results 0, expected -0
18: got wrong results -0, expected 0
20: got wrong results 0, expected -0
22: got wrong results -0, expected 0
23: got wrong results 0, expected -0
24: got wrong results -0, expected 0
25: got wrong results 0, expected -0
26: got wrong results -0, expected 0
27: got wrong results 0, expected -0

Fixes commit 3fc063dee0
("Make __strtod_internal tests type-generic").

Suggested-by: Joseph Myers <josmyers@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit cc3e743fc0)
2024-09-27 17:25:43 +02:00
Joseph Myers 6624318c89 Do not set errno for overflowing NaN payload in strtod/nan (bug 32045)
As reported in bug 32045, it's incorrect for strtod/nan functions to
set errno based on overflowing payload (strtod should only set errno
for overflow / underflow of its actual result, and potentially if
nothing in the string can be parsed as a number at all; nan should be
a pure function that never sets it).  Save and restore errno around
the internal strtoull call and add associated test coverage.

Tested for x86_64.

(cherry picked from commit 64f62c47e9)
2024-09-27 17:25:43 +02:00
Joseph Myers 63bcc01744 Improve NaN payload testing
There are two separate sets of tests of NaN payloads in glibc:

* libm-test-{get,set}payload* verify that getpayload, setpayload,
  setpayloadsig and __builtin_nan functions are consistent in their
  payload handling.

* test-nan-payload verifies that strtod-family functions and the
  not-built-in nan functions are consistent in their payload handling.

Nothing, however, connects the two sets of functions (i.e., verifies
that strtod / nan are consistent with getpayload / setpayload /
__builtin_nan).

Improve test-nan-payload to check actual payload value with getpayload
rather than just verifying that the strtod and nan functions produce
the same NaN.  Also check that the NaNs produced aren't signaling and
extend the tests to cover _FloatN / _FloatNx.

Tested for x86_64.

(cherry picked from commit be77d5ae41)
2024-09-27 17:25:43 +02:00
Joseph Myers 86369c9ee4 Make __strtod_internal tests type-generic
Some of the strtod tests use type-generic machinery in tst-strtod.h to
test the strto* functions for all floating types, while others only
test double even when the tests are in fact meaningful for all
floating types.

Convert the tests of the internal __strtod_internal interface to cover
all floating types.  I haven't tried to convert them to use newer test
interfaces in other ways, just made the changes necessary to use the
type-generic machinery.  As an internal interface, there are no
aliases for different types with the same ABI (however,
__strtold_internal is defined even if long double has the same ABI as
double), so macros used by the type-generic testing code are redefined
as needed to avoid expecting such aliases to be present.

Tested for x86_64.

(cherry picked from commit 3fc063dee0)
2024-09-27 17:25:43 +02:00
Joseph Myers a7be595c67 Fix strtod subnormal rounding (bug 30220)
As reported in bug 30220, the implementation of strtod-family
functions has a bug in the following case: the input string would,
with infinite exponent range, take one more bit to represent than is
available in the normal precision of the return type; the value
represented is in the subnormal range; and there are no nonzero bits
in the value, below those that can be represented in subnormal
precision, other than the least significant bit and possibly the
0.5ulp bit.  In this case, round_and_return ends up discarding the
least significant bit.

Fix by saving that bit to merge into more_bits (it can't be merged in
at the time it's computed, because more_bits mustn't include this bit
in the case of after-rounding tininess detection checking if the
result is still subnormal when rounded to normal precision, so merging
this bit into more_bits needs to take place after that check).

Tested for x86_64.

(cherry picked from commit 457622c2fa)
2024-09-27 17:25:43 +02:00
Joseph Myers 9cfeccf65a More thoroughly test underflow / errno in tst-strtod-round
Add tests of underflow in tst-strtod-round, and thus also test for
errno being unchanged when there is neither overflow nor underflow.
The errno setting before the function call to test for being unchanged
is adjusted to set errno to 12345 instead of 0, so that any bugs where
strtod sets errno to 0 would be detected.

This doesn't add any new test inputs for tst-strtod-round, and in
particular doesn't cover the edge cases of underflow the way
tst-strtod-underflow does (none of the existing test inputs for
tst-strtod-round actually exercise cases that have underflow with
before-rounding tininess detection but not with after-rounding
tininess detection), but at least it provides some coverage (as per
the recent discussions) that ordinary non-overflowing non-underflowing
inputs to these functions do not set errno.

Tested for x86_64.

(cherry picked from commit d73ed2601b)
2024-09-27 17:25:43 +02:00
Joseph Myers 293e4e3c90 Test errno setting on strtod overflow in tst-strtod-round
We have no tests that errno is set to ERANGE on overflow of
strtod-family functions (we do have some tests for underflow, in
tst-strtod-underflow).  Add such tests to tst-strtod-round.

Tested for x86_64.

(cherry picked from commit 207d64feb2)
2024-09-27 17:25:43 +02:00
Joseph Myers d8b4fc3653 Add tests of fread
There seem to be no glibc tests specifically for the fread function.
Add basic tests of that function.

Tested for x86_64.

(cherry picked from commit d14c977c65)
2024-09-26 16:18:59 +02:00
Sergey Kolosov 373aab3e52 stdio-common: Add new test for fdopen
This commit adds fdopen test with all modes.
Reviewed-by: DJ Delorie <dj@redhat.com>

(cherry picked from commit 1d72fa3cfa)
2024-09-26 15:41:42 +02:00
Siddhesh Poyarekar 84f6bfce2c libio: Attempt wide backup free only for non-legacy code
_wide_data and _mode are not available in legacy code, so do not attempt
to free the wide backup buffer in legacy code.

Resolves: BZ #32137 and BZ #27821

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit ae4d44b1d5)
2024-09-11 08:48:53 +02:00
Florian Weimer 4e382ce01c debug: Fix read error handling in pcprofiledump
The reading loops did not check for read failures.  Addresses
a static analysis report.

Manually tested by compiling a program with the GCC's
-finstrument-functions option, running it with
“LD_PRELOAD=debug/libpcprofile.so PCPROFILE_OUTPUT=output-file”,
and reviewing the output of “debug/pcprofiledump output-file”.

(cherry picked from commit 89b088bf70)
2024-09-10 12:41:28 +02:00
Florian Weimer 7f5027995f elf: Fix tst-dlopen-tlsreinit1.out test dependency
Fixes commit 5097cd344f
("elf: Avoid re-initializing already allocated TLS in dlopen
(bug 31717)").

Reported-by: Patsy Griffin <patsy@redhat.com>
Reviewed-by: Patsy Griffin <patsy@redhat.com>
(cherry picked from commit e82a7cb162)
2024-09-09 21:31:34 +02:00
Florian Weimer 27a0c6b490 elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)
The old code used l_init_called as an indicator for whether TLS
initialization was complete.  However, it is possible that
TLS for an object is initialized, written to, and then dlopen
for this object is called again, and l_init_called is not true at
this point.  Previously, this resulted in TLS being initialized
twice, discarding any interim writes (technically introducing a
use-after-free bug even).

This commit introduces an explicit per-object flag, l_tls_in_slotinfo.
It indicates whether _dl_add_to_slotinfo has been called for this
object.  This flag is used to avoid double-initialization of TLS.
In update_tls_slotinfo, the first_static_tls micro-optimization
is removed because preserving the initalization flag for subsequent
use by the second loop for static TLS is a bit complicated, and
another per-object flag does not seem to be worth it.  Furthermore,
the l_init_called flag is dropped from the second loop (for static
TLS initialization) because l_need_tls_init on its own prevents
double-initialization.

The remaining l_init_called usage in resize_scopes and update_scopes
is just an optimization due to the use of scope_has_map, so it is
not changed in this commit.

The isupper check ensures that libc.so.6 is TLS is not reverted.
Such a revert happens if l_need_tls_init is not cleared in
_dl_allocate_tls_init for the main_thread case, now that
l_init_called is not checked anymore in update_tls_slotinfo
in elf/dl-open.c.

Reported-by: Jonathon Anderson <janderson@rice.edu>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 5097cd344f)
2024-09-09 21:31:28 +02:00
Florian Weimer e3d5d2d350 elf: Clarify and invert second argument of _dl_allocate_tls_init
Also remove an outdated comment: _dl_allocate_tls_init is
called as part of pthread_create.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit fe06fb313b)
2024-09-09 21:15:23 +02:00
Florian Weimer 28c4f32f71 elf: Support recursive use of dynamic TLS in interposed malloc
It turns out that quite a few applications use bundled mallocs that
have been built to use global-dynamic TLS (instead of the recommended
initial-exec TLS).  The previous workaround from
commit afe42e935b ("elf: Avoid some
free (NULL) calls in _dl_update_slotinfo") does not fix all
encountered cases unfortunatelly.

This change avoids the TLS generation update for recursive use
of TLS from a malloc that was called during a TLS update.  This
is possible because an interposed malloc has a fixed module ID and
TLS slot.  (It cannot be unloaded.)  If an initially-loaded module ID
is encountered in __tls_get_addr and the dynamic linker is already
in the middle of a TLS update, use the outdated DTV, thus avoiding
another call into malloc.  It's still necessary to update the
DTV to the most recent generation, to get out of the slow path,
which is why the check for recursion is needed.

The bookkeeping is done using a global counter instead of per-thread
flag because TLS access in the dynamic linker is tricky.

All this will go away once the dynamic linker stops using malloc
for TLS, likely as part of a change that pre-allocates all TLS
during pthread_create/dlopen.

Fixes commit d2123d6827 ("elf: Fix slow
tls access after dlopen [BZ #19924]").

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 018f0fc3b8)
2024-09-09 21:15:23 +02:00
Maciej W. Rozycki 5ff30b2f75 nptl: Use <support/check.h> facilities in tst-setuid3
Remove local FAIL macro in favor to FAIL_EXIT1 from <support/check.h>,
which provides equivalent reporting, with the name of the file and the
line number within of the failure site additionally included.  Remove
FAIL_ERR altogether and include ": %m" explicitly with the format string
supplied to FAIL_EXIT1 as there seems little value to have a separate
macro just for this.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 8c98195af6)
2024-08-30 15:28:22 -04:00
Maciej W. Rozycki cae418638e posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64
Remove local FAIL macro in favor to FAIL_RET from <support/check.h>,
which provides equivalent reporting, with the name of the file of the
failure site additionally included, for the tst-truncate-common core
shared between the tst-truncate and tst-truncate64 tests.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit fe47595504)
2024-08-30 15:28:16 -04:00
Siddhesh Poyarekar a500b48bd2 ungetc: Fix backup buffer leak on program exit [BZ #27821]
If a file descriptor is left unclosed and is cleaned up by _IO_cleanup
on exit, its backup buffer remains unfreed, registering as a leak in
valgrind.  This is not strictly an issue since (1) the program should
ideally be closing the stream once it's not in use and (2) the program
is about to exit anyway, so keeping the backup buffer around a wee bit
longer isn't a real problem.  Free it anyway to keep valgrind happy
when the streams in question are the standard ones, i.e. stdout, stdin
or stderr.

Also, the _IO_have_backup macro checks for _IO_save_base,
which is a roundabout way to check for a backup buffer instead of
directly looking for _IO_backup_base.  The roundabout check breaks when
the main get area has not been used and user pushes a char into the
backup buffer with ungetc.  Fix this to use the _IO_backup_base
directly.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3e1d8d1d1d)
2024-08-28 15:58:45 -04:00
Siddhesh Poyarekar 70939528c6 ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]
When ungetc is called on an unused stream, the backup buffer is
allocated without the main get area being present.  This results in
every subsequent ungetc (as the stream remains in the backup area)
checking uninitialized memory in the backup buffer when trying to put a
character back into the stream.

Avoid comparing the input character with buffer contents when in backup
to avoid this uninitialized read.  The uninitialized read is harmless in
this context since the location is promptly overwritten with the input
character, thus fulfilling ungetc functionality.

Also adjust wording in the manual to drop the paragraph that says glibc
cannot do multiple ungetc back to back since with this change, ungetc
can actually do this.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit cdf0f88f97)
2024-08-28 15:58:01 -04:00
Siddhesh Poyarekar f0c308ab23 Make tst-ungetc use libsupport
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3f7df7e757)
2024-08-28 15:58:01 -04:00
Maciej W. Rozycki 3c5f493d87 stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650]
Complement commit b03e4d7bd2 ("stdio: fix vfscanf with matches longer
than INT_MAX (bug 27650)") and add a test case for the issue, inspired
by the reproducer provided with the bug report.

This has been verified to succeed as from the commit referred and fail
beforehand.

As the test requires 2GiB of data to be passed around its performance
has been evaluated using a choice of systems and the execution time
determined to be respectively in the range of 9s for POWER9@2.166GHz,
24s for FU740@1.2GHz, and 40s for 74Kf@950MHz.  As this is on the verge
of and beyond the default timeout it has been increased by the factor of
8.  Regardless, following recent practice the test has been added to the
standard rather than extended set.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 89cddc8a70)
2024-08-28 15:58:01 -04:00
Maciej W. Rozycki 98de2f2bae support: Add FAIL test failure helper
Add a FAIL test failure helper analogous to FAIL_RET, that does not
cause the current function to return, providing a standardized way to
report a test failure with a message supplied while permitting the
caller to continue executing, for further reporting, cleaning up, etc.

Update existing test cases that provide a conflicting definition of FAIL
by removing the local FAIL definition and then as follows:

- tst-fortify-syslog: provide a meaningful message in addition to the
  file name already added by <support/check.h>; 'support_record_failure'
  is already called by 'support_print_failure_impl' invoked by the new
  FAIL test failure helper.

- tst-ctype: no update to FAIL calls required, with the name of the file
  and the line number within of the failure site additionally included
  by the new FAIL test failure helper, and error counting plus count
  reporting upon test program termination also already provided by
  'support_record_failure' and 'support_report_failure' respectively,
  called by 'support_print_failure_impl' and 'adjust_exit_status' also
  respectively.  However in a number of places 'printf' is called and
  the error count adjusted by hand, so update these places to make use
  of FAIL instead.  And last but not least adjust the final summary just
  to report completion, with any error count following as reported by
  the test driver.

- test-tgmath2: no update to FAIL calls required, with the name of the
  file of the failure site additionally included by the new FAIL test
  failure helper.  Also there is no need to track the return status by
  hand as any call to FAIL will eventually cause the test case to return
  an unsuccesful exit status regardless of the return status from the
  test function, via a call to 'adjust_exit_status' made by the test
  driver.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 1b97a9f23b)
2024-08-28 15:58:01 -04:00
Florian Weimer e73fd06b7f string: strerror, strsignal cannot use buffer after dlmopen (bug 32026)
Secondary namespaces have a different malloc.  Allocating the
buffer in one namespace and freeing it another results in
heap corruption.  Fix this by using a static string (potentially
translated) in secondary namespaces.  It would also be possible
to use the malloc from the initial namespace to manage the
buffer, but these functions would still not be safe to use in
auditors etc. because a call to strerror could still free a
buffer while it is used by the application.  Another approach
could use proper initial-exec TLS, duplicated in secondary
namespaces, but that would need a callback interface for freeing
libc resources in namespaces on thread exit, which does not exist
today.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 25a5eb4010)
2024-08-19 16:11:19 +02:00
Florian Weimer 37c2aa4eaa Define __libc_initial for the static libc
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit eb0e50e9a1)
2024-08-19 16:11:14 +02:00
Noah Goldstein 49953727d1 x86: Fix bug in strchrnul-evex512 [BZ #32078]
Issue was we were expecting not matches with CHAR before the start of
the string in the page cross case.

The check code in the page cross case:
```
    and    $0xffffffffffffffc0,%rax
    vmovdqa64 (%rax),%zmm17
    vpcmpneqb %zmm17,%zmm16,%k1
    vptestmb %zmm17,%zmm17,%k0{%k1}
    kmovq  %k0,%rax
    inc    %rax
    shr    %cl,%rax
    je     L(continue)
```

expects that all characters that neither match null nor CHAR will be
1s in `rax` prior to the `inc`. Then the `inc` will overflow all of
the 1s where no relevant match was found.

This is incorrect in the page-cross case, as the
`vmovdqa64 (%rax),%zmm17` loads from before the start of the input
string.

If there are matches with CHAR before the start of the string, `rax`
won't properly overflow.

The fix is quite simple. Just replace:

```
    inc    %rax
    shr    %cl,%rax
```
With:
```
    sar    %cl,%rax
    inc    %rax
```

The arithmetic shift will clear any matches prior to the start of the
string while maintaining the signbit so the 1s can properly overflow
to zero in the case of no matches.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 7da0886247)
2024-08-15 13:26:05 -07:00
Florian Weimer 81631a0dd1 Adjust check-local-headers test for libaudit 4.0
The new version introduces /usr/include/audit_logging.h and
/usr/include/audit-records.h.

(cherry picked from commit 91eb62d638)
2024-08-13 09:57:26 +02:00
H.J. Lu 9fbbe86f7c x32/cet: Support shadow stack during startup for Linux 6.10
Use RXX_LP in RTLD_START_ENABLE_X86_FEATURES.  Support shadow stack during
startup for Linux 6.10:

commit 2883f01ec37dd8668e7222dfdb5980c86fdfe277
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Mar 15 07:04:33 2024 -0700

    x86/shstk: Enable shadow stacks for x32

    1. Add shadow stack support to x32 signal.
    2. Use the 64-bit map_shadow_stack syscall for x32.
    3. Set up shadow stack for x32.

Add the map_shadow_stack system call to <fixup-asm-unistd.h> and regenerate
arch-syscall.h.  Tested on Intel Tiger Lake with CET enabled x32.  There
are no regressions with CET enabled x86-64.  There are no changes in CET
enabled x86-64 _dl_start_user.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 8344c1f551)
2024-08-12 10:54:17 -07:00
H.J. Lu eeff407b19 x86-64: Remove sysdeps/x86_64/x32/dl-machine.h
Remove sysdeps/x86_64/x32/dl-machine.h by folding x32 ARCH_LA_PLTENTER,
ARCH_LA_PLTEXIT and RTLD_START into sysdeps/x86_64/dl-machine.h.  There
are no regressions on x86-64 nor x32.  There are no changes in x86-64
_dl_start_user.  On x32, _dl_start_user changes are

 <_dl_start_user>:
 	mov    %eax,%r12d
+	mov    %esp,%r13d
 	mov    (%rsp),%edx
 	mov    %edx,%esi
-	mov    %esp,%r13d
 	and    $0xfffffff0,%esp
 	mov    0x0(%rip),%edi        # <_dl_start_user+0x14>
 	lea    0x8(%r13,%rdx,4),%ecx

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 652c6cf269)
2024-08-12 10:54:05 -07:00
Florian Weimer 1ab7faf86d support: Add options list terminator to the test driver
This avoids crashes if a test is passed unknown options.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit c2a474f461)
2024-08-09 17:26:41 +02:00
Arjun Shankar 6eebc92cb2 manual/stdio: Further clarify putc, putwc, getc, and getwc
This is a follow-up to 10de4a47ef that
reworded the manual entries for putc and putwc and removed any
performance claims.

This commit further clarifies these entries and brings getc and getwc in
line with the descriptions of putc and putwc, removing any performance
claims from them as well.
Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 942670c81d)
2024-08-06 13:47:49 +02:00
Andreas Schwab afc15c2044 Fix name space violation in fortify wrappers (bug 32052)
Rename the identifier sz to __sz everywhere.

Fixes: a643f60c53 ("Make sure that the fortified function conditionals are constant")
(cherry picked from commit 39ca997ab3)
(redone from scratch because of many conflicts)
2024-08-06 08:21:58 +02:00
Florian Weimer 5a5eb72d8e resolv: Fix tst-resolv-short-response for older GCC (bug 32042)
Previous GCC versions do not support the C23 change that
allows labels on declarations.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit ec119972cb)
2024-08-01 21:09:33 +02:00
H.J. Lu 7f5ccdd8af Add mremap tests
Add tests for MREMAP_MAYMOVE and MREMAP_FIXED.  On Linux, also test
MREMAP_DONTUNMAP.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit ff0320bec2)
2024-08-01 14:21:57 +02:00
H.J. Lu a8c230c881 mremap: Update manual entry
Update mremap manual entry:

1. Change mremap to variadic.
2. Document MREMAP_FIXED and MREMAP_DONTUNMAP.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit cb2dee4ecc)
2024-08-01 14:21:49 +02:00
H.J. Lu 9f349d02c6 linux: Update the mremap C implementation [BZ #31968]
Update the mremap C implementation to support the optional argument for
MREMAP_DONTUNMAP added in Linux 5.7 since it may not always be correct
to implement a variadic function as a non-variadic function on all Linux
targets.  Return MAP_FAILED and set errno to EINVAL for unknown flag bits.
This fixes BZ #31968.

Note: A test must be added when a new flag bit is introduced.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 6c40cb0e9f)
2024-08-01 14:21:19 +02:00
Florian Weimer 127ef30c46 Enhanced test coverage for strncmp, wcsncmp
Add string/test-strncmp-nonarray and
wcsmbs/test-wcsncmp-nonarray.

This is the test that uncovered bug 31934.  Test run time
is more than one minute on a fairly current system, so turn
these into xtests that do not run automatically.

Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 54252394c2)
2024-08-01 09:41:24 +02:00
Florian Weimer 3b25c7fa87 Enhance test coverage for strnlen, wcsnlen
This commit adds string/test-strnlen-nonarray and
wcsmbs/test-wcsnlen-nonarray.

Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 783d4c0b81)
2024-08-01 09:41:24 +02:00
Lukas Bulwahn 4bdcc1963b manual: make setrlimit() description less ambiguous
The existing description for setrlimit() has some ambiguity. It could be
understood to have the semantics of getrlimit(), i.e., the limits from the
process are stored in the provided rlp pointer.

Make the description more explicit that rlp are the input values, and that
the limits of the process is changed with this function.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit aedbf08891)
2024-07-29 17:06:13 +02:00
Arjun Shankar b71a51189d manual/stdio: Clarify putc and putwc
The manual entry for `putc' described what "most systems" do instead of
describing the glibc implementation and its guarantees.  This commit
fixes that by warning that putc may be implemented as a macro that
double-evaluates `stream', and removing the performance claim.

Even though the current `putc' implementation does not double-evaluate
`stream', offering this obscure guarantee as an extension to what
POSIX allows does not seem very useful.

The entry for `putwc' is also edited to bring it in line with `putc'.
Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 10de4a47ef)
2024-07-29 15:23:15 +02:00
Miguel Martín 946006d37c malloc: add multi-threaded tests for aligned_alloc/calloc/malloc
Improve aligned_alloc/calloc/malloc test coverage by adding
multi-threaded tests with random memory allocations and with/without
cross-thread memory deallocations.

Perform a number of memory allocation calls with random sizes limited
to 0xffff.

Use the existing DSO ('malloc/tst-aligned_alloc-lib.c') to randomize
allocator selection.

The multi-threaded allocation/deallocation is staged as described below:

- Stage 1: Half of the threads will be allocating memory and the
  other half will be waiting for them to finish the allocation.
- Stage 2: Half of the threads will be allocating memory and the
  other half will be deallocating memory.
- Stage 3: Half of the threads will be deallocating memory and the
  second half waiting on them to finish.

Add 'malloc/tst-aligned-alloc-random-thread.c' where each thread will
deallocate only the memory that was previously allocated by itself.

Add 'malloc/tst-aligned-alloc-random-thread-cross.c' where each thread
will deallocate memory that was previously allocated by another thread.

The intention is to be able to utilize existing malloc testing to ensure
that similar allocation APIs are also exposed to the same rigors.
Reviewed-by: Arjun Shankar <arjun@redhat.com>

(cherry picked from commit b0fbcb7d00)
2024-07-29 15:23:09 +02:00
Miguel Martín f11b7178a1 malloc: avoid global locks in tst-aligned_alloc-lib.c
Make sure the DSO used by aligned_alloc/calloc/malloc tests does not get
a global lock on multithreaded tests.
Reviewed-by: Arjun Shankar <arjun@redhat.com>

(cherry picked from commit 9a27b566b2)
2024-07-29 15:23:09 +02:00
Florian Weimer 51db012c94 resolv: Track single-request fallback via _res._flags (bug 31476)
This avoids changing _res.options, which inteferes with change
detection as part of automatic reloading of /etc/resolv.conf.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 868ab8923a)
2024-07-24 15:10:39 +02:00
Florian Weimer 8c9fbc6651 resolv: Do not wait for non-existing second DNS response after error (bug 30081)
In single-request mode, there is no second response after an error
because the second query has not been sent yet.  Waiting for it
introduces an unnecessary timeout.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit af625987d6)
2024-07-24 14:33:43 +02:00
Florian Weimer fc1dc39984 resolv: Allow short error responses to match any query (bug 31890)
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 691a3b2e9b)
2024-07-24 14:33:43 +02:00
Adhemerval Zanella cb19cef087 elf: Fix localplt.awk for DT_RELR-enabled builds (BZ 31978)
For each input readelf output, localplt.awk parses each 'Relocation
section' entry, checks its offset against the dynamic section entry, and
saves each DT_JMPREL, DT_RELA, and DT_REL offset value it finds. After
all lines are read, the script checks if any segment offset differed
from 0, meaning at least one 'Relocation section' was matched.

However, if the shared object was built with RELR support and the static
linker could place all the relocation on DT_RELR, there would be no
DT_JMPREL, DT_RELA, and DT_REL entries; only a DT_RELR.

For the current three ABIs that support (aarch64, x86, and powerpc64),
the powerpc64 ld.so shows the behavior above. Both x86_64 and aarch64
show extra relocations on '.rela.dyn', which makes the script check to
succeed.

This patch fixes by handling DT_RELR, where the offset is checked
against the dynamic section entries and if the shared object contains an
entry it means that there are no extra PLT entries (since all
relocations are relative).

It fixes the elf/check-localplt failure on powerpc.

Checked with a build/check for aarch64-linux-gnu, x86_64-linux-gnu,
i686-linux-gnu, arm-linux-gnueabihf, s390x-linux-gnu, powerpc-linux-gnu,
powerpc64-linux-gnu, and powerpc64le-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 4f047d9ede)
2024-07-23 19:05:38 +02:00
John David Anglin f6a75fddf4 Fix usage of _STACK_GROWS_DOWN and _STACK_GROWS_UP defines [BZ 31989]
Signed-off-by: John David Anglin <dave.anglin@bell.net>
Reviewed-By: Andreas K. Hüttel <dilfridge@gentoo.org>
(cherry picked from commit 8cfa4ecff2)
2024-07-19 21:22:02 +02:00
Florian Weimer e8f5217097 Linux: Make __rseq_size useful for feature detection (bug 31965)
The __rseq_size value is now the active area of struct rseq
(so 20 initially), not the full struct size including padding
at the end (32 initially).

Update misc/tst-rseq to print some additional diagnostics.

Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
(cherry picked from commit 2e456ccf0c)
2024-07-16 16:35:29 +02:00
Adhemerval Zanella 143a7a0623 elf: Make dl-rseq-symbols Linux only
And avoid a Hurd build failures.

Checked on x86_64-linux-gnu.

(cherry picked from commit 9fc639f654)
2024-07-16 16:33:53 +02:00
Michael Jeanson 1062ebbd19 nptl: fix potential merge of __rseq_* relro symbols
While working on a patch to add support for the extensible rseq ABI, we
came across an issue where a new 'const' variable would be merged with
the existing '__rseq_size' variable. We tracked this to the use of
'-fmerge-all-constants' which allows the compiler to merge identical
constant variables. This means that all 'const' variables in a compile
unit that are of the same size and are initialized to the same value can
be merged.

In this specific case, on 32 bit systems 'unsigned int' and 'ptrdiff_t'
are both 4 bytes and initialized to 0 which should trigger the merge.
However for reasons we haven't delved into when the attribute 'section
(".data.rel.ro")' is added to the mix, only variables of the same exact
types are merged. As far as we know this behavior is not specified
anywhere and could change with a new compiler version, hence this patch.

Move the definitions of these variables into an assembler file and add
hidden writable aliases for internal use. This has the added bonus of
removing the asm workaround to set the values on rseq registration.

Tested on Debian 12 with GCC 12.2.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 2b92982e23)
2024-07-16 16:33:53 +02:00
Stefan Liebler 5c46e6b666 s390x: Fix segfault in wcsncmp [BZ #31934]
The z13/vector-optimized wcsncmp implementation segfaults if n=1
and there is only one character (equal on both strings) before
the page end.  Then it loads and compares one character and misses
to check n again.  The following load fails.

This patch removes the extra load and compare of the first character
and just start with the loop which uses vector-load-to-block-boundary.
This code-path also checks n.

With this patch both tests are passing:
- the simplified one mentioned in the bugzilla 31934
- the full one in Florian Weimer's patch:
"manual: Document a GNU extension for strncmp/wcsncmp"
(https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/):
On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 9b76514103)
2024-07-16 10:25:35 +02:00
Adhemerval Zanella a036311246 stdlib: fix arc4random fallback to /dev/urandom (BZ 31612)
The __getrandom_nocancel used by __arc4random_buf uses
INLINE_SYSCALL_CALL (which returns -1/errno) and the loop checks for
the return value instead of errno to fallback to /dev/urandom.

The malloc code now uses __getrandom_nocancel_nostatus, which uses
INTERNAL_SYSCALL_CALL, so there is no need to use the variant that does
not set errno (BZ#29624).

Checked on x86_64-linux-gnu.

Reviewed-by: Xi Ruoyao <xry111@xry111.site>
(cherry picked from commit 184b9e530e)
2024-07-08 10:23:10 -03:00
Adhemerval Zanella d2cbfcf1d9 math: Provide missing math symbols on libc.a (BZ 31781)
The libc.a for alpha, s390, and sparcv9 does not provide
copysignf64x, copysignf128, frexpf64x, frexpf128, modff64x, and
modff128.

Checked with a static build for the affected ABIs.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit eaa8113bf0)
2024-07-02 14:37:44 +02:00
Adhemerval Zanella d473c9bb3b math: Fix isnanf128 static build (BZ 31774)
Some static implementation of float128 routines might call __isnanf128,
which is not provided by the static object.

Checked on x86_64-linux-gnu.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5d4999e519)
2024-07-02 14:37:19 +02:00
Adhemerval Zanella 3950cbd7a1 math: Fix i386 and m68k exp10 on static build (BZ 31775)
The commit 08ddd26814 removed the static exp10 on i386 and m68k with an
empty w_exp10.c (required for the ABIs that uses the newly
implementation).  This patch fixes by adding the required symbols on the
arch-specific w_exp{f}_compat.c implementation.

Checked on i686-linux-gnu and with a build for m68k-linux-gnu.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 1f09aae36a)
2024-07-02 14:25:56 +02:00
Adhemerval Zanella 6cb25aff85 math: Fix i386 and m68k fmod/fmodf on static build (BZ 31488)
The commit 16439f419b removed the static fmod/fmodf on i386 and m68k
with and empty w_fmod.c (required for the ABIs that uses the newly
implementation).  This patch fixes by adding the required symbols on
the arch-specific w_fmod{f}_compat.c implementation.

To statically build fmod fails on some ABI (alpha, s390, sparc) because
it does not export the ldexpf128, this is also fixed by this patch.

Checked on i686-linux-gnu and with a build for m68k-linux-gnu.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 0b716305df)
2024-07-02 14:25:52 +02:00
Adhemerval Zanella 74630b1bb7 posix: Fix pidfd_spawn/pidfd_spawnp leak if execve fails (BZ 31695)
If the pidfd_spawn/pidfd_spawnp helper process succeeds, but evecve
fails for some reason (either with an invalid/non-existent, memory
allocation, etc.) the resulting pidfd is never closed, nor returned
to caller (so it can call close).

Since the process creation failed, it should be up to posix_spawn to
also, close the file descriptor in this case (similar to what it
does to reap the process).

This patch also changes the waitpid with waitid (P_PIDFD) for pidfd
case, to avoid a possible pid re-use.

Checked on x86_64-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit c90cfce849)
2024-06-25 13:51:16 -03:00
Florian Weimer 7f9f25f255 Linux: Include <dl-symbol-redir-ifunc.h> in dl-sysdep.c
The _dl_sysdep_parse_arguments function contains initalization
of a large on-stack variable:

  dl_parse_auxv_t auxv_values = { 0, };

This uses a non-inline version of memset on powerpc64le-linux-gnu,
so it must use the baseline memset.

(cherry picked from commit f6ea5d1291)
2024-06-21 12:13:06 +02:00
Andreas K. Hüttel 198632a05f NEWS: update list of fixed CVEs in 2.39
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2024-06-15 15:22:20 +02:00
Andreas K. Hüttel 77bb3c7154 NEWS: update list of fixed bugs in 2.39
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2024-06-15 15:11:18 +02:00
H.J. Lu f05638731e x86: Properly set x86 minimum ISA level [BZ #31883]
Properly set libc_cv_have_x86_isa_level in shell for MINIMUM_X86_ISA_LEVEL
defined as

(__X86_ISA_V1 + __X86_ISA_V2 + __X86_ISA_V3 + __X86_ISA_V4)

Also set __X86_ISA_V2 to 1 for i386 if __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
is defined.  There are no changes in config.h nor in config.make on x86-64.
On i386, -march=x86-64-v2 with GCC generates

 #define MINIMUM_X86_ISA_LEVEL 2

in config.h and

have-x86-isa-level = 2

in config.make.  This fixes BZ #31883.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 29807a271e)
2024-06-15 11:13:10 +01:00
H.J. Lu b7f5b0a711 x86: Properly set MINIMUM_X86_ISA_LEVEL for i386 [BZ #31867]
On i386, set the default minimum ISA level to 0, not 1 (baseline which
includes SSE2).  There are no changes in config.h nor in config.make on
x86-64.  This fixes BZ #31867.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Tested-by: Ian Jordan <immoloism@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 09bc68b0ac)
2024-06-15 11:13:10 +01:00
Mike FABIAN e1d0040a6d localedata: ssy_ER: Fix syntax error
(cherry picked from commit 07fd072caf)
2024-06-14 19:22:51 +01:00
sayan paul 9de9cd17e7 malloc: New test to check malloc alternate path using memory obstruction
The test aims to ensure that malloc uses the alternate path to
allocate memory when sbrk() or brk() fails.To achieve this,
the test first creates an obstruction at current program break,
tests that obstruction with a failing sbrk(), then checks if malloc
is still returning a valid ptr thus inferring that malloc() used
mmap() instead of brk() or sbrk() to allocate the memory.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
Reviewed-by: Zack Weinberg <zack@owlfolio.org>

(cherry picked from commit 127fc56152)
2024-06-10 17:15:32 +02:00
Joe Simmons-Talbott a2da98aa2a malloc: Improve aligned_alloc and calloc test coverage.
Add a DSO (malloc/tst-aligned_alloc-lib.so) that can be used during
testing to interpose malloc with a call that randomly uses either
aligned_alloc, __libc_malloc, or __libc_calloc in the place of malloc.
Use LD_PRELOAD with the DSO to mirror malloc/tst-malloc.c testing as an
example in malloc/tst-malloc-random.c.  Add malloc/tst-aligned-alloc-random.c
as another example that does a number of malloc calls with randomly sized,
but limited to 0xffff, requests.

The intention is to be able to utilize existing malloc testing to ensure
that similar allocation APIs are also exposed to the same rigors.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 3395157ff2)
2024-06-10 17:10:02 +02:00
H.J. Lu 305ee48826 malloc/Makefile: Split and sort tests
Put each test on a separate line and sort tests.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit d49cd6a191)
2024-06-10 17:09:03 +02:00
Michael Jeanson 00899eba26 x86/cet: fix shadow stack test scripts
Some shadow stack test scripts use the '==' operator with the 'test'
command to validate exit codes resulting in the following error:

  sysdeps/x86_64/tst-shstk-legacy-1e.sh: 31: test: 139: unexpected operator

The '==' operator is invalid for the 'test' command, use '-eq' like the
previous call to 'test'.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 155bb9d036)
2024-06-09 15:59:49 +01:00
Florian Weimer 6ade91c211 elf: Avoid some free (NULL) calls in _dl_update_slotinfo
This has been confirmed to work around some interposed mallocs.  Here
is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper
in lttng-tools:

  New TLS usage in libgcc_s.so.1, compatibility impact
  <https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/>

Reportedly, this patch also papers over a similar issue when tcmalloc
2.9.1 is not compiled with -ftls-model=initial-exec.  Of course the
goal really should be to compile mallocs with the initial-exec TLS
model, but this commit appears to be a useful interim workaround.

Fixes commit d2123d6827 ("elf: Fix slow
tls access after dlopen [BZ #19924]").

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit afe42e935b)
2024-06-03 19:05:39 +02:00
Stafford Horne 70f560fc22 misc: Add support for Linux uio.h RWF_NOAPPEND flag
In Linux 6.9 a new flag is added to allow for Per-io operations to
disable append mode even if a file was opened with the flag O_APPEND.
This is done with the new RWF_NOAPPEND flag.

This caused two test failures as these tests expected the flag 0x00000020
to be unused.  Adding the flag definition now fixes these tests on Linux
6.9 (v6.9-rc1).

  FAIL: misc/tst-preadvwritev2
  FAIL: misc/tst-preadvwritev64v2

This patch adds the flag, adjusts the test and adds details to
documentation.

Link: https://lore.kernel.org/all/20200831153207.GO3265@brightrain.aerifal.cx/
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 3db9d208dd)
2024-05-29 13:51:32 +02:00
Sunil K Pandey c9d8534406 i386: Disable Intel Xeon Phi tests for GCC 15 and above (BZ 31782)
This patch disables Intel Xeon Phi tests for GCC 15 and above.

GCC 15 removed Intel Xeon Phi ISA support.
commit e1a7e2c54d52d0ba374735e285b617af44841ace
Author: Haochen Jiang <haochen.jiang@intel.com>
Date:   Mon May 20 10:43:44 2024 +0800

    i386: Remove Xeon Phi ISA support

Fixes BZ 31782.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 1b713c9a53)
2024-05-28 09:32:29 -07:00
Adhemerval Zanella aee37de299 Reinstate generic features-time64.h
The a4ed0471d7 removed the generic version which is included by
features.h and used by Hurd.

Checked by building i686-gnu and x86_64-gnu with build-many-glibc.py.

(cherry picked from commit c27f8763cf)
2024-05-28 07:30:07 +02:00
Adhemerval Zanella dd535f4f19 Always define __USE_TIME_BITS64 when 64 bit time_t is used
It was raised on libc-help [1] that some Linux kernel interfaces expect
the libc to define __USE_TIME_BITS64 to indicate the time_t size for the
kABI.  Different than defined by the initial y2038 design document [2],
the __USE_TIME_BITS64 is only defined for ABIs that support more than
one time_t size (by defining the _TIME_BITS for each module).

The 64 bit time_t redirects are now enabled using a different internal
define (__USE_TIME64_REDIRECTS). There is no expected change in semantic
or code generation.

Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
arm-linux-gnueabi

[1] https://sourceware.org/pipermail/libc-help/2024-January/006557.html
[2] https://sourceware.org/glibc/wiki/Y2038ProofnessDesign

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit a4ed0471d7)
2024-05-28 07:30:07 +02:00
Florian Weimer 26e7005728 socket: Use may_alias on sockaddr structs (bug 19622)
This supports common coding patterns.  The GCC C front end before
version 7 rejects the may_alias attribute on a struct definition
if it was not present in a previous forward declaration, so this
attribute can only be conditionally applied.

This implements the spirit of the change in Austin Group issue 1641.

Suggested-by: Marek Polacek <polacek@redhat.com>
Suggested-by: Jakub Jelinek <jakub@redhat.com>
Reviewed-by: Sam James <sam@gentoo.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 8d7b6b4cb2)
2024-05-27 17:25:13 +02:00
H.J. Lu 9f2b100d67 parse_fdinfo: Don't advance pointer twice [BZ #31798]
pidfd_getpid.c has

      /* Ignore invalid large values.  */
      if (INT_MULTIPLY_WRAPV (10, n, &n)
          || INT_ADD_WRAPV (n, *l++ - '0', &n))
        return -1;

For GCC older than GCC 7, INT_ADD_WRAPV(a, b, r) is defined as

   _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)

and *l++ - '0' is evaluated twice.  Fix BZ #31798 by moving "l++" out of
the if statement.  Tested with GCC 6.4 and GCC 14.1.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit f981bf6b9d)
2024-05-27 07:38:56 -07:00
caiyinyu c7c3f5bf80 LoongArch: Fix undefined __memset_aligned reference in ld.so linking.
This patch from 095067efdf (LoongArch: Add
glibc.cpu.hwcap support.)
2024-05-15 09:08:10 +08:00
Sergey Kolosov 32969a2b36 socket: Add new test for connect
This commit adds a simple bind/accept/connect test for an IPv4 TCP
connection to a local process via the loopback interface.

Reviewed-by: Arjun Shankar <arjun@redhat.com>
(cherry picked from commit 3a83f79024)
2024-05-13 14:05:46 +02:00
Sergey Kolosov 2db79c96ba libsupport: Add xgetpeername
The patch adds redirections for getpeername.

Reviewed-by: Arjun Shankar <arjun@redhat.com>
(cherry picked from commit 6687a6e3f9)
2024-05-13 14:05:36 +02:00
Gabi Falk ab4ef4421f x86_64: Fix missing wcsncat function definition without multiarch (x86-64-v4)
This code expects the WCSCAT preprocessor macro to be predefined in case
the evex implementation of the function should be defined with a name
different from __wcsncat_evex.  However, when glibc is built for
x86-64-v4 without multiarch support, sysdeps/x86_64/wcsncat.S defines
WCSNCAT variable instead of WCSCAT to build it as wcsncat.  Rename the
variable to WCSNCAT, as it is actually a better naming choice for the
variable in this case.

Reported-by: Kenton Groombridge
Link: https://bugs.gentoo.org/921945
Fixes: 64b8b6516b ("x86: Add evex optimized functions for the wchar_t strcpy family")
Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit dd5f891c1a)
2024-05-11 01:00:24 +01:00
H.J. Lu 97bb89668d Force DT_RPATH for --enable-hardcoded-path-in-tests
On Fedora 40/x86-64, linker enables --enable-new-dtags by default which
generates DT_RUNPATH instead of DT_RPATH.  Unlike DT_RPATH, DT_RUNPATH
only applies to DT_NEEDED entries in the executable and doesn't applies
to DT_NEEDED entries in shared libraries which are loaded via DT_NEEDED
entries in the executable.  Some glibc tests have libstdc++.so.6 in
DT_NEEDED, which has libm.so.6 in DT_NEEDED.  When DT_RUNPATH is generated,
/lib64/libm.so.6 is loaded for such tests.  If the newly built glibc is
older than glibc 2.36, these tests fail with

assert/tst-assert-c++: /export/build/gnu/tools-build/glibc-gitlab-release/build-x86_64-linux/libc.so.6: version `GLIBC_2.36' not found (required by /lib64/libm.so.6)
assert/tst-assert-c++: /export/build/gnu/tools-build/glibc-gitlab-release/build-x86_64-linux/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /lib64/libm.so.6)

Pass -Wl,--disable-new-dtags to linker when building glibc tests with
--enable-hardcoded-path-in-tests.  This fixes BZ #31719.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 2dcaf70643)
2024-05-10 04:59:46 -07:00
Adhemerval Zanella 71149c2a2e elf: Only process multiple tunable once (BZ 31686)
The 680c597e9c commit made loader reject ill-formatted strings by
first tracking all set tunables and then applying them. However, it does
not take into consideration if the same tunable is set multiple times,
where parse_tunables_string appends the found tunable without checking
if it was already in the list. It leads to a stack-based buffer overflow
if the tunable is specified more than the total number of tunables.  For
instance:

  GLIBC_TUNABLES=glibc.malloc.check=2:... (repeat over the number of
  total support for different tunable).

Instead, use the index of the tunable list to get the expected tunable
entry.  Since now the initial list is zero-initialized, the compiler
might emit an extra memset and this requires some minor adjustment
on some ports.

Checked on x86_64-linux-gnu and aarch64-linux-gnu.

Reported-by: Yuto Maeda <maeda@cyberdefense.jp>
Reported-by: Yutaro Shimizu <shimizu@cyberdefense.jp>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit bcae44ea85)
2024-05-07 14:06:56 -03:00
Gabi Falk f8e4623421 Add a test to check for duplicate definitions in the static library
This change follows two previous fixes addressing multiple definitions
of __memcpy_chk and __mempcpy_chk functions on i586, and __memmove_chk
and __memset_chk functions on i686.  The test is intended to prevent
such issues from occurring in the future.

Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit ded2e0753e)
2024-05-04 13:29:48 +01:00
Gabi Falk 8b005d7869 i686: Fix multiple definitions of __memmove_chk and __memset_chk
Commit c73c96a4a1 updated memcpy.S and
mempcpy.S, but omitted memmove.S and memset.S.  As a result, the static
library built as PIC, whether with or without multiarch support,
contains two definitions for each of the __memmove_chk and __memset_chk
symbols.

/usr/lib/gcc/i686-pc-linux-gnu/14/../../../../i686-pc-linux-gnu/bin/ld: /usr/lib/gcc/i686-pc-linux-gnu/14/../../../../lib/libc.a(memset-ia32.o): in function `__memset_chk':
/var/tmp/portage/sys-libs/glibc-2.39-r3/work/glibc-2.39/string/../sysdeps/i386/i686/memset.S:32: multiple definition of `__memset_chk'; /usr/lib/gcc/i686-pc-linux-gnu/14/../../../../lib/libc.a(memset_chk.o):/var/tmp/portage/sys-libs/glibc-2.39-r3/work/glibc-2.39/debug/../sysdeps/i386/i686/multiarch/memset_chk.c:24: first defined here

After this change, regardless of PIC options, the static library, built
for i686 with multiarch contains implementations of these functions
respectively from debug/memmove_chk.c and debug/memset_chk.c, and
without multiarch contains implementations of these functions
respectively from sysdeps/i386/memmove_chk.S and
sysdeps/i386/memset_chk.S.  This ensures that memmove and memset won't
pull in __chk_fail and the routines it calls.

Reported-by: Sam James <sam@gentoo.org>
Tested-by: Sam James <sam@gentoo.org>
Fixes: c73c96a4a1 ("i686: Fix build with --disable-multiarch")
Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit 5a2cf833f5)
2024-05-04 13:29:48 +01:00
Gabi Falk 8323a83abd i586: Fix multiple definitions of __memcpy_chk and __mempcpy_chk
/home/bmg/install/compilers/x86_64-linux-gnu/lib/gcc/x86_64-glibc-linux-gnu/13.2.1/../../../../x86_64-glibc-linux-gnu/bin/ld: /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(memcpy_chk.o): in function `__memcpy_chk':
/home/bmg/src/glibc/debug/../sysdeps/i386/memcpy_chk.S:29: multiple definition of `__memcpy_chk';/home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(memcpy.o):/home/bmg/src/glibc/string/../sysdeps/i386/i586/memcpy.S:31: first defined here /home/bmg/install/compilers/x86_64-linux-gnu/lib/gcc/x86_64-glibc-linux-gnu/13.2.1/../../../../x86_64-glibc-linux-gnu/bin/ld: /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(mempcpy_chk.o): in function `__mempcpy_chk': /home/bmg/src/glibc/debug/../sysdeps/i386/mempcpy_chk.S:28: multiple definition of `__mempcpy_chk'; /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(mempcpy.o):/home/bmg/src/glibc/string/../sysdeps/i386/i586/memcpy.S:31: first defined here

After this change, the static library built for i586, regardless of PIC
options, contains implementations of these functions respectively from
sysdeps/i386/memcpy_chk.S and sysdeps/i386/mempcpy_chk.S.  This ensures
that memcpy and mempcpy won't pull in __chk_fail and the routines it
calls.

Reported-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit 0fdf4ba48c)
2024-05-04 13:29:05 +01:00
Sam James 5141d4d83c Revert "i586: Fix multiple definitions of __memcpy_chk and __mempcpy_chk"
This reverts commit 3148714ab6.

I had the wrong cherry-pick reference (the commit content is right; it's
just referring to a base that isn't upstream), but let's revert and reapply
for clarity.

Signed-off-by: Sam James <sam@gentoo.org>
2024-05-04 13:28:54 +01:00
Sam James c16871e662 Revert "i686: Fix multiple definitions of __memmove_chk and __memset_chk"
This reverts commit ad92c483a4.

I had the wrong cherry-pick reference (the commit content is right; it's
just referring to a base that isn't upstream), but let's revert and reapply
for clarity.

Signed-off-by: Sam James <sam@gentoo.org>
2024-05-04 13:28:51 +01:00
Sam James fa616ea373 Revert "Add a test to check for duplicate definitions in the static library"
This reverts commit ff110b2591.

I had the wrong cherry-pick reference (the commit content is right; it's
just referring to a base that isn't upstream), but let's revert and reapply
for clarity.

Signed-off-by: Sam James <sam@gentoo.org>
2024-05-04 13:28:13 +01:00
Gabi Falk ff110b2591 Add a test to check for duplicate definitions in the static library
This change follows two previous fixes addressing multiple definitions
of __memcpy_chk and __mempcpy_chk functions on i586, and __memmove_chk
and __memset_chk functions on i686.  The test is intended to prevent
such issues from occurring in the future.

Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit ded2e0753e)
2024-05-04 13:23:41 +01:00
Gabi Falk ad92c483a4 i686: Fix multiple definitions of __memmove_chk and __memset_chk
Commit c73c96a4a1 updated memcpy.S and
mempcpy.S, but omitted memmove.S and memset.S.  As a result, the static
library built as PIC, whether with or without multiarch support,
contains two definitions for each of the __memmove_chk and __memset_chk
symbols.

/usr/lib/gcc/i686-pc-linux-gnu/14/../../../../i686-pc-linux-gnu/bin/ld: /usr/lib/gcc/i686-pc-linux-gnu/14/../../../../lib/libc.a(memset-ia32.o): in function `__memset_chk':
/var/tmp/portage/sys-libs/glibc-2.39-r3/work/glibc-2.39/string/../sysdeps/i386/i686/memset.S:32: multiple definition of `__memset_chk'; /usr/lib/gcc/i686-pc-linux-gnu/14/../../../../lib/libc.a(memset_chk.o):/var/tmp/portage/sys-libs/glibc-2.39-r3/work/glibc-2.39/debug/../sysdeps/i386/i686/multiarch/memset_chk.c:24: first defined here

After this change, regardless of PIC options, the static library, built
for i686 with multiarch contains implementations of these functions
respectively from debug/memmove_chk.c and debug/memset_chk.c, and
without multiarch contains implementations of these functions
respectively from sysdeps/i386/memmove_chk.S and
sysdeps/i386/memset_chk.S.  This ensures that memmove and memset won't
pull in __chk_fail and the routines it calls.

Reported-by: Sam James <sam@gentoo.org>
Tested-by: Sam James <sam@gentoo.org>
Fixes: c73c96a4a1 ("i686: Fix build with --disable-multiarch")
Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit 5a2cf833f5)
2024-05-04 13:23:24 +01:00
Gabi Falk 3148714ab6 i586: Fix multiple definitions of __memcpy_chk and __mempcpy_chk
/home/bmg/install/compilers/x86_64-linux-gnu/lib/gcc/x86_64-glibc-linux-gnu/13.2.1/../../../../x86_64-glibc-linux-gnu/bin/ld: /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(memcpy_chk.o): in function `__memcpy_chk':
/home/bmg/src/glibc/debug/../sysdeps/i386/memcpy_chk.S:29: multiple definition of `__memcpy_chk';/home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(memcpy.o):/home/bmg/src/glibc/string/../sysdeps/i386/i586/memcpy.S:31: first defined here /home/bmg/install/compilers/x86_64-linux-gnu/lib/gcc/x86_64-glibc-linux-gnu/13.2.1/../../../../x86_64-glibc-linux-gnu/bin/ld: /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(mempcpy_chk.o): in function `__mempcpy_chk': /home/bmg/src/glibc/debug/../sysdeps/i386/mempcpy_chk.S:28: multiple definition of `__mempcpy_chk'; /home/bmg/build/glibcs/i586-linux-gnu/glibc/libc.a(mempcpy.o):/home/bmg/src/glibc/string/../sysdeps/i386/i586/memcpy.S:31: first defined here

After this change, the static library built for i586, regardless of PIC
options, contains implementations of these functions respectively from
sysdeps/i386/memcpy_chk.S and sysdeps/i386/mempcpy_chk.S.  This ensures
that memcpy and mempcpy won't pull in __chk_fail and the routines it
calls.

Reported-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Gabi Falk <gabifalk@gmx.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit 789894a2f554d4503ecb2f13b2b4e93e43414f33)
2024-05-04 13:23:15 +01:00
Carlos O'Donell 273a835fe7 time: Allow later version licensing.
The FSF's Licensing and Compliance Lab noted a discrepancy in the
licensing of several files in the glibc package.

When timespect_get.c was impelemented the license did not include
the standard ", or (at your option) any later version." text.

Change the license in timespec_get.c and all copied files to match
the expected license.

This change was previously approved in principle by the FSF in
RT ticket #1316403. And a similar instance was fixed in
commit 46703efa02.

(cherry picked from commit 91695ee459)
2024-05-03 10:15:11 +02:00
Florian Weimer acc56074b0 nscd: Use time_t for return type of addgetnetgrentX
Using int may give false results for future dates (timeouts after the
year 2028).

Fixes commit 04a21e050d64a1193a6daab872bca2528bda44b ("CVE-2024-33601,
CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX
(bug 31680)").

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 4bbca1a446)
2024-05-02 19:00:16 +02:00
Florian Weimer 836d43b989 login: structs utmp, utmpx, lastlog _TIME_BITS independence (bug 30701)
These structs describe file formats under /var/log, and should not
depend on the definition of _TIME_BITS.  This is achieved by
defining __WORDSIZE_TIME64_COMPAT32 to 1 on 32-bit ports that
support 32-bit time_t values (where __time_t is 32 bits).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 9abdae94c7)
2024-05-02 13:20:27 +02:00
Florian Weimer 9831f98c26 login: Check default sizes of structs utmp, utmpx, lastlog
The default <utmp-size.h> is for ports with a 64-bit time_t.
Ports with a 32-bit time_t or with __WORDSIZE_TIME64_COMPAT32=1
need to override it.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 4d4da5aab9)
2024-05-02 13:20:27 +02:00
H.J. Lu fd658f026f elf: Also compile dl-misc.os with $(rtld-early-cflags)
Also compile dl-misc.os with $(rtld-early-cflags) to avoid

Program received signal SIGILL, Illegal instruction.
0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2",
    endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156
156	  bool positive = true;
(gdb) bt
 #0  0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2",
    endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156
 #1  0x00007ffff7fdb1a9 in tunable_initialize (
    cur=cur@entry=0x7ffff7ffbc00 <tunable_list+2176>,
    strval=strval@entry=0x7fffffffe2c9 "2", len=len@entry=1)
    at dl-tunables.c:131
 #2  0x00007ffff7fdb3a2 in parse_tunables (valstring=<optimized out>)
    at dl-tunables.c:258
 #3  0x00007ffff7fdb5d9 in __GI___tunables_init (envp=0x7fffffffdd58)
    at dl-tunables.c:288
 #4  0x00007ffff7fe44c3 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0x7fffffffdcb0,
    dl_main=dl_main@entry=0x7ffff7fe5f80 <dl_main>)
    at ../sysdeps/unix/sysv/linux/dl-sysdep.c:110
 #5  0x00007ffff7fe5cae in _dl_start_final (arg=0x7fffffffdcb0) at rtld.c:494
 #6  _dl_start (arg=0x7fffffffdcb0) at rtld.c:581
 #7  0x00007ffff7fe4b38 in _start ()
(gdb)

when setting GLIBC_TUNABLES in glibc compiled with APX.
Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 049b7684c9)
2024-04-25 08:20:19 -07:00
Florian Weimer a9a8d3eebb CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
This avoids potential memory corruption when the underlying NSS
callback function does not use the buffer space to store all strings
(e.g., for constant strings).

Instead of custom buffer management, two scratch buffers are used.
This increases stack usage somewhat.

Scratch buffer allocation failure is handled by return -1
(an invalid timeout value) instead of terminating the process.
This fixes bug 31679.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c04a21e050)
2024-04-25 15:37:18 +02:00
Florian Weimer c99f886de5 CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678)
The addgetnetgrentX call in addinnetgrX may have failed to produce
a result, so the result variable in addinnetgrX can be NULL.
Use db->negtimeout as the fallback value if there is no result data;
the timeout is also overwritten below.

Also avoid sending a second not-found response.  (The client
disconnects after receiving the first response, so the data stream did
not go out of sync even without this fix.)  It is still beneficial to
add the negative response to the mapping, so that the client can get
it from there in the future, instead of going through the socket.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit b048a482f0)
2024-04-25 15:37:18 +02:00
Florian Weimer 5a508e0b50 CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678)
If we failed to add a not-found response to the cache, the dataset
point can be null, resulting in a null pointer dereference.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 7835b00dbc)
2024-04-25 15:37:18 +02:00
Florian Weimer 1263d583d2 CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
Using alloca matches what other caches do.  The request length is
bounded by MAXKEYLEN.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 87801a8fd0)
2024-04-25 15:37:18 +02:00
H.J. Lu 2f8f157eb0 x86: Define MINIMUM_X86_ISA_LEVEL in config.h [BZ #31676]
Define MINIMUM_X86_ISA_LEVEL at configure time to avoid

/usr/bin/ld: …/build/elf/librtld.os: in function `init_cpu_features':
…/git/elf/../sysdeps/x86/cpu-features.c:1202: undefined reference to `_dl_runtime_resolve_fxsave'
/usr/bin/ld: …/build/elf/librtld.os: relocation R_X86_64_PC32 against undefined hidden symbol `_dl_runtime_resolve_fxsave' can not be used when making a shared object
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

when glibc is built with -march=x86-64-v3 and configured with
--with-rtld-early-cflags=-march=x86-64, which is used to allow ld.so to
print an error message on unsupported CPUs:

Fatal glibc error: CPU does not support x86-64-v3

This fixes BZ #31676.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>

(cherry picked from commit 46c9997413)
2024-04-25 13:16:51 +02:00
Florian Weimer e701c7d761 i386: ulp update for SSE2 --disable-multi-arch configurations
(cherry picked from commit 3a3a449742)
2024-04-25 12:58:21 +02:00
Florian Weimer e828914cf9 nptl: Fix tst-cancel30 on kernels without ppoll_time64 support
Fall back to ppoll if ppoll_time64 fails with ENOSYS.
Fixes commit 370da8a121 ("nptl: Fix
tst-cancel30 on sparc64").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit f4724843ad)
2024-04-25 12:57:32 +02:00
Charles FolandAdhemerval Zanella 31da30f23c iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
(as specified by RFC 1922).  While the SOdesignation has the expected
bounds checks, neither SS2designation nor SS3designation have its;
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.

Checked on aarch64-linux-gnu.

Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit f9dc609e06)
2024-04-17 14:05:08 -03:00
Sunil K Pandey 423099a032 x86_64: Exclude SSE, AVX and FMA4 variants in libm multiarch
When glibc is built with ISA level 3 or higher by default, the resulting
glibc binaries won't run on SSE or FMA4 processors.  Exclude SSE, AVX and
FMA4 variants in libm multiarch when ISA level 3 or higher is enabled by
default.

When glibc is built with ISA level 2 enabled by default, only keep SSE4.1
variant.

Fixes BZ 31335.

NB: elf/tst-valgrind-smoke test fails with ISA level 4, because valgrind
doesn't support AVX512 instructions:

https://bugs.kde.org/show_bug.cgi?id=383010

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 9f78a7c1d0)
2024-04-14 05:41:02 -07:00
H.J. Lu 04df8652eb Apply the Makefile sorting fix
Apply the Makefile sorting fix generated by sort-makefile-lines.py.

(cherry picked from commit ef7f4b1fef)
2024-04-14 05:41:02 -07:00
Florian Weimer edb9a76e30 powerpc: Fix ld.so address determination for PCREL mode (bug 31640)
This seems to have stopped working with some GCC 14 versions,
which clobber r2.  With other compilers, the kernel-provided
r2 value is still available at this point.

Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
(cherry picked from commit 14e56bd4ce)
2024-04-14 08:25:43 +02:00
Sunil K Pandey 7b92f46f04 x86-64: Simplify minimum ISA check ifdef conditional with if
Replace minimum ISA check ifdef conditional with if.  Since
MINIMUM_X86_ISA_LEVEL and AVX_X86_ISA_LEVEL are compile time constants,
compiler will perform constant folding optimization, getting same
results.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit b6e3898194)
2024-04-13 20:22:28 +02:00
H.J. Lu 9883f4304c x86-64: Don't use SSE resolvers for ISA level 3 or above
When glibc is built with ISA level 3 or above enabled, SSE resolvers
aren't available and glibc fails to build:

ld: .../elf/librtld.os: in function `init_cpu_features':
.../elf/../sysdeps/x86/cpu-features.c:1200:(.text+0x1445f): undefined reference to `_dl_runtime_resolve_fxsave'
ld: .../elf/librtld.os: relocation R_X86_64_PC32 against undefined hidden symbol `_dl_runtime_resolve_fxsave' can not be used when making a shared object
/usr/local/bin/ld: final link failed: bad value

For ISA level 3 or above, don't use _dl_runtime_resolve_fxsave nor
_dl_tlsdesc_dynamic_fxsave.

This fixes BZ #31429.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>

(cherry picked from commit befe2d3c4d)
2024-04-13 17:55:54 +02:00
Wilco Dijkstra 9d92452c70 AArch64: Check kernel version for SVE ifuncs
Old Linux kernels disable SVE after every system call.  Calling the
SVE-optimized memcpy afterwards will then cause a trap to reenable SVE.
As a result, applications with a high use of syscalls may run slower with
the SVE memcpy.  This is true for kernels between 4.15.0 and before 6.2.0,
except for 5.14.0 which was patched.  Avoid this by checking the kernel
version and selecting the SVE ifunc on modern kernels.

Parse the kernel version reported by uname() into a 24-bit kernel.major.minor
value without calling any library functions.  If uname() is not supported or
if the version format is not recognized, assume the kernel is modern.

Tested-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 2e94e2f5d2)
2024-04-09 19:58:25 +01:00
Szabolcs Nagy 395a89f61e aarch64: fix check for SVE support in assembler
Due to GCC bug 110901 -mcpu can override -march setting when compiling
asm code and thus a compiler targetting a specific cpu can fail the
configure check even when binutils gas supports SVE.

The workaround is that explicit .arch directive overrides both -mcpu
and -march, and since that's what the actual SVE memcpy uses the
configure check should use that too even if the GCC issue is fixed
independently.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 73c26018ed)
2024-04-09 19:58:15 +01:00
Joe Ramsay b0e0a07018 aarch64/fpu: Sync libmvec routines from 2.39 and before with AOR
This includes a fix for big-endian in AdvSIMD log, some cosmetic
changes, and numerous small optimisations mainly around inlining and
using indexed variants of MLA intrinsics.
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

(cherry picked from commit e302e10213)
2024-04-09 19:58:04 +01:00
Florian Weimer 31c7d69af5 i386: Use generic memrchr in libc (bug 31316)
Before this change, we incorrectly used the SSE2 variant in the
implementation, without checking that the system actually supports
SSE2.

Tested-by: Sam James <sam@gentoo.org>
(cherry picked from commit 0d9166c224)
2024-04-07 00:41:35 +02:00
Adhemerval Zanella 5d070d12b3 x86: Expand the comment on when REP STOSB is used on memset
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 491e55beab)
2024-04-04 12:12:19 +02:00
Adhemerval Zanella 6484a92698 x86: Do not prefer ERMS for memset on Zen3+
For AMD Zen3+ architecture, the performance of the vectorized loop is
slightly better than ERMS.

Checked on x86_64-linux-gnu on Zen3.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 272708884c)
2024-04-04 12:12:11 +02:00
Adhemerval Zanella aa4249266e x86: Fix Zen3/Zen4 ERMS selection (BZ 30994)
The REP MOVSB usage on memcpy/memmove does not show much performance
improvement on Zen3/Zen4 cores compared to the vectorized loops.  Also,
as from BZ 30994, if the source is aligned and the destination is not
the performance can be 20x slower.

The performance difference is noticeable with small buffer sizes, closer
to the lower bounds limits when memcpy/memmove starts to use ERMS.  The
performance of REP MOVSB is similar to vectorized instruction on the
size limit (the L2 cache).  Also, there is no drawback to multiple cores
sharing the cache.

Checked on x86_64-linux-gnu on Zen3.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 0c0d39fe4a)
2024-04-04 12:11:58 +02:00
Andreas Schwab 5a461f2949 Add tst-gnu2-tls2mod1 to test-internal-extras
That allows sysdeps/x86_64/tst-gnu2-tls2mod1.S to use internal headers.

Fixes: 717ebfa85c ("x86-64: Allocate state buffer space for RDI, RSI and RBX")
(cherry picked from commit fd7ee2e6c5)
2024-04-02 06:22:06 -07:00
Adhemerval Zanella aded2fc004 elf: Enable TLS descriptor tests on aarch64
The aarch64 uses 'trad' for traditional tls and 'desc' for tls
descriptors, but unlike other targets it defaults to 'desc'.  The
gnutls2 configure check does not set aarch64 as an ABI that uses
TLS descriptors, which then disable somes stests.

Also rename the internal machinery fron gnu2 to tls descriptors.

Checked on aarch64-linux-gnu.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 3d53d18fc7)
2024-04-01 11:16:32 -07:00
Adhemerval Zanella a8ba52bde5 arm: Update _dl_tlsdesc_dynamic to preserve caller-saved registers (BZ 31372)
ARM _dl_tlsdesc_dynamic slow path has two issues:

  * The ip/r12 is defined by AAPCS as a scratch register, and gcc is
    used to save the stack pointer before on some function calls.  So it
    should also be saved/restored as well.  It fixes the tst-gnu2-tls2.

  * None of the possible VFP registers are saved/restored.  ARM has the
    additional complexity to have different VFP bank sizes (depending of
    VFP support by the chip).

The tst-gnu2-tls2 test is extended to check for VFP registers, although
only for hardfp builds.  Different than setcontext, _dl_tlsdesc_dynamic
does not have  HWCAP_ARM_IWMMXT (I don't have a way to properly test
it and it is almost a decade since newer hardware was released).

With this patch there is no need to mark tst-gnu2-tls2 as XFAIL.

Checked on arm-linux-gnueabihf.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 64c7e34428)
2024-04-01 11:16:27 -07:00
Adhemerval Zanella 15aebdbada Ignore undefined symbols for -mtls-dialect=gnu2
So it does not fail for arm config that defaults to -mtp=soft (which
issues a call to __aeabi_read_tp).
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 968b0ca944)
2024-04-01 11:16:20 -07:00
H.J. Lu 354cabcb26 x86-64: Allocate state buffer space for RDI, RSI and RBX
_dl_tlsdesc_dynamic preserves RDI, RSI and RBX before realigning stack.
After realigning stack, it saves RCX, RDX, R8, R9, R10 and R11.  Define
TLSDESC_CALL_REGISTER_SAVE_AREA to allocate space for RDI, RSI and RBX
to avoid clobbering saved RDI, RSI and RBX values on stack by xsave to
STATE_SAVE_OFFSET(%rsp).

   +==================+<- stack frame start aligned at 8 or 16 bytes
   |                  |<- RDI saved in the red zone
   |                  |<- RSI saved in the red zone
   |                  |<- RBX saved in the red zone
   |                  |<- paddings for stack realignment of 64 bytes
   |------------------|<- xsave buffer end aligned at 64 bytes
   |                  |<-
   |                  |<-
   |                  |<-
   |------------------|<- xsave buffer start at STATE_SAVE_OFFSET(%rsp)
   |                  |<- 8-byte padding for 64-byte alignment
   |                  |<- 8-byte padding for 64-byte alignment
   |                  |<- R11
   |                  |<- R10
   |                  |<- R9
   |                  |<- R8
   |                  |<- RDX
   |                  |<- RCX
   +==================+<- RSP aligned at 64 bytes

Define TLSDESC_CALL_REGISTER_SAVE_AREA, the total register save area size
for all integer registers by adding 24 to STATE_SAVE_OFFSET since RDI, RSI
and RBX are saved onto stack without adjusting stack pointer first, using
the red-zone.  This fixes BZ #31501.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>

(cherry picked from commit 717ebfa85c)
2024-04-01 11:16:14 -07:00
H.J. Lu 853e915fdd x86-64: Update _dl_tlsdesc_dynamic to preserve AMX registers
_dl_tlsdesc_dynamic should also preserve AMX registers which are
caller-saved.  Add X86_XSTATE_TILECFG_ID and X86_XSTATE_TILEDATA_ID
to x86-64 TLSDESC_CALL_STATE_SAVE_MASK.  Compute the AMX state size
and save it in xsave_state_full_size which is only used by
_dl_tlsdesc_dynamic_xsave and _dl_tlsdesc_dynamic_xsavec.  This fixes
the AMX part of BZ #31372.  Tested on AMX processor.

AMX test is enabled only for compilers with the fix for

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114098

GCC 14 and GCC 11/12/13 branches have the bug fix.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>

(cherry picked from commit 9b7091415a)
2024-04-01 10:55:17 -07:00
H.J. Lu a364304718 x86: Update _dl_tlsdesc_dynamic to preserve caller-saved registers
Compiler generates the following instruction sequence for GNU2 dynamic
TLS access:

	leaq	tls_var@TLSDESC(%rip), %rax
	call	*tls_var@TLSCALL(%rax)

or

	leal	tls_var@TLSDESC(%ebx), %eax
	call	*tls_var@TLSCALL(%eax)

CALL instruction is transparent to compiler which assumes all registers,
except for EFLAGS and RAX/EAX, are unchanged after CALL.  When
_dl_tlsdesc_dynamic is called, it calls __tls_get_addr on the slow
path.  __tls_get_addr is a normal function which doesn't preserve any
caller-saved registers.  _dl_tlsdesc_dynamic saved and restored integer
caller-saved registers, but didn't preserve any other caller-saved
registers.  Add _dl_tlsdesc_dynamic IFUNC functions for FNSAVE, FXSAVE,
XSAVE and XSAVEC to save and restore all caller-saved registers.  This
fixes BZ #31372.

Add GLRO(dl_x86_64_runtime_resolve) with GLRO(dl_x86_tlsdesc_dynamic)
to optimize elf_machine_runtime_setup.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>

(cherry picked from commit 0aac205a81)
2024-04-01 10:42:25 -07:00
H.J. Lu 7fc8242bf8 x86-64: Save APX registers in ld.so trampoline
Add APX registers to STATE_SAVE_MASK so that APX registers are saved in
ld.so trampoline.  This fixes BZ #31371.

Also update STATE_SAVE_OFFSET and STATE_SAVE_MASK for i386 which will
be used by i386 _dl_tlsdesc_dynamic.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>

(cherry picked from commit dfb05f8e70)
2024-04-01 10:38:15 -07:00
caiyinyu 983f34a125 LoongArch: Correct {__ieee754, _}_scalb -> {__ieee754, _}_scalbf 2024-03-22 09:29:44 +08:00
Amrita H S aad45c8ac3 powerpc: Placeholder and infrastructure/build support to add Power11 related changes.
The following three changes have been added to provide initial Power11 support.
    1. Add the directories to hold Power11 files.
    2. Add support to select Power11 libraries based on AT_PLATFORM.
    3. Let submachine=power11 be set automatically.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
(cherry picked from commit 1ea0511456)
2024-03-20 19:43:40 -05:00
Manjunath Matti ee7f4c54e1 powerpc: Add HWCAP3/HWCAP4 data to TCB for Power Architecture.
This patch adds a new feature for powerpc.  In order to get faster
access to the HWCAP3/HWCAP4 masks, similar to HWCAP/HWCAP2 (i.e. for
implementing __builtin_cpu_supports() in GCC) without the overhead of
reading them from the auxiliary vector, we now reserve space for them
in the TCB.

Suggested-by: Peter Bergner <bergner@linux.ibm.com>
Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
(cherry picked from commit 3ab9b88e2a)
2024-03-20 18:09:32 -05:00
Florian Weimer 71fcdba577 linux: Use rseq area unconditionally in sched_getcpu (bug 31479)
Originally, nptl/descr.h included <sys/rseq.h>, but we removed that
in commit 2c6b4b272e ("nptl:
Unconditionally use a 32-byte rseq area").  After that, it was
not ensured that the RSEQ_SIG macro was defined during sched_getcpu.c
compilation that provided a definition.  This commit always checks
the rseq area for CPU number information before using the other
approaches.

This adds an unnecessary (but well-predictable) branch on
architectures which do not define RSEQ_SIG, but its cost is small
compared to the system call.  Most architectures that have vDSO
acceleration for getcpu also have rseq support.

Fixes: 2c6b4b272e
Fixes: 1d350aa060
Reviewed-by: Arjun Shankar <arjun@redhat.com>
(cherry picked from commit 7a76f21867)
2024-03-18 11:28:19 +01:00
Jakub Jelinek 1b9c1a0047 Use gcc __builtin_stdc_* builtins in stdbit.h if possible
The following patch uses the GCC 14 __builtin_stdc_* builtins in stdbit.h
for the type-generic macros, so that when compiled with GCC 14 or later,
it supports not just 8/16/32/64-bit unsigned integers, but also 128-bit
(if target supports them) and unsigned _BitInt (any supported precision).
And so that the macros don't expand arguments multiple times and can be
evaluated in constant expressions.

The new testcase is gcc's gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c
adjusted to test stdbit.h and the type-generic macros in there instead
of the builtins and adjusted to use glibc test framework rather than
gcc style tests with __builtin_abort ().

Signed-off-by: Jakub Jelinek <jakub@redhat.com>
Reviewed-by: Joseph Myers <josmyers@redhat.com>
(cherry picked from commit da89496337)
2024-03-04 12:56:27 +01:00
Stefan Liebler e0910f1d32 S390: Do not clobber r7 in clone [BZ #31402]
Starting with commit e57d8fc97b
"S390: Always use svc 0"
clone clobbers the call-saved register r7 in error case:
function or stack is NULL.

This patch restores the saved registers also in the error case.
Furthermore the existing test misc/tst-clone is extended to check
all error cases and that clone does not clobber registers in this
error case.

(cherry picked from commit 02782fd128)
2024-02-27 11:08:08 +01:00
Xi Ruoyao d0724994de math: Update mips64 ulps
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
(cherry picked from commit e2a65ecc4b)
2024-02-22 21:29:26 +01:00
Adhemerval Zanella 312e159626 mips: FIx clone3 implementation (BZ 31325)
For o32 we need to setup a minimal stack frame to allow cprestore
on __thread_start_clone3 (which instruct the linker to save the
gp for PIC).  Also, there is no guarantee by kABI that $8 will be
preserved after syscall execution, so we need to save it on the
provided stack.

Checked on mipsel-linux-gnu.

Reported-by: Khem Raj <raj.khem@gmail.com>
Tested-by: Khem Raj <raj.khem@gmail.com>
(cherry picked from commit bbd248ac0d)
2024-02-12 11:45:12 -03:00
Adhemerval Zanella 63295e4fda arm: Remove wrong ldr from _dl_start_user (BZ 31339)
The commit 49d877a80b (arm: Remove
_dl_skip_args usage) removed the _SKIP_ARGS literal, which was
previously loader to r4 on loader _start.  However, the cleanup did not
remove the following 'ldr r4, [sl, r4]' on _dl_start_user, used to check
to skip the arguments after ld self-relocations.

In my testing, the kernel initially set r4 to 0, which makes the
ldr instruction just read the _GLOBAL_OFFSET_TABLE_.  However, since r4
is a callee-saved register; a different runtime might not zero
initialize it and thus trigger an invalid memory access.

Checked on arm-linux-gnu.

Reported-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 1e25112dc0)
2024-02-05 15:43:39 -03:00
Andreas K. Hüttel 6d1e3fb07b Replace advisories directory
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2024-01-31 02:12:43 +01:00
708 changed files with 24188 additions and 11790 deletions
+2
View File
@@ -0,0 +1,2 @@
For the GNU C Library Security Advisories, see the git master branch:
https://sourceware.org/git/?p=glibc.git;a=tree;f=advisories;hb=HEAD
+27 -3
View File
@@ -360,6 +360,8 @@ whole-archive = -Wl,--whole-archive
# Installed name of the startup code.
# The ELF convention is that the startfile is called crt1.o
start-installed-name = crt1.o
# Similar to crt1.o, but without _IO_stdin_used.
start-name-2.0 = crt1-2.0.o
# On systems that do not need a special startfile for statically linked
# binaries, simply set it to the normal name.
ifndef static-start-installed-name
@@ -537,6 +539,25 @@ else # build-static
endif # build-shared
endif # +link
# Command for linking test programs with crt1.o from glibc 2.0.
+link-2.0-before-inputs = -nostdlib -nostartfiles $(no-pie-ldflag) \
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
$(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-name-2.0)) \
$(+preinit) $(+prector)
+link-2.0-before-libc = -o $@ $(+link-2.0-before-inputs) \
$(filter-out $(addprefix $(csu-objpfx),start.o \
$(start-name-2.0))\
$(+preinit) $(link-extra-libs) \
$(common-objpfx)libc% $(+postinit),$^) \
$(link-extra-libs)
+link-after-libc = $(+postctor) $(+postinit)
define +link-2.0-tests
$(CC) $(+link-2.0-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
$(+link-after-libc)
$(call after-link,$@)
endef
# The pretty printer test programs need to be compiled without optimizations
# so they won't confuse gdb. We could use either the 'GCC optimize' pragma
# or the 'optimize' function attribute to achieve this; however, at least on
@@ -586,10 +607,13 @@ link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
# before the expansion of LDLIBS-* variables).
# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
# build-hardcoded-path-in-tests.
# build-hardcoded-path-in-tests. Add -Wl,--disable-new-dtags to force
# DT_RPATH instead of DT_RUNPATH which only applies to DT_NEEDED entries
# in the executable and doesn't applies to DT_NEEDED entries in shared
# libraries which are loaded via DT_NEEDED entries in the executable.
ifeq (yes,$(build-hardcoded-path-in-tests))
link-libc-tests-rpath-link = $(link-libc-rpath)
link-test-modules-rpath-link = $(link-libc-rpath)
link-libc-tests-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
link-test-modules-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
else
link-libc-tests-rpath-link = $(link-libc-rpath-link)
link-test-modules-rpath-link =
+8
View File
@@ -577,6 +577,14 @@ $(objpfx)lint-makefiles.out: scripts/lint-makefiles.sh
$(SHELL) $< "$(PYTHON)" `pwd` > $@ ; \
$(evaluate-test)
# Link libc.a as a whole to verify that it does not contain multiple
# definitions of any symbols.
tests-special += $(objpfx)link-static-libc.out
$(objpfx)link-static-libc.out:
$(LINK.o) $(whole-archive) -nostdlib -nostartfiles -r \
$(objpfx)libc.a -o /dev/null > $@ 2>&1; \
$(evaluate-test)
# Print test summary for tests in $1 .sum file;
# $2 is optional test identifier.
# Fail if there are unexpected failures in the test results.
+111
View File
@@ -5,6 +5,117 @@ 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.39.1
Deprecated and removed features, and other changes affecting compatibility:
* __rseq_size now denotes the size of the active rseq area (20 bytes
initially), not the size of struct rseq (32 bytes initially).
Security related changes:
The following CVEs were fixed in this release:
GLIBC-SA-2024-0004:
ISO-2022-CN-EXT: fix out-of-bound writes when writing escape
sequence (CVE-2024-2961)
GLIBC-SA-2024-0005:
nscd: Stack-based buffer overflow in netgroup cache (CVE-2024-33599)
GLIBC-SA-2024-0006:
nscd: Null pointer crash after notfound response (CVE-2024-33600)
GLIBC-SA-2024-0007:
nscd: netgroup cache may terminate daemon on memory allocation
failure (CVE-2024-33601)
GLIBC-SA-2024-0008:
nscd: netgroup cache assumes NSS callback uses in-buffer strings
(CVE-2024-33602)
GLIBC-SA-2025-0001:
assert: Buffer overflow when printing assertion failure message
(CVE-2025-0395)
GLIBC-SA-2026-0003
wordexp with WRDE_REUSE and WRDE_APPEND may return uninitialized
memory (CVE-2025-15281)
The following bugs are resolved with this release:
[19341] ctype: Fallback initialization of TLS using relocations
[19622] network: Support aliasing with struct sockaddr
[27821] ungetc: Fix backup buffer leak on program exit
[30081] resolv: Do not wait for non-existing second DNS response after error
[30701] time: getutxent misbehaves on 32-bit x86 when _TIME_BITS=64
[30994] REP MOVSB performance suffers from page aliasing on Zen 4
[31339] libc: arm32 loader crash after cleanup in 2.36
[31325] mips: clone3 is wrong for o32
[31335] math: Compile glibc with -march=x86-64-v3 should disable FMA4
multi-arch version
[31402] libc: clone (NULL, NULL, ...) clobbers %r7 register on
s390{,x}
[31479] libc: Missing #include <sys/rseq.h> in sched_getcpu.c may
result in a loss of rseq acceleration
[31316] build: Fails test misc/tst-dirname "Didn't expect signal from
child: got `Illegal instruction'" on non SSE CPUs
[31371] x86-64: APX and Tile registers aren't preserved in ld.so
trampoline
[31372] dynamic-link: _dl_tlsdesc_dynamic doesn't preserve all caller-
saved registers
[31429] build: Glibc failed to build with -march=x86-64-v3
[31476] resolv: Track single-request fallback via _res._flags
[31501] dynamic-link: _dl_tlsdesc_dynamic_xsavec may clobber %rbx
[31612] libc: arc4random fails to fallback to /dev/urandom if
getrandom is not present
[31640] dynamic-link: POWER10 ld.so crashes in
elf_machine_load_address with GCC 14
[31676] Configuring with CC="gcc -march=x86-64-v3"
--with-rtld-early-cflags=-march=x86-64 results in linker failure
[31677] nscd: nscd: netgroup cache: invalid memcpy under low
memory/storage conditions
[31678] nscd: nscd: Null pointer dereferences after failed netgroup
cache insertion
[31679] nscd: nscd: netgroup cache may terminate daemon on memory
allocation failure
[31680] nscd: nscd: netgroup cache assumes NSS callback uses in-buffer
strings
[31686] dynamic-link: Stack-based buffer overflow in
parse_tunables_string
[31695] libc: pidfd_spawn/pidfd_spawnp leak an fd if clone3 succeeds
[31717] elf: Avoid re-initializing already allocated TLS in dlopen
[31719] dynamic-link: --enable-hardcoded-path-in-tests doesn't work
with -Wl,--enable-new-dtags
[31782] Test build failure with recent GCC trunk
(x86/tst-cpu-features-supports.c:69:3: error: parameter to builtin
not valid: avx5124fmaps)
[31798] pidfd_getpid.c is miscompiled by GCC 6.4
[31840] Remove memory leak in fdopen
[31867] build: "CPU ISA level is lower than required" on SSE2-free
CPUs
[31883] build: ISA level support configure check relies on bashism /
is otherwise broken for arithmetic
[31890] resolv: Allow short error responses to match any DNS query
[31943] _dl_find_object can fail if ld.so contains gaps between load segments
[31965] rseq extension mechanism does not work as intended
[31968] mremap implementation in C does not handle arguments correctly
[32026] strerror/strsignal TLS not handled correctly for secondary namespaces
[32052] Name space violation in fortify wrappers
[32137] libio: Attempt wide backup free only for non-legacy code
[32231] elf: Change ldconfig auxcache magic number
[32470] x86: Avoid integer truncation with large cache sizes
[32582] Fix underallocation of abort_msg_s struct (CVE-2025-0395)
[32810] Crash on x86-64 if XSAVEC disable via tunable
[32987] elf: Fix subprocess status handling for tst-dlopen-sgid
[33185] Fix double-free after allocation failure in regcomp
[32483] ctype macros segfault in multithreaded programs with multiple libc.so
[33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables
[33361] nss: Group merge does not react to ERANGE during merge
[33601] aarch64: Do not link conform tests with -Wl,-z,force-bti
[33814] glob: wordexp with WRDE_REUSE and WRDE_APPEND may return
uninitialized memory
Version 2.39
Major new features:
+12 -1
View File
@@ -188,6 +188,7 @@ binaries-all = $(binaries-all-notests) $(binaries-all-tests)
binaries-static-notests = $(others-static)
binaries-static-tests = $(tests-static) $(xtests-static)
binaries-static = $(binaries-static-notests) $(binaries-static-tests)
binaries-shared-2.0-tests = $(tests-2.0)
ifeq (yesyes,$(have-fpie)$(build-shared))
binaries-pie-tests = $(tests-pie) $(xtests-pie)
binaries-pie-notests = $(others-pie)
@@ -215,7 +216,8 @@ binaries-malloc-hugetlb2-tests =
endif
binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests)
binaries-shared-tests = $(filter-out $(binaries-pie) $(binaries-static), \
binaries-shared-tests = $(filter-out $(binaries-pie) $(binaries-static) \
$(binaries-shared-2.0-tests), \
$(binaries-all-tests))
binaries-shared-notests = $(filter-out $(binaries-pie) $(binaries-static), \
$(binaries-all-notests))
@@ -235,6 +237,15 @@ $(addprefix $(objpfx),$(binaries-shared-tests)): %: %.o \
$(+link-tests)
endif
# Linking test programs with crt1.o from glibc 2.0.
ifneq "$(strip $(binaries-shared-2.0-tests))" ""
$(addprefix $(objpfx),$(binaries-shared-2.0-tests)): %: %.o \
$(link-extra-libs-tests) \
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
$(+link-2.0-tests)
endif
ifneq "$(strip $(binaries-mcheck-tests))" ""
$(addprefix $(objpfx),$(binaries-mcheck-tests)): %-mcheck: %.o \
$(link-extra-libs-tests) \
-14
View File
@@ -1,14 +0,0 @@
printf: incorrect output for integers with thousands separator and width field
When the printf family of functions is called with a format specifier
that uses an <apostrophe> (enable grouping) and a minimum width
specifier, the resulting output could be larger than reasonably expected
by a caller that computed a tight bound on the buffer size. The
resulting larger than expected output could result in a buffer overflow
in the printf family of functions.
CVE-Id: CVE-2023-25139
Public-Date: 2023-02-02
Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37)
Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38)
Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4)
-15
View File
@@ -1,15 +0,0 @@
getaddrinfo: Stack read overflow in no-aaaa mode
If the system is configured in no-aaaa mode via /etc/resolv.conf,
getaddrinfo is called for the AF_UNSPEC address family, and a DNS
response is received over TCP that is larger than 2048 bytes,
getaddrinfo may potentially disclose stack contents via the returned
address data, or crash.
CVE-Id: CVE-2023-4527
Public-Date: 2023-09-12
Vulnerable-Commit: f282cdbe7f436c75864e5640a409a10485e9abb2 (2.36)
Fix-Commit: bd77dd7e73e3530203be1c52c8a29d08270cb25d (2.39)
Fix-Commit: 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f (2.36-113)
Fix-Commit: b7529346025a130fee483d42178b5c118da971bb (2.37-38)
Fix-Commit: b25508dd774b617f99419bdc3cf2ace4560cd2d6 (2.38-19)
-15
View File
@@ -1,15 +0,0 @@
getaddrinfo: Potential use-after-free
When an NSS plugin only implements the _gethostbyname2_r and
_getcanonname_r callbacks, getaddrinfo could use memory that was freed
during buffer resizing, potentially causing a crash or read or write to
arbitrary memory.
CVE-Id: CVE-2023-4806
Public-Date: 2023-09-12
Fix-Commit: 973fe93a5675c42798b2161c6f29c01b0e243994 (2.39)
Fix-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
Fix-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
Fix-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
Fix-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
Fix-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
-16
View File
@@ -1,16 +0,0 @@
tunables: local privilege escalation through buffer overflow
If a tunable of the form NAME=NAME=VAL is passed in the environment of a
setuid program and NAME is valid, it may result in a buffer overflow,
which could be exploited to achieve escalated privileges. This flaw was
introduced in glibc 2.34.
CVE-Id: CVE-2023-4911
Public-Date: 2023-10-03
Vulnerable-Commit: 2ed18c5b534d9e92fc006202a5af0df6b72e7aca (2.34)
Fix-Commit: 1056e5b4c3f2d90ed2b4a55f96add28da2f4c8fa (2.39)
Fix-Commit: dcc367f148bc92e7f3778a125f7a416b093964d9 (2.34-423)
Fix-Commit: c84018a05aec80f5ee6f682db0da1130b0196aef (2.35-274)
Fix-Commit: 22955ad85186ee05834e47e665056148ca07699c (2.36-118)
Fix-Commit: b4e23c75aea756b4bddc4abcf27a1c6dca8b6bd3 (2.37-45)
Fix-Commit: 750a45a783906a19591fb8ff6b7841470f1f5701 (2.38-27)
-18
View File
@@ -1,18 +0,0 @@
getaddrinfo: DoS due to memory leak
The fix for CVE-2023-4806 introduced a memory leak when an application
calls getaddrinfo for AF_INET6 with AI_CANONNAME, AI_ALL and AI_V4MAPPED
flags set.
CVE-Id: CVE-2023-5156
Public-Date: 2023-09-25
Vulnerable-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420)
Vulnerable-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270)
Vulnerable-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115)
Vulnerable-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39)
Vulnerable-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20)
Fix-Commit: 8006457ab7e1cd556b919f477348a96fe88f2e49 (2.34-421)
Fix-Commit: 17092c0311f954e6f3c010f73ce3a78c24ac279a (2.35-272)
Fix-Commit: 856bac55f98dc840e7c27cfa82262b933385de90 (2.36-116)
Fix-Commit: 4473d1b87d04b25cdd0e0354814eeaa421328268 (2.37-42)
Fix-Commit: 5ee59ca371b99984232d7584fe2b1a758b4421d3 (2.38-24)
-15
View File
@@ -1,15 +0,0 @@
syslog: Heap buffer overflow in __vsyslog_internal
__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER
containing a long program name failed to update the required buffer
size, leading to the allocation and overflow of a too-small buffer on
the heap.
CVE-Id: CVE-2023-6246
Public-Date: 2024-01-30
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
Fix-Commit: 6bd0e4efcc78f3c0115e5ea9739a1642807450da (2.39)
Fix-Commit: 23514c72b780f3da097ecf33a793b7ba9c2070d2 (2.38-42)
Fix-Commit: 97a4292aa4a2642e251472b878d0ec4c46a0e59a (2.37-57)
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
Fix-Commit: d1a83b6767f68b3cb5b4b4ea2617254acd040c82 (2.36-126)
-15
View File
@@ -1,15 +0,0 @@
syslog: Heap buffer overflow in __vsyslog_internal
__vsyslog_internal used the return value of snprintf/vsnprintf to
calculate buffer sizes for memory allocation. If these functions (for
any reason) failed and returned -1, the resulting buffer would be too
small to hold output.
CVE-Id: CVE-2023-6779
Public-Date: 2024-01-30
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
Fix-Commit: 7e5a0c286da33159d47d0122007aac016f3e02cd (2.39)
Fix-Commit: d0338312aace5bbfef85e03055e1212dd0e49578 (2.38-43)
Fix-Commit: 67062eccd9a65d7fda9976a56aeaaf6c25a80214 (2.37-58)
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
Fix-Commit: 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 (2.36-127)
-13
View File
@@ -1,13 +0,0 @@
syslog: Integer overflow in __vsyslog_internal
__vsyslog_internal calculated a buffer size by adding two integers, but
did not first check if the addition would overflow.
CVE-Id: CVE-2023-6780
Public-Date: 2024-01-30
Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37)
Fix-Commit: ddf542da94caf97ff43cc2875c88749880b7259b (2.39)
Fix-Commit: d37c2b20a4787463d192b32041c3406c2bd91de0 (2.38-44)
Fix-Commit: 2b58cba076e912961ceaa5fa58588e4b10f791c0 (2.37-59)
Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16)
Fix-Commit: b9b7d6a27aa0632f334352fa400771115b3c69b7 (2.36-128)
-73
View File
@@ -1,73 +0,0 @@
GNU C Library Security Advisory Format
======================================
Security advisories in this directory follow a simple git commit log
format, with a heading and free-format description augmented with tags
to allow parsing key information. References to code changes are
specific to the glibc repository and follow a specific format:
Tag-name: <commit-ref> (release-version)
The <commit-ref> indicates a specific commit in the repository. The
release-version indicates the publicly consumable release in which this
commit is known to exist. The release-version is derived from the
git-describe format, (i.e. stripped out from glibc-2.34.NNN-gxxxx) and
is of the form 2.34-NNN. If the -NNN suffix is absent, it means that
the change is in that release tarball, otherwise the change is on the
release/2.YY/master branch and not in any released tarball.
The following tags are currently being used:
CVE-Id:
This is the CVE-Id assigned under the CVE Program
(https://www.cve.org/).
Public-Date:
The date this issue became publicly known.
Vulnerable-Commit:
The commit that introduced this vulnerability. There could be multiple
entries, one for each release branch in the glibc repository; the
release-version portion of this tag should tell you which branch this is
on.
Fix-Commit:
The commit that fixed this vulnerability. There could be multiple
entries for each release branch in the glibc repository, indicating that
all of those commits contributed to fixing that issue in each of those
branches.
Adding an Advisory
------------------
An advisory for a CVE needs to be added on the master branch in two steps:
1. Add the text of the advisory without any Fix-Commit tags along with
the fix for the CVE. Add the Vulnerable-Commit tag, if applicable.
The advisories directory does not exist in release branches, so keep
the advisory text commit distinct from the code changes, to ease
backports. Ask for the GLIBC-SA advisory number from the security
team.
2. Finish all backports on release branches and then back on the msater
branch, add all commit refs to the advisory using the Fix-Commit
tags. Don't bother adding the release-version subscript since the
next step will overwrite it.
3. Run the process-advisories.sh script in the scripts directory on the
advisory:
scripts/process-advisories.sh update GLIBC-SA-YYYY-NNNN
(replace YYYY-NNNN with the actual advisory number).
4. Verify the updated advisory and push the result.
Getting a NEWS snippet from advisories
--------------------------------------
Run:
scripts/process-advisories.sh news
and copy the content into the NEWS file.
+1
View File
@@ -38,6 +38,7 @@ tests := \
test-assert-perr \
tst-assert-c++ \
tst-assert-g++ \
tst-assert-sa-2025-0001 \
# tests
ifeq ($(have-cxx-thread_local),yes)
+3 -1
View File
@@ -18,6 +18,7 @@
#include <assert.h>
#include <atomic.h>
#include <ldsodefs.h>
#include <libc-pointer-arith.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +66,8 @@ __assert_fail_base (const char *fmt, const char *assertion, const char *file,
(void) __fxprintf (NULL, "%s", str);
(void) fflush (stderr);
total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
total = ALIGN_UP (total + sizeof (struct abort_msg_s) + 1,
GLRO(dl_pagesize));
struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (__glibc_likely (buf != MAP_FAILED))
+92
View File
@@ -0,0 +1,92 @@
/* Test for CVE-2025-0395.
Copyright The GNU Toolchain Authors.
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/>. */
/* Test that a large enough __progname does not result in a buffer overflow
when printing an assertion failure. This was CVE-2025-0395. */
#include <assert.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
#include <support/check.h>
#include <support/support.h>
#include <support/xstdio.h>
#include <support/xunistd.h>
extern const char *__progname;
int
do_test (int argc, char **argv)
{
support_need_proc ("Reads /proc/self/maps to add guards to writable maps.");
ignore_stderr ();
/* XXX assumes that the assert is on a 2 digit line number. */
const char *prompt = ": %s:99: do_test: Assertion `argc < 1' failed.\n";
int ret = fprintf (stderr, prompt, __FILE__);
if (ret < 0)
FAIL_EXIT1 ("fprintf failed: %m\n");
size_t pagesize = getpagesize ();
size_t namesize = pagesize - 1 - ret;
/* Alter the progname so that the assert message fills the entire page. */
char progname[namesize];
memset (progname, 'A', namesize - 1);
progname[namesize - 1] = '\0';
__progname = progname;
FILE *f = xfopen ("/proc/self/maps", "r");
char *line = NULL;
size_t len = 0;
uintptr_t prev_to = 0;
/* Pad the beginning of every writable mapping with a PROT_NONE map. This
ensures that the mmap in the assert_fail path never ends up below a
writable map and will terminate immediately in case of a buffer
overflow. */
while (xgetline (&line, &len, f))
{
uintptr_t from, to;
char perm[4];
sscanf (line, "%" SCNxPTR "-%" SCNxPTR " %c%c%c%c ",
&from, &to,
&perm[0], &perm[1], &perm[2], &perm[3]);
bool writable = (memchr (perm, 'w', 4) != NULL);
if (prev_to != 0 && from - prev_to > pagesize && writable)
xmmap ((void *) from - pagesize, pagesize, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
prev_to = to;
}
xfclose (f);
assert (argc < 1);
return 0;
}
#define EXPECTED_SIGNAL SIGABRT
#define TEST_FUNCTION_ARGV do_test
#include <support/test-driver.c>
+1
View File
@@ -1,6 +1,7 @@
## args: double
## ret: double
## includes: math.h
## name: workload-random
0x1.5a2730bacd94ap-1
-0x1.b57eb40fc048ep-21
-0x1.c0b185fb450e2p-17
+1
View File
@@ -1,6 +1,7 @@
## args: double
## ret: double
## includes: math.h
## name: workload-random
0x1.bcb6129b5ff2bp8
-0x1.63057386325ebp9
0x1.62f1d7dc4e8bfp9
+2 -2
View File
@@ -149,7 +149,7 @@ enum __socket_type
#include <bits/sockaddr.h>
/* Structure describing a generic socket address. */
struct sockaddr
struct __attribute_struct_may_alias__ sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
@@ -166,7 +166,7 @@ struct sockaddr
#define _SS_PADSIZE \
(_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
struct sockaddr_storage
struct __attribute_struct_may_alias__ sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
char __ss_padding[_SS_PADSIZE];
+4 -2
View File
@@ -21,7 +21,9 @@
#define __WORDSIZE32_PTRDIFF_LONG
/* Set to 1 in order to force time types to be 32 bits instead of 64 bits in
struct lastlog and struct utmp{,x} on 64-bit ports. This may be done in
struct lastlog and struct utmp{,x}. This may be done in
order to make 64-bit ports compatible with 32-bit ports. Set to 0 for
64-bit ports where the time types are 64-bits or for any 32-bit ports. */
64-bit ports where the time types are 64-bits and new 32-bit ports
where time_t is 64 bits, and there is no companion architecture with
32-bit time_t. */
#define __WORDSIZE_TIME64_COMPAT32
+9
View File
@@ -141,6 +141,9 @@
/* LOONGARCH floating-point ABI for ld.so. */
#undef LOONGARCH_ABI_FRLEN
/* Define whether ARM used hard-float and support VFPvX-D32. */
#undef HAVE_ARM_PCS_VFP_D32
/* Linux specific: minimum supported kernel version. */
#undef __LINUX_KERNEL_VERSION
@@ -283,10 +286,16 @@
/* Define if x86 ISA level should be included in shared libraries. */
#undef INCLUDE_X86_ISA_LEVEL
/* The x86 ISA level. 1 for baseline. Undefined on non-x86. */
#undef MINIMUM_X86_ISA_LEVEL
/* Define if -msahf is enabled by default on x86. */
#undef HAVE_X86_LAHF_SAHF
/* Define if -mmovbe is enabled by default on x86. */
#undef HAVE_X86_MOVBE
/* Define if -mapxf is enabled by default on x86. */
#undef HAVE_X86_APX
#endif
Vendored
+50 -11
View File
@@ -653,7 +653,7 @@ LIBGD
libc_cv_cc_loop_to_function
libc_cv_cc_submachine
libc_cv_cc_nofma
libc_cv_mtls_dialect_gnu2
libc_cv_mtls_descriptor
libc_cv_has_glob_dat
libc_cv_fpie
libc_cv_z_execstack
@@ -4760,6 +4760,12 @@ libc_config_ok=no
# whether to use such directories.
with_fp_cond=1
# A preconfigure script may define another name to TLS descriptor variant
mtls_descriptor=gnu2
# A preconfigure script may define another name to traditional TLS variant
mtls_traditional=gnu
if frags=`ls -d $srcdir/sysdeps/*/preconfigure 2> /dev/null`
then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysdeps preconfigure fragments" >&5
@@ -7006,9 +7012,9 @@ fi
printf "%s\n" "$libc_cv_has_glob_dat" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -mtls-dialect=gnu2" >&5
printf %s "checking for -mtls-dialect=gnu2... " >&6; }
if test ${libc_cv_mtls_dialect_gnu2+y}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tls descriptor support" >&5
printf %s "checking for tls descriptor support... " >&6; }
if test ${libc_cv_mtls_descriptor+y}
then :
printf %s "(cached) " >&6
else $as_nop
@@ -7019,25 +7025,58 @@ void foo (void)
i = 10;
}
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=gnu2 -nostdlib -nostartfiles
conftest.c -o conftest 1>&5'
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
-shared conftest.c -o conftest 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
libc_cv_mtls_dialect_gnu2=yes
libc_cv_mtls_descriptor=$mtls_descriptor
else
libc_cv_mtls_dialect_gnu2=no
libc_cv_mtls_descriptor=no
fi
rm -f conftest*
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_dialect_gnu2" >&5
printf "%s\n" "$libc_cv_mtls_dialect_gnu2" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mtls_descriptor" >&5
printf "%s\n" "$libc_cv_mtls_descriptor" >&6; }
config_vars="$config_vars
have-mtls-dialect-gnu2 = $libc_cv_mtls_dialect_gnu2"
have-mtls-descriptor = $libc_cv_mtls_descriptor"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for traditional tls support" >&5
printf %s "checking for traditional tls support... " >&6; }
if test ${libc_cv_test_mtls_traditional+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat > conftest.c <<EOF
__thread int i;
void foo (void)
{
i = 10;
}
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_traditional -nostdlib -nostartfiles
-shared conftest.c -o conftest 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
libc_cv_test_mtls_traditional=$mtls_traditional
else
libc_cv_test_mtls_traditional=no
fi
rm -f conftest* ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_mtls_traditional" >&5
printf "%s\n" "$libc_cv_test_mtls_traditional" >&6; }
config_vars="$config_vars
have-test-mtls-traditional = $libc_cv_test_mtls_traditional"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -Wno-ignored-attributes is required for aliases" >&5
printf %s "checking if -Wno-ignored-attributes is required for aliases... " >&6; }
+35 -7
View File
@@ -442,6 +442,12 @@ libc_config_ok=no
# whether to use such directories.
with_fp_cond=1
# A preconfigure script may define another name to TLS descriptor variant
mtls_descriptor=gnu2
# A preconfigure script may define another name to traditional TLS variant
mtls_traditional=gnu
dnl Let sysdeps/*/preconfigure act here.
LIBC_PRECONFIGURE([$srcdir], [for sysdeps])
@@ -1287,7 +1293,7 @@ fi
rm -f conftest*])
AC_SUBST(libc_cv_has_glob_dat)
AC_CACHE_CHECK([for -mtls-dialect=gnu2], libc_cv_mtls_dialect_gnu2,
AC_CACHE_CHECK([for tls descriptor support], libc_cv_mtls_descriptor,
[dnl
cat > conftest.c <<EOF
__thread int i;
@@ -1296,16 +1302,38 @@ void foo (void)
i = 10;
}
EOF
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=gnu2 -nostdlib -nostartfiles
conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_descriptor -nostdlib -nostartfiles
-shared conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
then
libc_cv_mtls_dialect_gnu2=yes
libc_cv_mtls_descriptor=$mtls_descriptor
else
libc_cv_mtls_dialect_gnu2=no
libc_cv_mtls_descriptor=no
fi
rm -f conftest*])
AC_SUBST(libc_cv_mtls_dialect_gnu2)
LIBC_CONFIG_VAR([have-mtls-dialect-gnu2], [$libc_cv_mtls_dialect_gnu2])
AC_SUBST(libc_cv_mtls_descriptor)
LIBC_CONFIG_VAR([have-mtls-descriptor], [$libc_cv_mtls_descriptor])
dnl Check if CC supports traditional tls.
AC_CACHE_CHECK([for traditional tls support],
libc_cv_test_mtls_traditional,
[dnl
cat > conftest.c <<EOF
__thread int i;
void foo (void)
{
i = 10;
}
EOF
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -fPIC -mtls-dialect=$mtls_traditional -nostdlib -nostartfiles
-shared conftest.c -o conftest 1>&AS_MESSAGE_LOG_FD])
then
libc_cv_test_mtls_traditional=$mtls_traditional
else
libc_cv_test_mtls_traditional=no
fi
rm -f conftest*])
LIBC_CONFIG_VAR([have-test-mtls-traditional],
[$libc_cv_test_mtls_traditional])
dnl clang emits an warning for a double alias redirection, to warn the
dnl original symbol is sed even when weak definition overrides it.
+4 -1
View File
@@ -33,7 +33,7 @@ elide-routines.os = libc-tls
csu-dummies = $(filter-out $(start-installed-name),crt1.o Mcrt1.o)
extra-objs = start.o \
$(start-installed-name) g$(start-installed-name) $(csu-dummies) \
S$(start-installed-name)
S$(start-installed-name) $(start-name-2.0)
omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
b$(start-installed-name) $(csu-dummies) \
S$(start-installed-name) \
@@ -138,6 +138,9 @@ ifndef start-installed-name-rule
$(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
$(objpfx)init.o $(objpfx)static-reloc.o
$(link-relocatable)
$(objpfx)$(start-name-2.0): $(objpfx)start.o $(objpfx)abi-note.o \
$(objpfx)static-reloc.o
$(link-relocatable)
$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
$(objpfx)init.o
$(link-relocatable)
+29 -3
View File
@@ -24,9 +24,35 @@ include ../Makeconfig
headers := ctype.h
routines := ctype ctype-c99 ctype-extn ctype-c99_l ctype_l isctype
aux := ctype-info
routines := \
ctype \
ctype-c99 \
ctype-c99_l \
ctype-extn \
ctype_l \
isctype \
# routines
aux := ctype-info
tests := test_ctype
tests := \
test_ctype \
tst-ctype-tls-dlmopen \
tst-ctype-tls-dlopen-static \
# tests
tests-static := \
tst-ctype-tls-dlopen-static \
# tests-static
modules-names := \
tst-ctype-tls-mod \
# modules-names
include ../Rules
$(objpfx)tst-ctype-tls-dlmopen: $(shared-thread-library)
$(objpfx)tst-ctype-tls-dlmopen.out: $(objpfx)tst-ctype-tls-mod.so
$(objpfx)tst-ctype-tls-dlopen-static: $(static-thread-library)
$(objpfx)tst-ctype-tls-dlopen-static.out: $(objpfx)tst-ctype-tls-mod.so
tst-ctype-tls-dlopen-static-ENV = \
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx):$(common-objpfx)elf
+17 -12
View File
@@ -19,20 +19,28 @@
#include <ctype.h>
#include <locale/localeinfo.h>
__libc_tsd_define (, const uint16_t *, CTYPE_B)
__libc_tsd_define (, const int32_t *, CTYPE_TOLOWER)
__libc_tsd_define (, const int32_t *, CTYPE_TOUPPER)
/* Fallback initialization using relocations. See the _nl_C_locobj
initializers in locale/xlocale.c. Usually, this is overwritten by
__ctype_init before user code runs, but this does not happen for
threads in secondary namespaces. With the initializers, secondary
namespaces at least get locale data from the C locale. */
__thread const uint16_t * __libc_tsd_CTYPE_B attribute_tls_model_ie
= (const uint16_t *) _nl_C_LC_CTYPE_class + 128;
__thread const int32_t * __libc_tsd_CTYPE_TOLOWER attribute_tls_model_ie
= (const int32_t *) _nl_C_LC_CTYPE_tolower + 128;
__thread const int32_t * __libc_tsd_CTYPE_TOUPPER attribute_tls_model_ie
= (const int32_t *) _nl_C_LC_CTYPE_toupper + 128;
void
__ctype_init (void)
{
const uint16_t **bp = __libc_tsd_address (const uint16_t *, CTYPE_B);
*bp = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
const int32_t **up = __libc_tsd_address (const int32_t *, CTYPE_TOUPPER);
*up = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128);
const int32_t **lp = __libc_tsd_address (const int32_t *, CTYPE_TOLOWER);
*lp = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128);
__libc_tsd_CTYPE_B
= ((const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS)) + 128;
__libc_tsd_CTYPE_TOUPPER
= ((const int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER)) + 128;
__libc_tsd_CTYPE_TOLOWER =
((const int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER)) + 128;
}
libc_hidden_def (__ctype_init)
@@ -41,10 +49,7 @@ libc_hidden_def (__ctype_init)
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
/* Defined in locale/C-ctype.c. */
extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_class32[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_class_upper[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_class_lower[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_class_alpha[] attribute_hidden;
+2
View File
@@ -0,0 +1,2 @@
#define DO_STATIC_TEST 0
#include "tst-ctype-tls-skeleton.c"
+2
View File
@@ -0,0 +1,2 @@
#define DO_STATIC_TEST 1
#include "tst-ctype-tls-skeleton.c"
+37
View File
@@ -0,0 +1,37 @@
/* Wrappers for <ctype.h> macros in a secondary namespace.
Copyright (C) 2025 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>
int
my_isalpha (int ch)
{
return isalpha (ch);
}
int
my_toupper (int ch)
{
return toupper (ch);
}
int
my_tolower (int ch)
{
return tolower (ch);
}
+67
View File
@@ -0,0 +1,67 @@
/* Test that <ctype.h> in a secondary namespace works.
Copyright (C) 2025 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/>. */
/* Before this file is included, define DO_STATIC_TEST to 0 or 1.
With 0, dlmopen is used for the test. With 1, dlopen is used. */
#include <stddef.h>
#include <stdlib.h>
#include <support/check.h>
#include <support/support.h>
#include <support/xdlfcn.h>
#include <support/xthread.h>
static int (*my_isalpha) (int);
static int (*my_toupper) (int);
static int (*my_tolower) (int);
static void *
checks (void *ignore)
{
TEST_VERIFY (my_isalpha ('a'));
TEST_VERIFY (!my_isalpha ('0'));
TEST_COMPARE (my_toupper ('a'), 'A');
TEST_COMPARE (my_toupper ('A'), 'A');
TEST_COMPARE (my_tolower ('a'), 'a');
TEST_COMPARE (my_tolower ('A'), 'a');
return NULL;
}
static int
do_test (void)
{
char *dso = xasprintf ("%s/ctype/tst-ctype-tls-mod.so", support_objdir_root);
#if DO_STATIC_TEST
void *handle = xdlopen (dso, RTLD_LAZY);
#else
void *handle = xdlmopen (LM_ID_NEWLM, dso, RTLD_LAZY);
#endif
my_isalpha = xdlsym (handle, "my_isalpha");
my_toupper = xdlsym (handle, "my_toupper");
my_tolower = xdlsym (handle, "my_tolower");
checks (NULL);
xpthread_join (xpthread_create (NULL, checks, NULL));
xdlclose (handle);
free (dso);
return 0;
}
#include <support/test-driver.c>
+1
View File
@@ -287,6 +287,7 @@ tests = \
tst-fortify-wide \
tst-longjmp_chk \
tst-longjmp_chk2 \
tst-longjmp_chk3 \
tst-realpath-chk \
tst-sprintf-fortify-rdonly \
tst-sprintf-fortify-unchecked \
+47 -36
View File
@@ -75,6 +75,44 @@ static struct argp argp =
options, parse_opt, args_doc, doc, NULL, more_help
};
/* Try to read SIZE bytes from FD and store them on BUF. Terminate
the process upon read error. Also terminate the process if less
than SIZE bytes are remaining in the file. If !IN_HEADER, do not
terminate the process if the end of the file is encountered
immediately, before any bytes are read.
Returns true if SIZE bytes have been read, and false if no bytes
have been read due to an end-of-file condition. */
static bool
read_exactly (int fd, void *buffer, size_t size, bool in_header)
{
char *p = buffer;
char *end = p + size;
while (p < end)
{
ssize_t ret = TEMP_FAILURE_RETRY (read (fd, p, end - p));
if (ret < 0)
{
if (in_header)
error (EXIT_FAILURE, errno, _("cannot read header"));
else
error (EXIT_FAILURE, errno, _("cannot read pointer pair"));
}
if (ret == 0)
{
if (p == buffer && !in_header)
/* Nothing has been read. */
return false;
if (in_header)
error (EXIT_FAILURE, 0, _("unexpected end of file in header"));
else
error (EXIT_FAILURE, 0,
_("unexpected end of file in pointer pair"));
}
p += ret;
}
return true;
}
int
main (int argc, char *argv[])
@@ -110,8 +148,7 @@ main (int argc, char *argv[])
/* Read the first 4-byte word. It contains the information about
the word size and the endianness. */
uint32_t word;
if (TEMP_FAILURE_RETRY (read (fd, &word, 4)) != 4)
error (EXIT_FAILURE, errno, _("cannot read header"));
read_exactly (fd, &word, sizeof (word), true);
/* Check whether we have to swap the byte order. */
int must_swap = (word & 0x0fffffff) == bswap_32 (0xdeb00000);
@@ -121,56 +158,30 @@ main (int argc, char *argv[])
/* We have two loops, one for 32 bit pointers, one for 64 bit pointers. */
if (word == 0xdeb00004)
{
union
{
uint32_t ptrs[2];
char bytes[8];
} pair;
uint32_t ptrs[2];
while (1)
{
size_t len = sizeof (pair);
size_t n;
while (len > 0
&& (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
len))) != 0)
len -= n;
if (len != 0)
/* Nothing to read. */
if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
break;
printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
must_swap ? bswap_32 (pair.ptrs[0]) : pair.ptrs[0],
must_swap ? bswap_32 (pair.ptrs[1]) : pair.ptrs[1]);
must_swap ? bswap_32 (ptrs[0]) : ptrs[0],
must_swap ? bswap_32 (ptrs[1]) : ptrs[1]);
}
}
else if (word == 0xdeb00008)
{
union
{
uint64_t ptrs[2];
char bytes[16];
} pair;
uint64_t ptrs[2];
while (1)
{
size_t len = sizeof (pair);
size_t n;
while (len > 0
&& (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
len))) != 0)
len -= n;
if (len != 0)
/* Nothing to read. */
if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
break;
printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
must_swap ? bswap_64 (pair.ptrs[0]) : pair.ptrs[0],
must_swap ? bswap_64 (pair.ptrs[1]) : pair.ptrs[1]);
must_swap ? bswap_64 (ptrs[0]) : ptrs[0],
must_swap ? bswap_64 (ptrs[1]) : ptrs[1]);
}
}
else
+1 -7
View File
@@ -22,7 +22,6 @@
#include <syslog.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <support/check.h>
#include <support/support.h>
@@ -46,18 +45,13 @@ handler (int sig)
_exit (127);
}
#define FAIL() \
do { \
printf ("Failure on line %d\n", __LINE__); \
support_record_failure (); \
} while (0)
#define CHK_FAIL_START \
chk_fail_ok = 1; \
if (! setjmp (chk_fail_buf)) \
{
#define CHK_FAIL_END \
chk_fail_ok = 0; \
FAIL (); \
FAIL ("not supposed to reach here"); \
}
static void
+10 -4
View File
@@ -18,9 +18,13 @@
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static char buf[SIGSTKSZ * 4];
#include <support/support.h>
static char *buf;
static jmp_buf jb;
static void
@@ -49,8 +53,10 @@ do_test (void)
set_fortify_handler (handler);
/* Create a valid signal stack and enable it. */
size_t bufsize = SIGSTKSZ * 4;
buf = xmalloc (bufsize);
ss.ss_sp = buf;
ss.ss_size = sizeof (buf);
ss.ss_size = bufsize;
ss.ss_flags = 0;
if (sigaltstack (&ss, NULL) < 0)
{
@@ -65,8 +71,8 @@ do_test (void)
/* Shrink the signal stack so the jmpbuf is now invalid.
We adjust the start & end to handle stacks that grow up & down. */
ss.ss_sp = buf + sizeof (buf) / 2;
ss.ss_size = sizeof (buf) / 4;
ss.ss_sp = buf + bufsize / 2;
ss.ss_size = bufsize / 4;
if (sigaltstack (&ss, NULL) < 0)
{
printf ("second sigaltstack failed: %m\n");
+178 -10
View File
@@ -57,6 +57,7 @@ dl-routines = \
dl-close \
dl-debug \
dl-debug-symbols \
dl-debug_state \
dl-deps \
dl-exception \
dl-execstack \
@@ -170,6 +171,7 @@ CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os))
CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
# Add the requested compiler flags to the early startup code.
CFLAGS-dl-misc.os += $(rtld-early-cflags)
CFLAGS-dl-printf.os += $(rtld-early-cflags)
CFLAGS-dl-setup_hash.os += $(rtld-early-cflags)
CFLAGS-dl-sysdep.os += $(rtld-early-cflags)
@@ -265,6 +267,7 @@ tests-static-normal := \
tst-array1-static \
tst-array5-static \
tst-dl-iter-static \
tst-dlopen-sgid \
tst-dst-static \
tst-env-setuid-static \
tst-getauxval-static \
@@ -375,6 +378,7 @@ tests += \
tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit-tlsdesc-dlopen2 \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@@ -411,8 +415,16 @@ tests += \
tst-dlmopen1 \
tst-dlmopen3 \
tst-dlmopen4 \
tst-dlmopen4-nonpic \
tst-dlmopen4-pic \
tst-dlopen-auditdup \
tst-dlopen-constructor-null \
tst-dlopen-self \
tst-dlopen-tlsmodid \
tst-dlopen-tlsreinit1 \
tst-dlopen-tlsreinit2 \
tst-dlopen-tlsreinit3 \
tst-dlopen-tlsreinit4 \
tst-dlopenfail \
tst-dlopenfail-2 \
tst-dlopenrpath \
@@ -424,6 +436,7 @@ tests += \
tst-glibc-hwcaps-prepend \
tst-global1 \
tst-global2 \
tst-gnu2-tls2 \
tst-initfinilazyfail \
tst-initorder \
tst-initorder2 \
@@ -441,8 +454,12 @@ tests += \
tst-p_align1 \
tst-p_align2 \
tst-p_align3 \
tst-recursive-tls \
tst-relsort1 \
tst-ro-dynamic \
tst-rtld-no-malloc \
tst-rtld-no-malloc-audit \
tst-rtld-no-malloc-preload \
tst-rtld-run-static \
tst-single_threaded \
tst-single_threaded-pthread \
@@ -467,6 +484,7 @@ tests += \
tst-tls19 \
tst-tls20 \
tst-tls21 \
tst-tls23 \
tst-tlsalign \
tst-tlsalign-extern \
tst-tlsgap \
@@ -474,6 +492,7 @@ tests += \
tst-unique2 \
tst-unwind-ctor \
tst-unwind-main \
tst-version-hash-zero \
unload3 \
unload4 \
unload5 \
@@ -504,6 +523,8 @@ tests-internal += \
tst-dl_find_object \
tst-dl_find_object-threads \
tst-dlmopen2 \
tst-link-map-contiguous-ldso \
tst-link-map-contiguous-libc \
tst-ptrguard1 \
tst-stackguard1 \
tst-tls-surplus \
@@ -515,6 +536,10 @@ tests-internal += \
unload2 \
# tests-internal
ifeq ($(build-hardcoded-path-in-tests),yes)
tests-internal += tst-link-map-contiguous-main
endif
tests-container += \
tst-dlopen-self-container \
tst-dlopen-tlsmodid-container \
@@ -795,6 +820,7 @@ modules-names += \
tst-auditmanymod8 \
tst-auditmanymod9 \
tst-auditmod-tlsdesc \
tst-auditmod-tlsdesc2 \
tst-auditmod1 \
tst-auditmod11 \
tst-auditmod12 \
@@ -835,6 +861,14 @@ modules-names += \
tst-dlmopen-twice-mod1 \
tst-dlmopen-twice-mod2 \
tst-dlmopen1mod \
tst-dlopen-auditdup-auditmod \
tst-dlopen-auditdupmod \
tst-dlopen-constructor-null-mod1 \
tst-dlopen-constructor-null-mod2 \
tst-dlopen-sgid-mod \
tst-dlopen-tlsreinitmod1 \
tst-dlopen-tlsreinitmod2 \
tst-dlopen-tlsreinitmod3 \
tst-dlopenfaillinkmod \
tst-dlopenfailmod1 \
tst-dlopenfailmod2 \
@@ -846,6 +880,9 @@ modules-names += \
tst-filterobj-flt \
tst-finilazyfailmod \
tst-globalmod2 \
tst-gnu2-tls2mod0 \
tst-gnu2-tls2mod1 \
tst-gnu2-tls2mod2 \
tst-initlazyfailmod \
tst-initorder2a \
tst-initorder2b \
@@ -872,6 +909,23 @@ modules-names += \
tst-null-argv-lib \
tst-p_alignmod-base \
tst-p_alignmod3 \
tst-recursive-tlsmallocmod \
tst-recursive-tlsmod0 \
tst-recursive-tlsmod1 \
tst-recursive-tlsmod2 \
tst-recursive-tlsmod3 \
tst-recursive-tlsmod4 \
tst-recursive-tlsmod5 \
tst-recursive-tlsmod6 \
tst-recursive-tlsmod7 \
tst-recursive-tlsmod8 \
tst-recursive-tlsmod9 \
tst-recursive-tlsmod10 \
tst-recursive-tlsmod11 \
tst-recursive-tlsmod12 \
tst-recursive-tlsmod13 \
tst-recursive-tlsmod14 \
tst-recursive-tlsmod15 \
tst-relsort1mod1 \
tst-relsort1mod2 \
tst-ro-dynamic-mod \
@@ -896,6 +950,7 @@ modules-names += \
tst-tls19mod3 \
tst-tls20mod-bad \
tst-tls21mod \
tst-tls23-mod \
tst-tlsalign-lib \
tst-tlsgap-mod0 \
tst-tlsgap-mod1 \
@@ -926,6 +981,9 @@ modules-names += \
tst-unique2mod1 \
tst-unique2mod2 \
tst-unwind-ctor-lib \
tst-version-hash-zero-linkmod \
tst-version-hash-zero-mod \
tst-version-hash-zero-refmod \
unload2dep \
unload2mod \
unload3mod1 \
@@ -995,13 +1053,13 @@ modules-names-tests = $(filter-out ifuncmod% tst-tlsmod%,\
# For +depfiles in Makerules.
extra-test-objs += tst-auditmod17.os
ifeq (yes,$(have-mtls-dialect-gnu2))
ifneq (no,$(have-mtls-descriptor))
tests += tst-gnu2-tls1
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)
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=$(have-mtls-descriptor)
endif # $(have-mtls-descriptor)
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
@@ -2002,6 +2060,13 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen4.out: $(objpfx)tst-dlmopen1mod.so
CFLAGS-tst-dlmopen4-pic.c += -fPIC
$(objpfx)tst-dlmopen4-pic.out: $(objpfx)tst-dlmopen1mod.so
CFLAGS-tst-dlmopen4-nonpic.c += -fno-pie
tst-dlmopen4-nonpic-no-pie = yes
$(objpfx)tst-dlmopen4-nonpic.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
@@ -2968,11 +3033,11 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
$(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))
ifneq (no,$(have-mtls-descriptor))
# 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
CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
@@ -2982,6 +3047,9 @@ $(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
$(objpfx)tst-audit-tlsdesc-dlopen2.out: $(objpfx)tst-auditmod-tlsdesc2.so \
$(patsubst %, $(objpfx)%.so, $(tlsmod17a-modules))
tst-audit-tlsdesc-dlopen2-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc2.so
$(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \
@@ -3044,8 +3112,108 @@ $(objpfx)tst-tlsgap.out: \
$(objpfx)tst-tlsgap-mod0.so \
$(objpfx)tst-tlsgap-mod1.so \
$(objpfx)tst-tlsgap-mod2.so
ifeq (yes,$(have-mtls-dialect-gnu2))
CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
$(objpfx)tst-gnu2-tls2: $(shared-thread-library)
$(objpfx)tst-gnu2-tls2.out: \
$(objpfx)tst-gnu2-tls2mod0.so \
$(objpfx)tst-gnu2-tls2mod1.so \
$(objpfx)tst-gnu2-tls2mod2.so
ifneq (no,$(have-mtls-descriptor))
CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-gnu2-tls2mod0.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-gnu2-tls2mod1.c += -mtls-dialect=$(have-mtls-descriptor)
CFLAGS-tst-gnu2-tls2mod2.c += -mtls-dialect=$(have-mtls-descriptor)
endif
$(objpfx)tst-tls23: $(shared-thread-library)
$(objpfx)tst-tls23.out: $(objpfx)tst-tls23-mod.so
ifneq (no,$(have-test-mtls-traditional))
CFLAGS-tst-tls23-mod.c += -mtls-dialect=$(have-test-mtls-traditional)
endif
$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so
# More objects than DTV_SURPLUS, to trigger DTV reallocation.
$(objpfx)tst-recursive-tls.out: \
$(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
# Order matters here. The test needs the constructor for
# tst-dlopen-tlsreinitmod2.so to be called first.
LDFLAGS-tst-dlopen-tlsreinitmod1.so = -Wl,--no-as-needed
$(objpfx)tst-dlopen-tlsreinitmod1.so: \
$(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
LDFLAGS-tst-dlopen-tlsreinit2 = -Wl,--no-as-needed
$(objpfx)tst-dlopen-tlsreinit2: \
$(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
LDFLAGS-tst-dlopen-tlsreinit4 = -Wl,--no-as-needed
$(objpfx)tst-dlopen-tlsreinit4: \
$(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
# tst-dlopen-tlsreinitmod2.so is underlinked and refers to
# tst-dlopen-tlsreinitmod3.so. The dependency is provided via
# $(objpfx)tst-dlopen-tlsreinitmod1.so.
tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
$(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
# Reuse an audit module which provides ample debug logging.
$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
tst-dlopen-tlsreinit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
$(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so
tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
$(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so
tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so
$(objpfx)tst-dlopen-auditdup.out: \
$(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so
# Reuse an audit module which provides ample debug logging.
tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
# Any shared object should do.
tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so
# These rules link and run the special elf/tst-nolink-libc-* tests if
# a port adds them to the tests variables. Neither test variant is
# linked against libc.so, but tst-nolink-libc-1 is linked against
# ld.so. The test is always run directly, not under the dynamic
# linker.
CFLAGS-tst-nolink-libc.c += $(no-stack-protector)
$(objpfx)tst-nolink-libc-1: $(objpfx)tst-nolink-libc.o $(objpfx)ld.so
$(LINK.o) -nostdlib -nostartfiles -o $@ $< \
-Wl,--dynamic-linker=$(objpfx)ld.so,--no-as-needed $(objpfx)ld.so
$(objpfx)tst-nolink-libc-1.out: $(objpfx)tst-nolink-libc-1 $(objpfx)ld.so
$< > $@ 2>&1; $(evaluate-test)
$(objpfx)tst-nolink-libc-2: $(objpfx)tst-nolink-libc.o
$(LINK.o) -nostdlib -nostartfiles -o $@ $< \
-Wl,--dynamic-linker=$(objpfx)ld.so
$(objpfx)tst-nolink-libc-2.out: $(objpfx)tst-nolink-libc-2 $(objpfx)ld.so
$< > $@ 2>&1; $(evaluate-test)
$(objpfx)tst-version-hash-zero.out: \
$(objpfx)tst-version-hash-zero-mod.so \
$(objpfx)tst-version-hash-zero-refmod.so
LDFLAGS-tst-version-hash-zero-mod.so = \
-Wl,--version-script=tst-version-hash-zero-mod.map
# The run-time test module tst-version-hash-zero-refmod.so is linked
# to a stub module, tst-version-hash-zero-linkmod.so, to produce an
# expected relocation error.
$(objpfx)tst-version-hash-zero-refmod.so: \
$(objpfx)tst-version-hash-zero-linkmod.so
LDFLAGS-tst-version-hash-zero-linkmod.so = \
-Wl,--version-script=tst-version-hash-zero-linkmod.map \
-Wl,--soname=tst-version-hash-zero-mod.so
$(objpfx)tst-version-hash-zero-refmod.so: \
$(objpfx)tst-version-hash-zero-linkmod.so
tst-version-hash-zero-refmod.so-no-z-defs = yes
$(objpfx)tst-dlopen-constructor-null: \
$(objpfx)tst-dlopen-constructor-null-mod1.so \
$(objpfx)tst-dlopen-constructor-null-mod2.so
$(objpfx)tst-dlopen-constructor-null-mod2.so: \
$(objpfx)tst-dlopen-constructor-null-mod1.so
+1 -1
View File
@@ -820,7 +820,7 @@ struct aux_cache_entry
struct aux_cache_entry *next;
};
#define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
#define AUX_CACHEMAGIC "glibc-ld.so.auxcache-2.0"
struct aux_cache_file_entry
{
+13 -13
View File
@@ -264,6 +264,12 @@ _dl_close_worker (struct link_map *map, bool force)
_dl_catch_exception (NULL, _dl_call_fini, imap);
#ifdef SHARED
/* Auditing checkpoint: we will start deleting objects.
This is supposed to happen before la_objclose (see _dl_fini),
but only once per non-recursive dlclose call. */
if (!unload_any)
_dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
/* Auditing checkpoint: we remove an object. */
_dl_audit_objclose (imap);
#endif
@@ -424,15 +430,10 @@ _dl_close_worker (struct link_map *map, bool force)
if (!unload_any)
goto out;
#ifdef SHARED
/* Auditing checkpoint: we will start deleting objects. */
_dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
#endif
/* Notify the debugger we are about to remove some loaded objects. */
/* Notify the debugger we are about to remove some loaded objects.
LA_ACT_DELETE has already been signalled above for !unload_any. */
struct r_debug *r = _dl_debug_update (nsid);
r->r_state = RT_DELETE;
_dl_debug_state ();
_dl_debug_change_state (r, RT_DELETE);
LIBC_PROBE (unmap_start, 2, nsid, r);
if (unload_global)
@@ -723,6 +724,10 @@ _dl_close_worker (struct link_map *map, bool force)
/* TLS is cleaned up for the unloaded modules. */
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
/* Notify the debugger those objects are finalized and gone. */
_dl_debug_change_state (r, RT_CONSISTENT);
LIBC_PROBE (unmap_complete, 2, nsid, r);
#ifdef SHARED
/* Auditing checkpoint: we have deleted all objects. Also, do not notify
auditors of the cleanup of a failed audit module loading attempt. */
@@ -735,11 +740,6 @@ _dl_close_worker (struct link_map *map, bool force)
--GL(dl_nns);
while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL);
/* Notify the debugger those objects are finalized and gone. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
LIBC_PROBE (unmap_complete, 2, nsid, r);
/* Recheck if we need to retry, release the lock. */
out:
if (dl_close_state == rerun)
+1
View File
@@ -38,3 +38,4 @@
_r_debug:
_r_debug_extended:
.zero R_DEBUG_EXTENDED_SIZE
rtld_hidden_def (_r_debug)
+103 -52
View File
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <assert.h>
#include <ldsodefs.h>
@@ -30,23 +31,86 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
&& VERIFY_MEMBER (l_prev))
? 1 : -1];
#ifdef SHARED
/* r_debug structs for secondary namespaces. The first namespace is
handled separately because its r_debug structure must overlap with
the public _r_debug symbol, so the first array element corresponds
to LM_ID_BASE + 1. See elf/dl-debug-symbols.S. */
struct r_debug_extended _r_debug_array[DL_NNS - 1];
/* If not null, pointer to the _r_debug in the main executable. */
static struct r_debug *_r_debug_main;
void
_dl_debug_post_relocate (struct link_map *main_map)
{
/* Perform a full symbol search in all objects, to maintain
compatibility if interposed _r_debug definitions. The lookup
cannot fail because there is a definition in ld.so, and this
function is only called if the ld.so search scope is not empty. */
const ElfW(Sym) *sym = NULL;
lookup_t result =_dl_lookup_symbol_x ("_r_debug", main_map, &sym,
main_map->l_scope, NULL, 0, 0, NULL);
if (sym->st_size >= sizeof (struct r_debug))
{
struct r_debug *main_r_debug = DL_SYMBOL_ADDRESS (result, sym);
if (main_r_debug != &_r_debug_extended.base)
{
/* The extended version of the struct is not available in
the main executable because a copy relocation has been
used. r_map etc. have already been copied as part of the
copy relocation processing. */
main_r_debug->r_version = 1;
/* Record that dual updates of the initial link map are
required. */
_r_debug_main = main_r_debug;
}
}
}
/* Return the r_debug object for the namespace NS. */
static inline struct r_debug_extended *
get_rdebug (Lmid_t ns)
{
if (ns == LM_ID_BASE)
return &_r_debug_extended;
else
return &_r_debug_array[ns - 1];
}
#else /* !SHARED */
static inline struct r_debug_extended *
get_rdebug (Lmid_t ns)
{
return &_r_debug_extended; /* There is just one namespace. */
}
#endif /* !SHARED */
/* Update the `r_map' member and return the address of `struct r_debug'
of the namespace NS. */
struct r_debug *
_dl_debug_update (Lmid_t ns)
{
struct r_debug_extended *r;
if (ns == LM_ID_BASE)
r = &_r_debug_extended;
else
r = &GL(dl_ns)[ns]._ns_debug;
struct r_debug_extended *r = get_rdebug (ns);
if (r->base.r_map == NULL)
atomic_store_release (&r->base.r_map,
(void *) GL(dl_ns)[ns]._ns_loaded);
return &r->base;
}
void
_dl_debug_change_state (struct r_debug *r, int state)
{
atomic_store_release (&r->r_state, state);
#ifdef SHARED
if (r == &_r_debug_extended.base && _r_debug_main != NULL)
/* Update the copy-relocation of _r_debug. */
atomic_store_release (&_r_debug_main->r_state, state);
#endif
_dl_debug_state ();
}
/* Initialize _r_debug_extended for the namespace NS. LDBASE is the
run-time load address of the dynamic linker, to be put in
_r_debug_extended.r_ldbase. Return the address of _r_debug. */
@@ -54,34 +118,7 @@ _dl_debug_update (Lmid_t ns)
struct r_debug *
_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
{
struct r_debug_extended *r, **pp = NULL;
if (ns == LM_ID_BASE)
{
r = &_r_debug_extended;
/* Initialize r_version to 1. */
if (_r_debug_extended.base.r_version == 0)
_r_debug_extended.base.r_version = 1;
}
else if (DL_NNS > 1)
{
r = &GL(dl_ns)[ns]._ns_debug;
if (r->base.r_brk == 0)
{
/* Add the new namespace to the linked list. After a namespace
is initialized, r_brk becomes non-zero. A namespace becomes
empty (r_map == NULL) when it is unused. But it is never
removed from the linked list. */
struct r_debug_extended *p;
for (pp = &_r_debug_extended.r_next;
(p = *pp) != NULL;
pp = &p->r_next)
;
r->base.r_version = 2;
}
}
struct r_debug_extended *r = get_rdebug (ns);
if (r->base.r_brk == 0)
{
/* Tell the debugger where to find the map of loaded objects.
@@ -89,30 +126,44 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
only once. */
r->base.r_ldbase = ldbase ?: _r_debug_extended.base.r_ldbase;
r->base.r_brk = (ElfW(Addr)) &_dl_debug_state;
r->r_next = NULL;
#ifdef SHARED
/* Add the new namespace to the linked list. This assumes that
namespaces are allocated in increasing order. After a
namespace is initialized, r_brk becomes non-zero. A
namespace becomes empty (r_map == NULL) when it is unused.
But it is never removed from the linked list. */
if (ns != LM_ID_BASE)
{
r->base.r_version = 2;
if (ns - 1 == LM_ID_BASE)
{
atomic_store_release (&_r_debug_extended.r_next, r);
/* Now there are multiple namespaces. Note that this
deliberately does not update the copy in the main
executable (if it exists). */
atomic_store_release (&_r_debug_extended.base.r_version, 2);
}
else
/* Update r_debug_extended of the previous namespace. */
atomic_store_release (&_r_debug_array[ns - 2].r_next, r);
}
else
#endif /* SHARED */
r->base.r_version = 1;
}
if (r->base.r_map == NULL)
atomic_store_release (&r->base.r_map,
(void *) GL(dl_ns)[ns]._ns_loaded);
if (pp != NULL)
{
atomic_store_release (pp, r);
/* Bump r_version to 2 for the new namespace. */
atomic_store_release (&_r_debug_extended.base.r_version, 2);
struct link_map_public *l = (void *) GL(dl_ns)[ns]._ns_loaded;
atomic_store_release (&r->base.r_map, l);
#ifdef SHARED
if (ns == LM_ID_BASE && _r_debug_main != NULL)
/* Update the copy-relocation of _r_debug. */
atomic_store_release (&_r_debug_main->r_map, l);
#endif
}
return &r->base;
}
/* This function exists solely to have a breakpoint set on it by the
debugger. The debugger is supposed to find this function's address by
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
for this particular symbol name in the PT_INTERP file. */
void
_dl_debug_state (void)
{
}
rtld_hidden_def (_dl_debug_state)
+30
View File
@@ -0,0 +1,30 @@
/* Debugger hook called after dynamic linker updates.
Copyright (C) 1996-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ldsodefs.h>
/* This function exists solely to have a breakpoint set on it by the
debugger. The debugger is supposed to find this function's address by
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
for this particular symbol name in the PT_INTERP file. Therefore,
this function must not be inlined. */
void
_dl_debug_state (void)
{
}
rtld_hidden_def (_dl_debug_state)
+2
View File
@@ -235,6 +235,8 @@ _dl_print_diagnostics (char **environ)
_dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
_dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
_dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
_dl_diagnostics_print_labeled_value ("dl_hwcap3", GLRO (dl_hwcap3));
_dl_diagnostics_print_labeled_value ("dl_hwcap4", GLRO (dl_hwcap4));
_dl_diagnostics_print_labeled_string
("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
_dl_diagnostics_print_labeled_value
+57 -29
View File
@@ -465,6 +465,37 @@ _dl_find_object (void *pc1, struct dl_find_object *result)
}
rtld_hidden_def (_dl_find_object)
/* Subroutine of _dlfo_process_initial to split out noncontigous link
maps. NODELETE is the number of used _dlfo_nodelete_mappings
elements. It is incremented as needed, and the new NODELETE value
is returned. */
static size_t
_dlfo_process_initial_noncontiguous_map (struct link_map *map,
size_t nodelete)
{
struct dl_find_object_internal dlfo;
_dl_find_object_from_map (map, &dlfo);
/* PT_LOAD segments for a non-contiguous link map are added to the
non-closeable mappings. */
const ElfW(Phdr) *ph = map->l_phdr;
const ElfW(Phdr) *ph_end = map->l_phdr + map->l_phnum;
for (; ph < ph_end; ++ph)
if (ph->p_type == PT_LOAD)
{
if (_dlfo_nodelete_mappings != NULL)
{
/* Second pass only. */
_dlfo_nodelete_mappings[nodelete] = dlfo;
ElfW(Addr) start = ph->p_vaddr + map->l_addr;
_dlfo_nodelete_mappings[nodelete].map_start = start;
_dlfo_nodelete_mappings[nodelete].map_end = start + ph->p_memsz;
}
++nodelete;
}
return nodelete;
}
/* _dlfo_process_initial is called twice. First to compute the array
sizes from the initial loaded mappings. Second to fill in the
bases and infos arrays with the (still unsorted) data. Returns the
@@ -476,29 +507,8 @@ _dlfo_process_initial (void)
size_t nodelete = 0;
if (!main_map->l_contiguous)
{
struct dl_find_object_internal dlfo;
_dl_find_object_from_map (main_map, &dlfo);
/* PT_LOAD segments for a non-contiguous are added to the
non-closeable mappings. */
for (const ElfW(Phdr) *ph = main_map->l_phdr,
*ph_end = main_map->l_phdr + main_map->l_phnum;
ph < ph_end; ++ph)
if (ph->p_type == PT_LOAD)
{
if (_dlfo_nodelete_mappings != NULL)
{
/* Second pass only. */
_dlfo_nodelete_mappings[nodelete] = dlfo;
_dlfo_nodelete_mappings[nodelete].map_start
= ph->p_vaddr + main_map->l_addr;
_dlfo_nodelete_mappings[nodelete].map_end
= _dlfo_nodelete_mappings[nodelete].map_start + ph->p_memsz;
}
++nodelete;
}
}
/* Contiguous case already handled in _dl_find_object_init. */
nodelete = _dlfo_process_initial_noncontiguous_map (main_map, nodelete);
size_t loaded = 0;
for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
@@ -510,11 +520,22 @@ _dlfo_process_initial (void)
/* lt_library link maps are implicitly NODELETE. */
if (l->l_type == lt_library || l->l_nodelete_active)
{
if (_dlfo_nodelete_mappings != NULL)
/* Second pass only. */
_dl_find_object_from_map
(l, _dlfo_nodelete_mappings + nodelete);
++nodelete;
/* The kernel may have loaded ld.so with gaps. */
if (!l->l_contiguous
#ifdef SHARED
&& l == &GL(dl_rtld_map)
#endif
)
nodelete
= _dlfo_process_initial_noncontiguous_map (l, nodelete);
else
{
if (_dlfo_nodelete_mappings != NULL)
/* Second pass only. */
_dl_find_object_from_map
(l, _dlfo_nodelete_mappings + nodelete);
++nodelete;
}
}
else if (l->l_type == lt_loaded)
{
@@ -661,6 +682,14 @@ _dl_find_object_update_1 (struct link_map **loaded, size_t count)
= _dlfo_loaded_mappings[!active_idx];
size_t remaining_to_add = current_used + count;
/* remaining_to_add can be 0 if (current_used + count) wraps, but in practice
this is not possible as it represent counts of link maps. Link maps have
sizes larger than 1 byte, so the sum of any two link map counts will
always fit within a size_t without wrapping around. This check ensures
that target_seg is not erroneously considered potentially NULL by GCC. */
if (remaining_to_add == 0)
__builtin_unreachable ();
/* Ensure that the new segment chain has enough space. */
{
size_t new_allocated
@@ -756,7 +785,6 @@ _dl_find_object_update_1 (struct link_map **loaded, size_t count)
/* Prefer newly loaded link map. */
assert (loaded_index1 > 0);
_dl_find_object_from_map (loaded[loaded_index1 - 1], dlfo);
loaded[loaded_index1 - 1]->l_find_object_processed = 1;
--loaded_index1;
}
+3 -1
View File
@@ -87,7 +87,7 @@ _dl_find_object_to_external (struct dl_find_object_internal *internal,
}
/* Extract the object location data from a link map and writes it to
*RESULT using relaxed MO stores. */
*RESULT using relaxed MO stores. Set L->l_find_object_processed. */
static void __attribute__ ((unused))
_dl_find_object_from_map (struct link_map *l,
struct dl_find_object_internal *result)
@@ -100,6 +100,8 @@ _dl_find_object_from_map (struct link_map *l,
atomic_store_relaxed (&result->eh_dbase, (void *) l->l_info[DT_PLTGOT]);
#endif
l->l_find_object_processed = 1;
for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum;
ph < ph_end; ++ph)
if (ph->p_type == DLFO_EH_SEGMENT_TYPE)
+9
View File
@@ -69,6 +69,7 @@ _dl_fini (void)
unsigned int i;
struct link_map *l;
struct link_map *proxy_link_map = NULL;
assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
/* Do not handle ld.so in secondary namespaces. */
@@ -84,6 +85,11 @@ _dl_fini (void)
are not dlclose()ed from underneath us. */
++l->l_direct_opencount;
}
else
/* Used below to call la_objclose for the ld.so proxy
link map. */
proxy_link_map = l;
assert (ns != LM_ID_BASE || i == nloaded);
assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
@@ -122,6 +128,9 @@ _dl_fini (void)
--l->l_direct_opencount;
}
if (proxy_link_map != NULL)
_dl_audit_objclose (proxy_link_map);
#ifdef SHARED
_dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
#endif
+33 -27
View File
@@ -929,6 +929,36 @@ _dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph)
}
}
static void
_dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l)
{
/* Signal that we are going to add new objects. */
struct r_debug *r = _dl_debug_update (nsid);
if (r->r_state == RT_CONSISTENT)
{
#ifdef SHARED
/* Auditing checkpoint: we are going to add new objects. Since this
is called after _dl_add_to_namespace_list the namespace is guaranteed
to not be empty. */
if ((mode & __RTLD_AUDIT) == 0)
_dl_audit_activity_nsid (nsid, LA_ACT_ADD);
#endif
/* Notify the debugger we have added some objects. We need to
call _dl_debug_initialize in a static program in case dynamic
linking has not been used before. */
_dl_debug_change_state (r, RT_ADD);
LIBC_PROBE (map_start, 2, nsid, r);
}
else
assert (r->r_state == RT_ADD);
#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
_dl_audit_objopen (l, nsid);
#endif
}
/* Map in the shared object NAME, actually located in REALNAME, and already
opened on FD. */
@@ -1029,6 +1059,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
/* Add the map for the mirrored object to the object list. */
_dl_add_to_namespace_list (l, nsid);
_dl_notify_new_object (mode, nsid, l);
return l;
}
#endif
@@ -1487,33 +1519,7 @@ cannot enable executable stack as shared object requires");
if (mode & __RTLD_SPROF)
return l;
/* Signal that we are going to add new objects. */
struct r_debug *r = _dl_debug_update (nsid);
if (r->r_state == RT_CONSISTENT)
{
#ifdef SHARED
/* Auditing checkpoint: we are going to add new objects. Since this
is called after _dl_add_to_namespace_list the namespace is guaranteed
to not be empty. */
if ((mode & __RTLD_AUDIT) == 0)
_dl_audit_activity_nsid (nsid, LA_ACT_ADD);
#endif
/* Notify the debugger we have added some objects. We need to
call _dl_debug_initialize in a static program in case dynamic
linking has not been used before. */
r->r_state = RT_ADD;
_dl_debug_state ();
LIBC_PROBE (map_start, 2, nsid, r);
}
else
assert (r->r_state == RT_ADD);
#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
_dl_audit_objopen (l, nsid);
#endif
_dl_notify_new_object (mode, nsid, l);
return l;
}
+16 -6
View File
@@ -113,12 +113,22 @@ check_match (const char *const undef_name,
/* We can match the version information or use the
default one if it is not hidden. */
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if ((map->l_versions[ndx].hash != version->hash
|| strcmp (map->l_versions[ndx].name, version->name))
&& (version->hidden || map->l_versions[ndx].hash
|| (verstab[symidx] & 0x8000)))
/* It's not the version we want. */
return NULL;
if (map->l_versions[ndx].hash == version->hash
&& strcmp (map->l_versions[ndx].name, version->name) == 0)
/* This is an exact version match. Return the symbol below. */
;
else
{
if (!version->hidden
&& map->l_versions[ndx].name[0] == '\0'
&& (verstab[symidx] & 0x8000) == 0
&& (*num_versions)++ == 0)
/* This is the global default version. Store it as a
fallback match. */
*versioned_sym = sym;
return NULL;
}
}
}
else
+43 -45
View File
@@ -363,17 +363,8 @@ resize_tls_slotinfo (struct link_map *new)
{
bool any_tls = false;
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
/* Only add TLS memory if this object is loaded now and
therefore is not yet initialized. */
if (! imap->l_init_called && imap->l_tls_blocksize > 0)
{
_dl_add_to_slotinfo (imap, false);
any_tls = true;
}
}
if (_dl_add_to_slotinfo (new->l_searchlist.r_list[i], false))
any_tls = true;
return any_tls;
}
@@ -383,22 +374,8 @@ resize_tls_slotinfo (struct link_map *new)
static void
update_tls_slotinfo (struct link_map *new)
{
unsigned int first_static_tls = new->l_searchlist.r_nlist;
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
/* Only add TLS memory if this object is loaded now and
therefore is not yet initialized. */
if (! imap->l_init_called && imap->l_tls_blocksize > 0)
{
_dl_add_to_slotinfo (imap, true);
if (imap->l_need_tls_init
&& first_static_tls == new->l_searchlist.r_nlist)
first_static_tls = i;
}
}
_dl_add_to_slotinfo (new->l_searchlist.r_list[i], true);
size_t newgen = GL(dl_tls_generation) + 1;
if (__glibc_unlikely (newgen == 0))
@@ -410,13 +387,11 @@ TLS generation counter wrapped! Please report this."));
/* We need a second pass for static tls data, because
_dl_update_slotinfo must not be run while calls to
_dl_add_to_slotinfo are still pending. */
for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
if (imap->l_need_tls_init
&& ! imap->l_init_called
&& imap->l_tls_blocksize > 0)
if (imap->l_need_tls_init && imap->l_tls_blocksize > 0)
{
/* For static TLS we have to allocate the memory here and
now, but we can delay updating the DTV. */
@@ -601,6 +576,14 @@ dl_open_worker_begin (void *a)
_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
new->l_name, new->l_ns, new->l_direct_opencount);
#ifdef SHARED
/* No relocation processing on this execution path. But
relocation has not been performed for static
position-dependent executables, so disable the assert for
static linking. */
assert (new->l_relocated);
#endif
/* If the user requested the object to be in the global
namespace but it is not so far, prepare to add it now. This
can raise an exception to do a malloc failure. */
@@ -622,9 +605,15 @@ dl_open_worker_begin (void *a)
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
add_to_global_update (new);
const int r_state __attribute__ ((unused))
= _dl_debug_update (args->nsid)->r_state;
assert (r_state == RT_CONSISTENT);
/* It is not possible to run the ELF constructor for the new
link map if it has not executed yet: If this dlopen call came
from an ELF constructor that has not put that object into a
consistent state, completing initialization for the entire
scope will expose objects that have this partially
constructed object among its dependencies to this
inconsistent state. This could happen even with a benign
dlopen (NULL, RTLD_LAZY) call from a constructor of an
initially loaded shared object. */
return;
}
@@ -656,17 +645,6 @@ dl_open_worker_begin (void *a)
#endif
}
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
#endif
/* Notify the debugger all new objects are now ready to go. */
struct r_debug *r = _dl_debug_update (args->nsid);
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
_dl_open_check (new);
/* Print scope information. */
@@ -713,6 +691,7 @@ dl_open_worker_begin (void *a)
created dlmopen namespaces. Do not do this for static dlopen
because libc has relocations against ld.so, which may not have
been relocated at this point. */
struct r_debug *r = _dl_debug_update (args->nsid);
#ifdef SHARED
if (GL(dl_ns)[args->nsid].libc_map != NULL)
_dl_open_relocate_one_object (args, r, GL(dl_ns)[args->nsid].libc_map,
@@ -804,6 +783,25 @@ dl_open_worker (void *a)
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
/* Auditing checkpoint and debugger signalling. Do this even on
error, so that dlopen exists with consistent state. */
if (args->nsid >= 0 || args->map != NULL)
{
Lmid_t nsid = args->map != NULL ? args->map->l_ns : args->nsid;
struct r_debug *r = _dl_debug_update (nsid);
#ifdef SHARED
bool was_not_consistent = r->r_state != RT_CONSISTENT;
#endif
_dl_debug_change_state (r, RT_CONSISTENT);
LIBC_PROBE (map_complete, 3, nsid, r, args->map);
#ifdef SHARED
if (was_not_consistent)
/* Avoid redudant/recursive signalling. */
_dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT);
#endif
}
if (__glibc_unlikely (ex.errstring != NULL))
/* Reraise the error. */
_dl_signal_exception (err, &ex, NULL);
@@ -872,7 +870,7 @@ no more namespaces available for dlmopen()"));
}
GL(dl_ns)[nsid].libc_map = NULL;
_dl_debug_update (nsid)->r_state = RT_CONSISTENT;
_dl_debug_change_state (_dl_debug_update (nsid), RT_CONSISTENT);
}
/* Never allow loading a DSO in a namespace which is empty. Such
direct placements is only causing problems. Also don't allow
+16 -16
View File
@@ -202,12 +202,9 @@ resolve_map (lookup_t l, struct r_scope_elem *scope[], const ElfW(Sym) **ref,
#include "dynamic-link.h"
void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int reloc_mode, int consider_profiling)
_dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
int reloc_mode, int consider_profiling)
{
if (l->l_relocated)
return;
struct textrels
{
caddr_t start;
@@ -220,8 +217,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int lazy = reloc_mode & RTLD_LAZY;
int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
#ifdef SHARED
bool consider_symbind = false;
#ifdef SHARED
/* If we are auditing, install the same handlers we need for profiling. */
if ((reloc_mode & __RTLD_AUDIT) == 0)
{
@@ -240,9 +237,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
}
#elif defined PROF
/* Never use dynamic linker profiling for gprof profiling code. */
# define consider_profiling 0
#else
# define consider_symbind 0
consider_profiling = 0;
#endif
/* If DT_BIND_NOW is set relocate all references in this object. We
@@ -300,7 +295,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
#ifndef PROF
if ((consider_profiling || consider_symbind)
&& l->l_info[DT_PLTRELSZ] != NULL)
{
@@ -321,7 +315,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
_dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name);
}
}
#endif
}
/* Mark the object so we know this work has been done. */
@@ -342,17 +335,24 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
textrels = textrels->next;
}
/* In case we can protect the data now that the relocations are
done, do it. */
if (l->l_relro_size != 0)
_dl_protect_relro (l);
}
void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int reloc_mode, int consider_profiling)
{
if (l->l_relocated)
return;
_dl_relocate_object_no_relro (l, scope, reloc_mode, consider_profiling);
_dl_protect_relro (l);
}
void
_dl_protect_relro (struct link_map *l)
{
if (l->l_relro_size == 0)
return;
ElfW(Addr) start = ALIGN_DOWN((l->l_addr
+ l->l_relro_addr),
GLRO(dl_pagesize));
+3 -2
View File
@@ -158,6 +158,8 @@ const ElfW(Phdr) *_dl_phdr;
size_t _dl_phnum;
uint64_t _dl_hwcap;
uint64_t _dl_hwcap2;
uint64_t _dl_hwcap3;
uint64_t _dl_hwcap4;
enum dso_sort_algorithm _dl_dso_sort_algo;
@@ -336,8 +338,7 @@ _dl_non_dynamic_init (void)
call_function_static_weak (_dl_find_object_init);
/* Setup relro on the binary itself. */
if (_dl_main_map.l_relro_size != 0)
_dl_protect_relro (&_dl_main_map);
_dl_protect_relro (&_dl_main_map);
}
#ifdef DL_SYSINFO_IMPLEMENTATION
+145 -19
View File
@@ -75,6 +75,31 @@
/* Default for dl_tls_static_optional. */
#define OPTIONAL_TLS 512
/* Used to count the number of threads currently executing dynamic TLS
updates. Used to avoid recursive malloc calls in __tls_get_addr
for an interposed malloc that uses global-dynamic TLS (which is not
recommended); see _dl_tls_allocate_active checks. This could be a
per-thread flag, but would need TLS access in the dynamic linker. */
unsigned int _dl_tls_threads_in_update;
static inline void
_dl_tls_allocate_begin (void)
{
atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, 1);
}
static inline void
_dl_tls_allocate_end (void)
{
atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, -1);
}
static inline bool
_dl_tls_allocate_active (void)
{
return atomic_load_relaxed (&_dl_tls_threads_in_update) > 0;
}
/* Compute the static TLS surplus based on the namespace count and the
TLS space that can be used for optimizations. */
static inline int
@@ -425,12 +450,18 @@ _dl_allocate_tls_storage (void)
size += TLS_PRE_TCB_SIZE;
#endif
/* Perform the allocation. Reserve space for the required alignment
and the pointer to the original allocation. */
/* Reserve space for the required alignment and the pointer to the
original allocation. */
size_t alignment = GLRO (dl_tls_static_align);
/* Perform the allocation. */
_dl_tls_allocate_begin ();
void *allocated = malloc (size + alignment + sizeof (void *));
if (__glibc_unlikely (allocated == NULL))
return NULL;
{
_dl_tls_allocate_end ();
return NULL;
}
/* Perform alignment and allocate the DTV. */
#if TLS_TCB_AT_TP
@@ -466,6 +497,8 @@ _dl_allocate_tls_storage (void)
result = allocate_dtv (result);
if (result == NULL)
free (allocated);
_dl_tls_allocate_end ();
return result;
}
@@ -483,6 +516,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
size_t newsize = max_modid + DTV_SURPLUS;
size_t oldsize = dtv[-1].counter;
_dl_tls_allocate_begin ();
if (dtv == GL(dl_initial_dtv))
{
/* This is the initial dtv that was either statically allocated in
@@ -494,6 +528,13 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
if (newp == NULL)
oom ();
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
#ifdef SHARED
/* Auditors can trigger a DTV resize event while the full malloc
is not yet in use. Mark the new DTV allocation as the
initial allocation. */
if (!__rtld_malloc_is_complete ())
GL(dl_initial_dtv) = &newp[1];
#endif
}
else
{
@@ -502,6 +543,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
if (newp == NULL)
oom ();
}
_dl_tls_allocate_end ();
newp[0].counter = newsize;
@@ -517,9 +559,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage
for the TLS space. The DTV may be resized, and so this function may
call malloc to allocate that space. The loader's GL(dl_load_tls_lock)
is taken when manipulating global TLS-related data in the loader. */
is taken when manipulating global TLS-related data in the loader.
If MAIN_THREAD, this is the first call during process
initialization. In this case, TLS initialization for secondary
(audit) namespaces is skipped because that has already been handled
by dlopen. */
void *
_dl_allocate_tls_init (void *result, bool init_tls)
_dl_allocate_tls_init (void *result, bool main_thread)
{
if (result == NULL)
/* The memory allocation failed. */
@@ -592,17 +639,21 @@ _dl_allocate_tls_init (void *result, bool init_tls)
some platforms use in static programs requires it. */
dtv[map->l_tls_modid].pointer.val = dest;
/* Copy the initialization image and clear the BSS part. For
audit modules or dependencies with initial-exec TLS, we can not
set the initial TLS image on default loader initialization
because it would already be set by the audit setup. However,
subsequent thread creation would need to follow the default
behaviour. */
if (map->l_ns != LM_ID_BASE && !init_tls)
/* Copy the initialization image and clear the BSS part.
For audit modules or dependencies with initial-exec TLS,
we can not set the initial TLS image on default loader
initialization because it would already be set by the
audit setup, which uses the dlopen code and already
clears l_need_tls_init. Calls with !main_thread from
pthread_create need to initialze TLS for the current
thread regardless of namespace. */
if (map->l_ns != LM_ID_BASE && main_thread)
continue;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
map->l_tls_blocksize - map->l_tls_initimage_size);
if (main_thread)
map->l_need_tls_init = 0;
}
total += cnt;
@@ -626,7 +677,7 @@ _dl_allocate_tls (void *mem)
{
return _dl_allocate_tls_init (mem == NULL
? _dl_allocate_tls_storage ()
: allocate_dtv (mem), true);
: allocate_dtv (mem), false);
}
rtld_hidden_def (_dl_allocate_tls)
@@ -676,7 +727,9 @@ allocate_dtv_entry (size_t alignment, size_t size)
if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
{
/* The alignment is supported by malloc. */
_dl_tls_allocate_begin ();
void *ptr = malloc (size);
_dl_tls_allocate_end ();
return (struct dtv_pointer) { ptr, ptr };
}
@@ -688,7 +741,10 @@ allocate_dtv_entry (size_t alignment, size_t size)
/* Perform the allocation. This is the pointer we need to free
later. */
_dl_tls_allocate_begin ();
void *start = malloc (alloc_size);
_dl_tls_allocate_end ();
if (start == NULL)
return (struct dtv_pointer) {};
@@ -819,7 +875,18 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
dtv entry free it. Note: this is not AS-safe. */
/* XXX Ideally we will at some point create a memory
pool. */
free (dtv[modid].pointer.to_free);
/* Avoid calling free on a null pointer. Some mallocs
incorrectly use dynamic TLS, and depending on how the
free function was compiled, it could call
__tls_get_addr before the null pointer check in the
free implementation. Checking here papers over at
least some dynamic TLS usage by interposed mallocs. */
if (dtv[modid].pointer.to_free != NULL)
{
_dl_tls_allocate_begin ();
free (dtv[modid].pointer.to_free);
_dl_tls_allocate_end ();
}
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
dtv[modid].pointer.to_free = NULL;
@@ -949,10 +1016,22 @@ __tls_get_addr (GET_ADDR_ARGS)
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
if (__glibc_unlikely (dtv[0].counter != gen))
{
/* Update DTV up to the global generation, see CONCURRENCY NOTES
in _dl_update_slotinfo. */
gen = atomic_load_acquire (&GL(dl_tls_generation));
return update_get_addr (GET_ADDR_PARAM, gen);
if (_dl_tls_allocate_active ()
&& GET_ADDR_MODULE < _dl_tls_initial_modid_limit)
/* This is a reentrant __tls_get_addr call, but we can
satisfy it because it's an initially-loaded module ID.
These TLS slotinfo slots do not change, so the
out-of-date generation counter does not matter. However,
if not in a TLS update, still update_get_addr below, to
get off the slow path eventually. */
;
else
{
/* Update DTV up to the global generation, see CONCURRENCY NOTES
in _dl_update_slotinfo. */
gen = atomic_load_acquire (&GL(dl_tls_generation));
return update_get_addr (GET_ADDR_PARAM, gen);
}
}
void *p = dtv[GET_ADDR_MODULE].pointer.val;
@@ -962,7 +1041,7 @@ __tls_get_addr (GET_ADDR_ARGS)
return (char *) p + GET_ADDR_OFFSET;
}
#endif
#endif /* SHARED */
/* Look up the module's TLS block as for __tls_get_addr,
@@ -1011,10 +1090,52 @@ _dl_tls_get_addr_soft (struct link_map *l)
return data;
}
size_t _dl_tls_initial_modid_limit;
void
_dl_tls_initial_modid_limit_setup (void)
{
struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
size_t idx;
for (idx = 0; idx < listp->len; ++idx)
{
struct link_map *l = listp->slotinfo[idx].map;
if (l == NULL
/* The object can be unloaded, so its modid can be
reassociated. */
|| !(l->l_type == lt_executable || l->l_type == lt_library))
break;
}
_dl_tls_initial_modid_limit = idx;
}
/* Add module to slot information data. If DO_ADD is false, only the
required memory is allocated. Must be called with
GL (dl_load_tls_lock) acquired. If the function has already been
called for the link map L with !DO_ADD, then this function will not
raise an exception, otherwise it is possible that it encounters a
memory allocation failure.
Return false if L has already been added to the slotinfo data, or
if L has no TLS data. If the returned value is true, L has been
added with this call (DO_ADD), or has been added in a previous call
(!DO_ADD).
The expected usage is as follows: Call _dl_add_to_slotinfo for
several link maps with DO_ADD set to false, and record if any calls
result in a true result. If there was a true result, call
_dl_add_to_slotinfo again, this time with DO_ADD set to true. (For
simplicity, it's possible to call the function for link maps where
the previous result was false.) The return value from the second
round of calls can be ignored. If there was true result initially,
call _dl_update_slotinfo to update the TLS generation counter. */
bool
_dl_add_to_slotinfo (struct link_map *l, bool do_add)
{
if (l->l_tls_blocksize == 0 || l->l_tls_in_slotinfo)
return false;
/* Now that we know the object is loaded successfully add
modules containing TLS data to the dtv info table. We
might have to increase its size. */
@@ -1043,9 +1164,11 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
the first slot. */
assert (idx == 0);
_dl_tls_allocate_begin ();
listp = (struct dtv_slotinfo_list *)
malloc (sizeof (struct dtv_slotinfo_list)
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
_dl_tls_allocate_end ();
if (listp == NULL)
{
/* We ran out of memory while resizing the dtv slotinfo list. */
@@ -1068,7 +1191,10 @@ cannot create TLS data structures"));
atomic_store_relaxed (&listp->slotinfo[idx].map, l);
atomic_store_relaxed (&listp->slotinfo[idx].gen,
GL(dl_tls_generation) + 1);
l->l_tls_in_slotinfo = true;
}
return true;
}
#if PTHREAD_IN_LIBC
+17 -11
View File
@@ -32,6 +32,7 @@
#include <ldsodefs.h>
#include <array_length.h>
#include <dl-minimal-malloc.h>
#include <dl-symbol-redir-ifunc.h>
#define TUNABLES_INTERNAL 1
#include "dl-tunables.h"
@@ -223,6 +224,7 @@ parse_tunables_string (const char *valstring, struct tunable_toset_t *tunables)
{
tunables[ntunables++] =
(struct tunable_toset_t) { cur, value, p - value };
break;
}
}
@@ -234,23 +236,27 @@ parse_tunables_string (const char *valstring, struct tunable_toset_t *tunables)
static void
parse_tunables (const char *valstring)
{
struct tunable_toset_t tunables[tunables_list_size];
int ntunables = parse_tunables_string (valstring, tunables);
if (ntunables == -1)
struct tunable_toset_t tunables[tunables_list_size] = { 0 };
if (parse_tunables_string (valstring, tunables) == -1)
{
_dl_error_printf (
"WARNING: ld.so: invalid GLIBC_TUNABLES `%s': ignored.\n", valstring);
return;
}
for (int i = 0; i < ntunables; i++)
if (!tunable_initialize (tunables[i].t, tunables[i].value,
tunables[i].len))
_dl_error_printf ("WARNING: ld.so: invalid GLIBC_TUNABLES value `%.*s' "
"for option `%s': ignored.\n",
(int) tunables[i].len,
tunables[i].value,
tunables[i].t->name);
for (int i = 0; i < tunables_list_size; i++)
{
if (tunables[i].t == NULL)
continue;
if (!tunable_initialize (tunables[i].t, tunables[i].value,
tunables[i].len))
_dl_error_printf ("WARNING: ld.so: invalid GLIBC_TUNABLES value `%.*s' "
"for option `%s': ignored.\n",
(int) tunables[i].len,
tunables[i].value,
tunables[i].t->name);
}
}
/* Initialize the tunables list from the environment. For now we only use the
+7
View File
@@ -357,6 +357,13 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
}
}
/* The empty string has ELF hash zero. This avoids a NULL check
before the version string comparison in check_match in
dl-lookup.c. */
for (unsigned int i = 0; i < map->l_nversions; ++i)
if (map->l_versions[i].name == NULL)
map->l_versions[i].name = "";
}
/* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue
+4
View File
@@ -1234,6 +1234,10 @@ typedef struct
#define AT_RSEQ_FEATURE_SIZE 27 /* rseq supported feature size. */
#define AT_RSEQ_ALIGN 28 /* rseq allocation alignment. */
/* More machine-dependent hints about processor capabilities. */
#define AT_HWCAP3 29 /* extension of AT_HWCAP. */
#define AT_HWCAP4 30 /* extension of AT_HWCAP. */
#define AT_EXECFN 31 /* Filename of executable. */
/* Pointer to the global system page used for system calls and other
+41
View File
@@ -0,0 +1,41 @@
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <https://www.gnu.org/licenses/>. */
#ifndef _ENDSWITH_H
#define _ENDSWITH_H
#include <stdbool.h>
#include <string.h>
/* Return true if the N bytes at NAME end with with the characters in
the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
Expected to be called with a string literal for SUFFIX. */
static inline bool
endswithn (const char *name, size_t n, const char *suffix)
{
return (n >= strlen (suffix)
&& memcmp (name + n - strlen (suffix), suffix,
strlen (suffix)) == 0);
}
/* Same as endswithn, but uses the entire SUBJECT for matching. */
static inline bool
endswith (const char *subject, const char *suffix)
{
return endswithn (subject, strlen (subject), suffix);
}
#endif /* _ENDSWITH_H */
+1 -11
View File
@@ -40,6 +40,7 @@
#include <libgen.h>
#include <ldconfig.h>
#include <endswith.h>
#include <dl-cache.h>
#include <dl-hwcaps.h>
#include <dl-is_dso.h>
@@ -661,17 +662,6 @@ struct dlib_entry
struct dlib_entry *next;
};
/* Return true if the N bytes at NAME end with with the characters in
the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
Expected to be called with a string literal for SUFFIX. */
static inline bool
endswithn (const char *name, size_t n, const char *suffix)
{
return (n >= strlen (suffix)
&& memcmp (name + n - strlen (suffix), suffix,
strlen (suffix)) == 0);
}
/* Skip some temporary DSO files. These files may be partially written
and lead to ldconfig crashes when examined. */
static bool
+2 -1
View File
@@ -33,6 +33,7 @@
#include <gnu/lib-names.h>
#include <ldconfig.h>
#include <endswith.h>
#define Elf32_CLASS ELFCLASS32
#define Elf64_CLASS ELFCLASS64
@@ -48,7 +49,7 @@ static bool
is_gdb_python_file (const char *name)
{
size_t len = strlen (name);
return len > 7 && strcmp (name + len - 7, "-gdb.py") == 0;
return endswithn (name, len, "-gdb.py");
}
/* Returns 0 if everything is ok, != 0 in case of error. */
+121 -107
View File
@@ -788,6 +788,8 @@ init_tls (size_t naudit)
_dl_fatal_printf ("\
cannot allocate TLS data structures for initial thread\n");
_dl_tls_initial_modid_limit_setup ();
/* Store for detection of the special case by __tls_get_addr
so it knows not to pass this dtv to the normal realloc. */
GL(dl_initial_dtv) = GET_DTV (tcbp);
@@ -1282,6 +1284,60 @@ rtld_setup_main_map (struct link_map *main_map)
return has_interp;
}
/* Set up the program header information for the dynamic linker
itself. It can be accessed via _r_debug and dl_iterate_phdr
callbacks, and it is used by _dl_find_object. */
static void
rtld_setup_phdr (void)
{
/* Starting from binutils-2.23, the linker will define the magic
symbol __ehdr_start to point to our own ELF header if it is
visible in a segment that also includes the phdrs. */
const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start;
assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
GL(dl_rtld_map).l_phdr = rtld_phdr;
GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
GL(dl_rtld_map).l_contiguous = 1;
/* The linker may not have produced a contiguous object. The kernel
will load the object with actual gaps (unlike the glibc loader
for shared objects, which always produces a contiguous mapping).
See similar logic in rtld_setup_main_map above. */
{
ElfW(Addr) expected_load_address = 0;
for (const ElfW(Phdr) *ph = rtld_phdr; ph < &rtld_phdr[rtld_ehdr->e_phnum];
++ph)
if (ph->p_type == PT_LOAD)
{
ElfW(Addr) mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1);
if (GL(dl_rtld_map).l_contiguous && expected_load_address != 0
&& expected_load_address != mapstart)
GL(dl_rtld_map).l_contiguous = 0;
ElfW(Addr) allocend = ph->p_vaddr + ph->p_memsz;
/* The next expected address is the page following this load
segment. */
expected_load_address = ((allocend + GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
}
}
/* PT_GNU_RELRO is usually the last phdr. */
size_t cnt = rtld_ehdr->e_phnum;
while (cnt-- > 0)
if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
{
GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
break;
}
}
/* Adjusts the contents of the stack and related globals for the user
entry point. The ld.so processed skip_args arguments and bumped
_dl_argv and _dl_argc accordingly. Those arguments are removed from
@@ -1747,33 +1803,7 @@ dl_main (const ElfW(Phdr) *phdr,
++GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
++GL(dl_load_adds);
/* Starting from binutils-2.23, the linker will define the magic symbol
__ehdr_start to point to our own ELF header if it is visible in a
segment that also includes the phdrs. If that's not available, we use
the old method that assumes the beginning of the file is part of the
lowest-addressed PT_LOAD segment. */
/* Set up the program header information for the dynamic linker
itself. It is needed in the dl_iterate_phdr callbacks. */
const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start;
assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
GL(dl_rtld_map).l_phdr = rtld_phdr;
GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
/* PT_GNU_RELRO is usually the last phdr. */
size_t cnt = rtld_ehdr->e_phnum;
while (cnt-- > 0)
if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
{
GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
break;
}
rtld_setup_phdr ();
/* Add the dynamic linker to the TLS list if it also uses TLS. */
if (GL(dl_rtld_map).l_tls_blocksize != 0)
@@ -1820,8 +1850,7 @@ dl_main (const ElfW(Phdr) *phdr,
elf_setup_debug_entry (main_map, r);
/* We start adding objects. */
r->r_state = RT_ADD;
_dl_debug_state ();
_dl_debug_change_state (r, RT_ADD);
LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
/* Auditing checkpoint: we are ready to signal that the initial map
@@ -1980,43 +2009,37 @@ dl_main (const ElfW(Phdr) *phdr,
if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map))
break;
bool rtld_multiple_ref = false;
if (__glibc_likely (i < main_map->l_searchlist.r_nlist))
/* Insert the link map for the dynamic loader into the chain in
symbol search order because gdb uses the chain's order as its
symbol search order. */
GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
if (__glibc_likely (state.mode == rtld_mode_normal))
{
/* Some DT_NEEDED entry referred to the interpreter object itself, so
put it back in the list of visible objects. We insert it into the
chain in symbol search order because gdb uses the chain's order as
its symbol search order. */
rtld_multiple_ref = true;
GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
if (__glibc_likely (state.mode == rtld_mode_normal))
{
GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
? main_map->l_searchlist.r_list[i + 1]
: NULL);
GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
? main_map->l_searchlist.r_list[i + 1]
: NULL);
#ifdef NEED_DL_SYSINFO_DSO
if (GLRO(dl_sysinfo_map) != NULL
&& GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map)
&& GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map))
GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map);
if (GLRO(dl_sysinfo_map) != NULL
&& GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map)
&& GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map))
GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map);
#endif
}
else
/* In trace mode there might be an invisible object (which we
could not find) after the previous one in the search list.
In this case it doesn't matter much where we put the
interpreter object, so we just initialize the list pointer so
that the assertion below holds. */
GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next;
}
else
/* In trace mode there might be an invisible object (which we
could not find) after the previous one in the search list.
In this case it doesn't matter much where we put the
interpreter object, so we just initialize the list pointer so
that the assertion below holds. */
GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next;
assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next);
GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map);
if (GL(dl_rtld_map).l_next != NULL)
{
assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev);
GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map);
}
assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next);
GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map);
if (GL(dl_rtld_map).l_next != NULL)
{
assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev);
GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map);
}
/* Now let us see whether all libraries are available in the
@@ -2266,25 +2289,25 @@ dl_main (const ElfW(Phdr) *phdr,
_rtld_main_check (main_map, _dl_argv[0]);
/* Now we have all the objects loaded. Relocate them all except for
the dynamic linker itself. We do this in reverse order so that copy
relocs of earlier objects overwrite the data written by later
objects. We do not re-relocate the dynamic linker itself in this
loop because that could result in the GOT entries for functions we
call being changed, and that would break us. It is safe to relocate
the dynamic linker out of order because it has no copy relocations.
Likewise for libc, which is relocated early to ensure that IFUNC
resolvers in libc work. */
/* Now we have all the objects loaded. */
int consider_profiling = GLRO(dl_profile) != NULL;
/* If we are profiling we also must do lazy reloaction. */
GLRO(dl_lazy) |= consider_profiling;
/* If libc.so has been loaded, relocate it early, after the dynamic
loader itself. The initial self-relocation of ld.so should be
sufficient for IFUNC resolvers in libc.so. */
if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
_dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map,
GL(dl_ns)[LM_ID_BASE].libc_map->l_scope,
GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling);
{
RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
_dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map,
GL(dl_ns)[LM_ID_BASE].libc_map->l_scope,
GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling);
rtld_timer_accum (&relocate_time, start);
}
RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
@@ -2307,9 +2330,8 @@ dl_main (const ElfW(Phdr) *phdr,
/* Also allocated with the fake malloc(). */
l->l_free_initfini = 0;
if (l != &GL(dl_rtld_map))
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
consider_profiling);
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
consider_profiling);
/* Add object to slot information data if necessasy. */
if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
@@ -2335,7 +2357,7 @@ dl_main (const ElfW(Phdr) *phdr,
into the main thread's TLS area, which we allocated above.
Note: thread-local variables must only be accessed after completing
the next step. */
_dl_allocate_tls_init (tcbp, false);
_dl_allocate_tls_init (tcbp, true);
/* And finally install it for the main thread. */
if (! __rtld_tls_init_tp_called)
@@ -2344,36 +2366,29 @@ dl_main (const ElfW(Phdr) *phdr,
/* Make sure no new search directories have been added. */
assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs));
if (rtld_multiple_ref)
/* Set up the object lookup structures. */
_dl_find_object_init ();
/* If libc.so was loaded, relocate ld.so against it. Complete ld.so
initialization with mutex symbols from libc.so and malloc symbols
from the global scope. */
if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
{
/* There was an explicit ref to the dynamic linker as a shared lib.
Re-relocate ourselves with user-controlled symbol definitions.
We must do this after TLS initialization in case after this
re-relocation, we might call a user-supplied function
(e.g. calloc from _dl_relocate_object) that uses TLS data. */
/* Set up the object lookup structures. */
_dl_find_object_init ();
/* The malloc implementation has been relocated, so resolving
its symbols (and potentially calling IFUNC resolvers) is safe
at this point. */
__rtld_malloc_init_real (main_map);
/* Likewise for the locking implementation. */
__rtld_mutex_init ();
RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
/* Mark the link map as not yet relocated again. */
GL(dl_rtld_map).l_relocated = 0;
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
_dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
rtld_timer_accum (&relocate_time, start);
__rtld_mutex_init ();
__rtld_malloc_init_real (main_map);
/* Update copy-relocated _r_debug if necessary. */
_dl_debug_post_relocate (main_map);
}
/* All ld.so initialization is complete. Apply RELRO. */
_dl_protect_relro (&GL(dl_rtld_map));
/* Relocation is complete. Perform early libc initialization. This
is the initial libc, even if audit modules have been loaded with
other libcs. */
@@ -2386,16 +2401,15 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
_dl_sysdep_start_cleanup ();
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
/* Notify the debugger all new objects are now ready to go. We must re-get
the address since by now the variable might be in another object. */
r = _dl_debug_update (LM_ID_BASE);
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
_dl_debug_change_state (r, RT_CONSISTENT);
LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
#if defined USE_LDCONFIG && !defined MAP_COPY
/* We must munmap() the cache file. */
_dl_unload_cache ();
+40 -1
View File
@@ -38,6 +38,7 @@
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <intprops.h>
/* Get libc version number. */
#include "../version.h"
@@ -410,6 +411,7 @@ load_shobj (const char *name)
int fd;
ElfW(Shdr) *shdr;
size_t pagesize = getpagesize ();
struct stat st;
/* Since we use dlopen() we must be prepared to work around the sometimes
strange lookup rules for the shared objects. If we have a file foo.so
@@ -553,14 +555,39 @@ load_shobj (const char *name)
error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
map->l_name);
if (fstat (fd, &st) < 0)
error (EXIT_FAILURE, errno, _("stat(%s) failure"), map->l_name);
/* We're depending on data that's being read from the file, so be a
bit paranoid here and make sure the requests are reasonable -
i.e. both size and offset are nonnegative and smaller than the
file size, as well as the offset of the end of the data. PREAD
would have failed anyway, but this is more robust and explains
what happened better. Note that SZ must be unsigned and OFF may
be signed or unsigned. */
#define PCHECK(sz1,off1) { \
size_t sz = sz1, end_off; \
off_t off = off1; \
if (sz > st.st_size \
|| off < 0 || off > st.st_size \
|| INT_ADD_WRAPV (sz, off, &end_off) \
|| end_off > st.st_size) \
error (EXIT_FAILURE, ERANGE, \
_("read outside of file extents %zu + %jd > %jd"), \
sz, (intmax_t) off, (intmax_t) st.st_size); \
}
/* Map the section header. */
size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
shdr = (ElfW(Shdr) *) alloca (size);
PCHECK (size, ehdr->e_shoff);
if (pread (fd, shdr, size, ehdr->e_shoff) != size)
error (EXIT_FAILURE, errno, _("reading of section headers failed"));
/* Get the section header string table. */
char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
PCHECK (shdr[ehdr->e_shstrndx].sh_size,
shdr[ehdr->e_shstrndx].sh_offset);
if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
shdr[ehdr->e_shstrndx].sh_offset)
!= shdr[ehdr->e_shstrndx].sh_size)
@@ -588,6 +615,7 @@ load_shobj (const char *name)
size_t size = debuglink_entry->sh_size;
char *debuginfo_fname = (char *) alloca (size + 1);
debuginfo_fname[size] = '\0';
PCHECK (size, debuglink_entry->sh_offset);
if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
!= size)
{
@@ -641,21 +669,32 @@ load_shobj (const char *name)
if (fd2 != -1)
{
ElfW(Ehdr) ehdr2;
struct stat st;
if (fstat (fd2, &st) < 0)
error (EXIT_FAILURE, errno, _("stat(%s) failure"), workbuf);
/* Read the ELF header. */
PCHECK (sizeof (ehdr2), 0);
if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
error (EXIT_FAILURE, errno,
_("reading of ELF header failed"));
/* Map the section header. */
size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
size_t size;
if (INT_MULTIPLY_WRAPV (ehdr2.e_shnum, sizeof (ElfW(Shdr)), &size))
error (EXIT_FAILURE, errno, _("too many section headers"));
ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
PCHECK (size, ehdr2.e_shoff);
if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
error (EXIT_FAILURE, errno,
_("reading of section headers failed"));
/* Get the section header string table. */
shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
PCHECK (shdr2[ehdr2.e_shstrndx].sh_size,
shdr2[ehdr2.e_shstrndx].sh_offset);
if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
shdr2[ehdr2.e_shstrndx].sh_offset)
!= shdr2[ehdr2.e_shstrndx].sh_size)
+46
View File
@@ -0,0 +1,46 @@
/* Loading TLS-using modules from auditors (bug 32412). Main program.
Copyright (C) 2021-2025 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 <support/xdlfcn.h>
#include <stdio.h>
static int
do_test (void)
{
puts ("info: start of main program");
/* Load TLS-using modules, to trigger DTV resizing. The dynamic
linker will load them again (requiring their own TLS) because the
dlopen calls from the auditor were in the auditing namespace. */
for (int i = 1; i <= 19; ++i)
{
char dso[30];
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
char sym[30];
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
void *handle = xdlopen (dso, RTLD_LAZY);
int (*func) (void) = xdlsym (handle, sym);
/* Trigger TLS allocation. */
func ();
}
return 0;
}
#include <support/test-driver.c>
+69 -16
View File
@@ -17,6 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
#include <endswith.h>
#include <errno.h>
#include <getopt.h>
#include <link.h>
@@ -30,16 +31,21 @@
#include <support/xstdio.h>
#include <support/xdlfcn.h>
#include <support/support.h>
#include <support/test-driver.h>
static int restart;
static int do_dlclose;
#define CMDLINE_OPTIONS \
{ "restart", no_argument, &restart, 1 },
{ "restart", no_argument, &restart, 1 }, \
{ "dlclose", no_argument, &do_dlclose, 1 }, \
static int
handle_restart (void)
{
xdlopen ("tst-audit23mod.so", RTLD_NOW);
xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
void *handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
if (do_dlclose)
xdlclose (handle);
return 0;
}
@@ -59,8 +65,8 @@ is_vdso (const char *str)
|| startswith (str, "linux-vdso");
}
static int
do_test (int argc, char *argv[])
static void
do_one_test (int argc, char *argv[], bool pass_dlclose_flag)
{
/* We must have either:
- One or four parameters left if called initially:
@@ -68,16 +74,15 @@ do_test (int argc, char *argv[])
+ "--library-path" optional
+ the library path optional
+ the application name */
if (restart)
return handle_restart ();
char *spargv[9];
char *spargv[10];
TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv));
int i = 0;
for (; i < argc - 1; i++)
spargv[i] = argv[i + 1];
spargv[i++] = (char *) "--direct";
spargv[i++] = (char *) "--restart";
if (pass_dlclose_flag)
spargv[i++] = (char *) "--dlclose";
spargv[i] = NULL;
setenv ("LD_AUDIT", "tst-auditmod23.so", 0);
@@ -85,14 +90,30 @@ do_test (int argc, char *argv[])
= support_capture_subprogram (spargv[0], spargv);
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
{
FILE *fp = fmemopen (result.err.buffer, result.err.length, "r");
TEST_VERIFY (fp != NULL);
unsigned int line = 0;
char *buffer = NULL;
size_t buffer_length = 0;
puts ("info: *** audit log start ***");
while (xgetline (&buffer, &buffer_length, fp))
printf ("%6u\t%s", ++line, buffer);
puts ("info: *** audit log end ***");
free (buffer);
xfclose (fp);
}
/* The expected la_objopen/la_objclose:
1. executable
2. loader
3. libc.so
4. tst-audit23mod.so
5. libc.so (LM_ID_NEWLM).
6. vdso (optional and ignored). */
enum { max_objs = 6 };
4. libgcc_s.so (one some architectures, for libsupport)
5. tst-audit23mod.so
6. libc.so (LM_ID_NEWLM).
7. loader (proxy link map in new namespace)
vdso (optional and ignored). */
enum { max_objs = 7 };
struct la_obj_t
{
char *lname;
@@ -115,8 +136,10 @@ do_test (int argc, char *argv[])
TEST_VERIFY (out != NULL);
char *buffer = NULL;
size_t buffer_length = 0;
unsigned int line = 0;
while (xgetline (&buffer, &buffer_length, out))
{
++line;
if (startswith (buffer, "la_activity: "))
{
uintptr_t cookie;
@@ -127,8 +150,14 @@ do_test (int argc, char *argv[])
/* The cookie identifies the object at the head of the link map,
so we only add a new namespace if it changes from the previous
one. This works since dlmopen is the last in the test body. */
if (cookie != last_act_cookie && last_act_cookie != -1)
one. This works since dlmopen is the last in the test body.
Currently, this does not work as expected because there
is no head link map if a namespace is completely deleted.
No LA_ACT_CONSISTENT event is generated in that case.
See the comment in _dl_audit_activity_nsid and bug 32068. */
if (cookie != last_act_cookie && last_act_cookie != -1
&& !pass_dlclose_flag)
TEST_COMPARE (last_act, LA_ACT_CONSISTENT);
if (this_act == LA_ACT_ADD && acts[nacts] != cookie)
@@ -174,8 +203,8 @@ do_test (int argc, char *argv[])
if (is_vdso (lname))
continue;
if (nobjs == max_objs)
FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld",
lname, laddr, lmid);
FAIL_EXIT1 ("(line %u) non expected la_objopen: %s %"PRIxPTR" %ld",
line, lname, laddr, lmid);
objs[nobjs].lname = lname;
objs[nobjs].laddr = laddr;
objs[nobjs].lmid = lmid;
@@ -217,11 +246,26 @@ do_test (int argc, char *argv[])
}
}
Lmid_t lmid_other = LM_ID_NEWLM;
unsigned int other_namespace_count = 0;
for (size_t i = 0; i < nobjs; i++)
{
if (objs[i].lmid != LM_ID_BASE)
{
if (lmid_other == LM_ID_NEWLM)
lmid_other = objs[i].lmid;
TEST_COMPARE (objs[i].lmid, lmid_other);
++other_namespace_count;
if (!(endswith (objs[i].lname, "/" LIBC_SO)
|| endswith (objs[i].lname, "/" LD_SO)))
FAIL ("unexpected object in secondary namespace: %s",
objs[i].lname);
}
TEST_COMPARE (objs[i].closed, true);
free (objs[i].lname);
}
/* Both libc.so and ld.so should be present. */
TEST_COMPARE (other_namespace_count, 2);
/* la_activity(LA_ACT_CONSISTENT) should be the last callback received.
Since only one link map may be not-CONSISTENT at a time, this also
@@ -231,7 +275,16 @@ do_test (int argc, char *argv[])
free (buffer);
xfclose (out);
}
static int
do_test (int argc, char *argv[])
{
if (restart)
return handle_restart ();
do_one_test (argc, argv, false);
do_one_test (argc, argv, true);
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
/* Loading TLS-using modules from auditors (bug 32412). Audit module.
Copyright (C) 2021-2025 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 <dlfcn.h>
#include <link.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
unsigned int
la_version (unsigned int version)
{
/* Open some modules, to trigger DTV resizing before the switch to
the main malloc. */
for (int i = 1; i <= 19; ++i)
{
char dso[30];
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
char sym[30];
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
void *handle = dlopen (dso, RTLD_LAZY);
if (handle == NULL)
{
printf ("error: dlmopen from auditor: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
int (*func) (void) = dlsym (handle, sym);
if (func == NULL)
{
printf ("error: dlsym from auditor: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
/* Trigger TLS allocation. */
func ();
}
puts ("info: TLS-using modules loaded from auditor");
fflush (stdout);
return LAV_CURRENT;
}
+2
View File
@@ -0,0 +1,2 @@
#define BUILD_FOR_NONPIC
#include "tst-dlmopen4.c"
+2
View File
@@ -0,0 +1,2 @@
#define BUILD_FOR_PIC
#include "tst-dlmopen4.c"
+22
View File
@@ -46,6 +46,15 @@ do_test (void)
TEST_COMPARE (debug->base.r_version, 1);
TEST_VERIFY_EXIT (debug->r_next == NULL);
#ifdef BUILD_FOR_PIC
/* In a PIC build, using _r_debug directly should give us the same
object. */
TEST_VERIFY (&_r_debug == &debug->base);
#endif
#ifdef BUILD_FOR_NONPIC
TEST_COMPARE (_r_debug.r_version, 1);
#endif
void *h = xdlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so",
RTLD_LAZY);
@@ -57,6 +66,19 @@ do_test (void)
const char *name = basename (debug->r_next->base.r_map->l_name);
TEST_COMPARE_STRING (name, "tst-dlmopen1mod.so");
#ifdef BUILD_FOR_NONPIC
/* If a copy relocation is used, it must be at version 1. */
if (&_r_debug != &debug->base)
{
TEST_COMPARE (_r_debug.r_version, 1);
TEST_COMPARE ((uintptr_t) _r_debug.r_map,
(uintptr_t) debug->base.r_map);
TEST_COMPARE (_r_debug.r_brk, debug->base.r_brk);
TEST_COMPARE (_r_debug.r_state, debug->base.r_state);
TEST_COMPARE (_r_debug.r_ldbase, debug->base.r_ldbase);
}
#endif
xdlclose (h);
return 0;
+104
View File
@@ -0,0 +1,104 @@
/* Auditor that opens again an object that just has been opened.
Copyright (C) 2024 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 <dlfcn.h>
#include <link.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
unsigned int
la_version (unsigned int v)
{
return LAV_CURRENT;
}
static bool trigger_on_la_activity;
unsigned int
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
{
printf ("info: la_objopen: \"%s\"\n", map->l_name);
if (strstr (map->l_name, "/tst-dlopen-auditdupmod.so") != NULL)
trigger_on_la_activity = true;
return 0;
}
void
la_activity (uintptr_t *cookie, unsigned int flag)
{
static unsigned int calls;
++calls;
printf ("info: la_activity: call %u (flag %u)\n", calls, flag);
fflush (stdout);
if (trigger_on_la_activity)
{
/* Avoid triggering on the dlmopen call below. */
static bool recursion;
if (recursion)
return;
recursion = true;
puts ("info: about to dlmopen tst-dlopen-auditdupmod.so");
fflush (stdout);
void *handle = dlmopen (LM_ID_BASE, "tst-dlopen-auditdupmod.so",
RTLD_NOW);
if (handle == NULL)
{
printf ("error: dlmopen: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
/* Check that the constructor has not run. Running the
constructor would require constructing its dependencies, but
the constructor call that triggered this auditing activity
has not completed, and constructors among the dependencies
may not be able to deal with that. */
int *status = dlsym (handle, "auditdupmod_status");
if (status == NULL)
{
printf ("error: dlsym: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
printf ("info: auditdupmod_status == %d\n", *status);
if (*status != 0)
{
puts ("error: auditdupmod_status == 0 expected");
fflush (stdout);
_exit (1);
}
/* Checked in the destructor and the main program. */
++*status;
printf ("info: auditdupmod_status == %d\n", *status);
/* Check that the module has been relocated. */
int **status_address = dlsym (handle, "auditdupmod_status_address");
if (status_address == NULL || *status_address != status)
{
puts ("error: invalid auditdupmod_status address in"
" tst-dlopen-auditdupmod.so");
fflush (stdout);
_exit (1);
}
fflush (stdout);
}
}
+36
View File
@@ -0,0 +1,36 @@
/* Test that recursive dlopen from auditor works (bug 31986).
Copyright (C) 2024 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>
static int
do_test (void)
{
puts ("info: about to dlopen tst-dlopen-auditdupmod.so");
fflush (stdout);
void *handle = xdlopen ("tst-dlopen-auditdupmod.so", RTLD_NOW);
int *status = xdlsym (handle, "auditdupmod_status");
printf ("info: auditdupmod_status == %d (from main)\n", *status);
TEST_COMPARE (*status, 2);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>
+48
View File
@@ -0,0 +1,48 @@
/* Directly opened test module that gets reopened from the auditor.
Copyright (C) 2024 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 <stdlib.h>
#include <support/xdlfcn.h>
int auditdupmod_status;
/* Used to check for successful relocation processing. */
int *auditdupmod_status_address = &auditdupmod_status;
static void __attribute__ ((constructor))
init (void)
{
++auditdupmod_status;
printf ("info: tst-dlopen-auditdupmod.so constructor called (status %d)\n",
auditdupmod_status);
}
static void __attribute__ ((destructor))
fini (void)
{
/* The tst-dlopen-auditdup-auditmod.so auditor incremented
auditdupmod_status. */
printf ("info: tst-dlopen-auditdupmod.so destructor called (status %d)\n",
auditdupmod_status);
if (auditdupmod_status != 2)
{
puts ("error: auditdupmod_status == 2 expected");
exit (1);
}
}
+55
View File
@@ -0,0 +1,55 @@
/* Module calling dlopen (NULL, RTLD_LAZY) to obtain the global scope.
Copyright (C) 2024 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 <dlfcn.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int mod1_status;
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlopen-constructor-null-mod1.so constructor");
void *handle = dlopen (NULL, RTLD_LAZY);
if (handle == NULL)
{
printf ("error: %s\n", dlerror ());
exit (1);
}
puts ("info: dlopen returned");
if (dlsym (handle, "malloc") != malloc)
{
puts ("error: dlsym did not produce expected result");
exit (1);
}
dlclose (handle);
/* Check that the second module's constructor has not executed. */
if (getenv ("mod2_status") != NULL)
{
printf ("error: mod2_status environment variable set: %s\n",
getenv ("mod2_status"));
exit (1);
}
/* Communicate to the second module that the constructor executed. */
mod1_status = 1;
}
+37
View File
@@ -0,0 +1,37 @@
/* Module whose constructor should not be invoked by dlopen (NULL, RTLD_LAZY).
Copyright (C) 2024 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 <stdlib.h>
extern int mod1_status;
int mod2_status;
static void __attribute__ ((constructor))
init (void)
{
printf ("info: tst-dlopen-constructor-null-mod2.so constructor"
" (mod1_status=%d)", mod1_status);
if (!(mod1_status == 1 && mod2_status == 0))
{
puts ("error: mod1_status == 1 && mod2_status == 0 expected");
exit (1);
}
setenv ("mod2_status", "constructed", 1);
mod2_status = 1;
}
+38
View File
@@ -0,0 +1,38 @@
/* Verify that dlopen (NULL, RTLD_LAZY) does not complete initialization.
Copyright (C) 2024 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/>. */
/* This test mimics what the glvndSetupPthreads function in libglvnd
does. */
#include <stdlib.h>
#include <support/check.h>
/* Defined and initialized in the shared objects. */
extern int mod1_status;
extern int mod2_status;
static int
do_test (void)
{
TEST_COMPARE (mod1_status, 1);
TEST_COMPARE (mod2_status, 1);
TEST_COMPARE_STRING (getenv ("mod2_status"), "constructed");
return 0;
}
#include <support/test-driver.c>
+1
View File
@@ -0,0 +1 @@
/* Opening this object should not succeed. */
+106
View File
@@ -0,0 +1,106 @@
/* Test case for ignored LD_LIBRARY_PATH in static startug (bug 32976).
Copyright (C) 2025 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 <dlfcn.h>
#include <gnu/lib-names.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <sys/wait.h>
#include <unistd.h>
/* This is the name of our test object. Use a custom module for
testing, so that this object does not get picked up from the system
path. */
static const char dso_name[] = "tst-dlopen-sgid-mod.so";
/* Used to mark the recursive invocation. */
static const char magic_argument[] = "run-actual-test";
static int
do_test (void)
{
/* Pathname of the directory that receives the shared objects this
test attempts to load. */
char *libdir = support_create_temp_directory ("tst-dlopen-sgid-");
/* This is supposed to be ignored and stripped. */
TEST_COMPARE (setenv ("LD_LIBRARY_PATH", libdir, 1), 0);
/* Copy of libc.so.6. */
{
char *from = xasprintf ("%s/%s", support_objdir_root, LIBC_SO);
char *to = xasprintf ("%s/%s", libdir, LIBC_SO);
add_temp_file (to);
support_copy_file (from, to);
free (to);
free (from);
}
/* Copy of the test object. */
{
char *from = xasprintf ("%s/elf/%s", support_objdir_root, dso_name);
char *to = xasprintf ("%s/%s", libdir, dso_name);
add_temp_file (to);
support_copy_file (from, to);
free (to);
free (from);
}
free (libdir);
support_capture_subprogram_self_sgid (magic_argument);
return 0;
}
static void
alternative_main (int argc, char **argv)
{
if (argc == 2 && strcmp (argv[1], magic_argument) == 0)
{
if (getgid () == getegid ())
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
/* Should be removed due to SGID. */
TEST_COMPARE_STRING (getenv ("LD_LIBRARY_PATH"), NULL);
TEST_VERIFY (dlopen (dso_name, RTLD_NOW) == NULL);
{
const char *message = dlerror ();
TEST_COMPARE_STRING (message,
"tst-dlopen-sgid-mod.so:"
" cannot open shared object file:"
" No such file or directory");
}
support_record_failure_barrier ();
exit (EXIT_SUCCESS);
}
}
#define PREPARE alternative_main
#include <support/test-driver.c>
+40
View File
@@ -0,0 +1,40 @@
/* Test that dlopen preserves already accessed TLS (bug 31717).
Copyright (C) 2024 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 <stdbool.h>
#include <support/check.h>
#include <support/xdlfcn.h>
#include <ctype.h>
static int
do_test (void)
{
void *handle = xdlopen ("tst-dlopen-tlsreinitmod1.so", RTLD_NOW);
bool *tlsreinitmod3_tested = xdlsym (handle, "tlsreinitmod3_tested");
TEST_VERIFY (*tlsreinitmod3_tested);
xdlclose (handle);
/* This crashes if the libc.so.6 TLS image has been reverted. */
TEST_VERIFY (!isupper ('@'));
return 0;
}
#include <support/test-driver.c>
+39
View File
@@ -0,0 +1,39 @@
/* Test that dlopen preserves already accessed TLS (bug 31717).
Variant with initially-linked modules.
Copyright (C) 2024 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 <stdbool.h>
#include <support/check.h>
#include <support/xdlfcn.h>
static int
do_test (void)
{
/* Defined in tst-dlopen-tlsreinitmod3.so. */
extern bool tlsreinitmod3_tested;
TEST_VERIFY (tlsreinitmod3_tested);
/* This crashes if the libc.so.6 TLS image has been reverted. */
TEST_VERIFY (!isupper ('@'));
return 0;
}
#include <support/test-driver.c>
+2
View File
@@ -0,0 +1,2 @@
/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */
#include "tst-dlopen-tlsreinit1.c"
+2
View File
@@ -0,0 +1,2 @@
/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */
#include "tst-dlopen-tlsreinit2.c"
+20
View File
@@ -0,0 +1,20 @@
/* Test that dlopen preserves already accessed TLS (bug 31717), module 1.
Copyright (C) 2024 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/>. */
/* This module triggers loading of tst-dlopen-tlsreinitmod2.so and
tst-dlopen-tlsreinitmod3.so. */
+30
View File
@@ -0,0 +1,30 @@
/* Test that dlopen preserves already accessed TLS (bug 31717), module 2.
Copyright (C) 2024 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>
/* Defined in tst-dlopen-tlsreinitmod3.so. This an underlinked symbol
dependency. */
extern void call_tlsreinitmod3 (void);
static void __attribute__ ((constructor))
tlsreinitmod2_init (void)
{
puts ("info: constructor of tst-dlopen-tlsreinitmod2.so invoked");
call_tlsreinitmod3 ();
}
+102
View File
@@ -0,0 +1,102 @@
/* Test that dlopen preserves already accessed TLS (bug 31717), module 3.
Copyright (C) 2024 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 <dlfcn.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
/* Used to verify from the main program that the test ran. */
bool tlsreinitmod3_tested;
/* This TLS variable must not revert back to the initial state after
dlopen. */
static __thread int tlsreinitmod3_state = 1;
/* Set from the ELF constructor during dlopen. */
static bool tlsreinitmod3_constructed;
/* Second half of test, behind a compiler barrier. The compiler
barrier is necessary to prevent carrying over TLS address
information from call_tlsreinitmod3 to call_tlsreinitmod3_tail. */
void call_tlsreinitmod3_tail (void *self) __attribute__ ((weak));
/* Called from tst-dlopen-tlsreinitmod2.so. */
void
call_tlsreinitmod3 (void)
{
printf ("info: call_tlsreinitmod3 invoked (state=%d)\n",
tlsreinitmod3_state);
if (tlsreinitmod3_constructed)
{
puts ("error: call_tlsreinitmod3 called after ELF constructor");
fflush (stdout);
/* Cannot rely on test harness due to dynamic linking. */
_exit (1);
}
tlsreinitmod3_state = 2;
/* Self-dlopen. This will run the ELF constructor. */
void *self = dlopen ("tst-dlopen-tlsreinitmod3.so", RTLD_NOW);
if (self == NULL)
{
printf ("error: dlopen: %s\n", dlerror ());
fflush (stdout);
/* Cannot rely on test harness due to dynamic linking. */
_exit (1);
}
call_tlsreinitmod3_tail (self);
}
void
call_tlsreinitmod3_tail (void *self)
{
printf ("info: dlopen returned in tlsreinitmod3 (state=%d)\n",
tlsreinitmod3_state);
if (!tlsreinitmod3_constructed)
{
puts ("error: dlopen did not call tlsreinitmod3 ELF constructor");
fflush (stdout);
/* Cannot rely on test harness due to dynamic linking. */
_exit (1);
}
if (tlsreinitmod3_state != 2)
{
puts ("error: TLS state reverted in tlsreinitmod3");
fflush (stdout);
/* Cannot rely on test harness due to dynamic linking. */
_exit (1);
}
dlclose (self);
/* Signal test completion to the main program. */
tlsreinitmod3_tested = true;
}
static void __attribute__ ((constructor))
tlsreinitmod3_init (void)
{
puts ("info: constructor of tst-dlopen-tlsreinitmod3.so invoked");
tlsreinitmod3_constructed = true;
}
+2 -16
View File
@@ -105,10 +105,7 @@ do_test (int argc, char **argv)
if (ret != 0)
exit (1);
/* Special return code to make sure that the child executed all the way
through. */
exit (42);
return 0;
}
else
{
@@ -127,18 +124,7 @@ do_test (int argc, char **argv)
continue;
}
int status = support_capture_subprogram_self_sgid (buf);
/* Bail out early if unsupported. */
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (WEXITSTATUS (status) != 42)
{
printf (" [%d] child failed with status %d\n", i,
WEXITSTATUS (status));
support_record_failure ();
}
support_capture_subprogram_self_sgid (buf);
}
return 0;
}
+2 -15
View File
@@ -148,10 +148,7 @@ do_test (int argc, char **argv)
if (ret != 0)
exit (1);
/* Special return code to make sure that the child executed all the way
through. */
exit (42);
return 0;
}
else
{
@@ -175,17 +172,7 @@ do_test (int argc, char **argv)
free (profilepath);
}
int status = support_capture_subprogram_self_sgid (SETGID_CHILD);
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
exit (EXIT_UNSUPPORTED);
if (WEXITSTATUS (status) != 42)
{
printf (" child failed with status %d\n",
WEXITSTATUS (status));
support_record_failure ();
}
support_capture_subprogram_self_sgid (SETGID_CHILD);
return 0;
}
+122
View File
@@ -0,0 +1,122 @@
/* Test TLSDESC relocation.
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <pthread.h>
#include <support/xdlfcn.h>
#include <support/xthread.h>
#include <support/check.h>
#include <support/test-driver.h>
#include "tst-gnu2-tls2.h"
#ifndef IS_SUPPORTED
# define IS_SUPPORTED() true
#endif
/* An architecture can define it to clobber caller-saved registers in
malloc below to verify that the implicit TLSDESC call won't change
caller-saved registers. */
#ifndef PREPARE_MALLOC
# define PREPARE_MALLOC()
#endif
extern void * __libc_malloc (size_t);
size_t malloc_counter = 0;
void *
malloc (size_t n)
{
PREPARE_MALLOC ();
malloc_counter++;
return __libc_malloc (n);
}
static void *mod[3];
#ifndef MOD
# define MOD(i) "tst-gnu2-tls2mod" #i ".so"
#endif
static const char *modname[3] = { MOD(0), MOD(1), MOD(2) };
#undef MOD
static void
open_mod (int i)
{
mod[i] = xdlopen (modname[i], RTLD_LAZY);
printf ("open %s\n", modname[i]);
}
static void
close_mod (int i)
{
xdlclose (mod[i]);
mod[i] = NULL;
printf ("close %s\n", modname[i]);
}
static void
access_mod (int i, const char *sym)
{
struct tls var = { -1, -1, -1, -1 };
struct tls *(*f) (struct tls *) = xdlsym (mod[i], sym);
/* Check that our malloc is called. */
malloc_counter = 0;
struct tls *p = f (&var);
TEST_VERIFY (malloc_counter != 0);
printf ("access %s: %s() = %p\n", modname[i], sym, p);
TEST_VERIFY_EXIT (memcmp (p, &var, sizeof (var)) == 0);
++(p->a);
}
static void *
start (void *arg)
{
/* The DTV generation is at the last dlopen of mod0 and the
entry for mod1 is NULL. */
open_mod (1); /* Reuse modid of mod1. Uses dynamic TLS. */
/* Force the slow path in GNU2 TLS descriptor call. */
access_mod (1, "apply_tls");
return arg;
}
static int
do_test (void)
{
if (!IS_SUPPORTED ())
return EXIT_UNSUPPORTED;
open_mod (0);
open_mod (1);
open_mod (2);
close_mod (0);
close_mod (1); /* Create modid gap at mod1. */
open_mod (0); /* Reuse modid of mod0, bump generation count. */
/* Create a thread where DTV of mod1 is NULL. */
pthread_t t = xpthread_create (NULL, start, NULL);
xpthread_join (t);
return 0;
}
#include <support/test-driver.c>
+40
View File
@@ -0,0 +1,40 @@
/* Test TLSDESC relocation.
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdint.h>
struct tls
{
int64_t a, b, c, d;
};
extern struct tls *apply_tls (struct tls *);
/* An architecture can define them to verify that clobber caller-saved
registers aren't changed by the implicit TLSDESC call. */
#ifndef INIT_TLSDESC_CALL
# define INIT_TLSDESC_CALL()
#endif
#ifndef BEFORE_TLSDESC_CALL
# define BEFORE_TLSDESC_CALL()
#endif
#ifndef AFTER_TLSDESC_CALL
# define AFTER_TLSDESC_CALL()
#endif
+32
View File
@@ -0,0 +1,32 @@
/* DSO used by tst-gnu2-tls2.
Copyright (C) 2024 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 <tst-gnu2-tls2.h>
__thread struct tls tls_var0 __attribute__ ((visibility ("hidden")));
struct tls *
apply_tls (struct tls *p)
{
INIT_TLSDESC_CALL ();
BEFORE_TLSDESC_CALL ();
tls_var0 = *p;
struct tls *ret = &tls_var0;
AFTER_TLSDESC_CALL ();
return ret;
}
+32
View File
@@ -0,0 +1,32 @@
/* DSO used by tst-gnu2-tls2.
Copyright (C) 2024 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 <tst-gnu2-tls2.h>
__thread struct tls tls_var1[100] __attribute__ ((visibility ("hidden")));
struct tls *
apply_tls (struct tls *p)
{
INIT_TLSDESC_CALL ();
BEFORE_TLSDESC_CALL ();
tls_var1[1] = *p;
struct tls *ret = &tls_var1[1];
AFTER_TLSDESC_CALL ();
return ret;
}
+32
View File
@@ -0,0 +1,32 @@
/* DSO used by tst-gnu2-tls2.
Copyright (C) 2024 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 <tst-gnu2-tls2.h>
__thread struct tls tls_var2 __attribute__ ((visibility ("hidden")));
struct tls *
apply_tls (struct tls *p)
{
INIT_TLSDESC_CALL ();
BEFORE_TLSDESC_CALL ();
tls_var2 = *p;
struct tls *ret = &tls_var2;
AFTER_TLSDESC_CALL ();
return ret;
}
+158
View File
@@ -0,0 +1,158 @@
/* Check that _dl_find_object behavior matches up with gaps.
Copyright (C) 2025 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 <dlfcn.h>
#include <gnu/lib-names.h>
#include <inttypes.h>
#include <link.h>
#include <stdbool.h>
#include <stdio.h>
#include <support/check.h>
#include <support/support.h>
#include <support/xdlfcn.h>
#include <support/xunistd.h>
#include <support/xstdio.h>
#include <sys/mman.h>
#include <unistd.h>
/* Slow path in case we cannot find a gap with mmap (when the runtime has
mapped all the pages in the gap for some reason). */
static bool
find_gap_with_proc_self_map (const struct link_map *l)
{
int pagesize = getpagesize ();
support_need_proc ("Reads /proc/self/maps to find gap in ld.so mapping");
/* Parse /proc/self/maps and find all the mappings in the ld.so range
but not from ld.so. */
FILE *f = xfopen ("/proc/self/maps", "r");
char *line = NULL, *path_ldso = NULL;
size_t len;
bool found = false;
while (xgetline (&line, &len, f))
{
uintptr_t from, to;
char *path = NULL;
int r = sscanf (line, "%" SCNxPTR "-%" SCNxPTR "%*s%*s%*s%*s%ms",
&from, &to, &path);
TEST_VERIFY (r == 2 || r == 3);
TEST_COMPARE (from % pagesize, 0);
TEST_COMPARE (to % pagesize, 0);
if (path_ldso == NULL && l->l_map_start == from)
{
TEST_COMPARE (r, 3);
path_ldso = path;
continue;
}
if (from > l->l_map_start && to < l->l_map_end
&& (r == 2 || (path_ldso != NULL && strcmp (path, path_ldso))))
{
if (r == 2)
printf ("info: anonymous mapping found at 0x%" PRIxPTR " - 0x%"
PRIxPTR "\n", from, to);
else
printf ("info: object \"%s\" found at 0x%" PRIxPTR " - 0x%"
PRIxPTR "\n", path, from, to);
found = true;
}
free (path);
}
free (path_ldso);
free (line);
xfclose (f);
return found;
}
static int
do_test (void)
{
struct link_map *l = xdlopen (LD_SO, RTLD_NOW);
if (!l->l_contiguous)
{
puts ("info: ld.so link map is not contiguous");
/* Try to find holes by probing with mmap. */
int pagesize = getpagesize ();
bool gap_found = false;
ElfW(Addr) addr = l->l_map_start;
TEST_COMPARE (addr % pagesize, 0);
while (addr < l->l_map_end)
{
void *expected = (void *) addr;
void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1);
struct dl_find_object dlfo;
int dlfo_ret = _dl_find_object (expected, &dlfo);
if (ptr == expected)
{
if (dlfo_ret < 0)
{
TEST_COMPARE (dlfo_ret, -1);
printf ("info: hole without mapping data found at %p\n", ptr);
}
else
FAIL ("object \"%s\" found in gap at %p",
dlfo.dlfo_link_map->l_name, ptr);
gap_found = true;
}
else if (dlfo_ret == 0)
{
if ((void *) dlfo.dlfo_link_map != (void *) l)
{
printf ("info: object \"%s\" found at %p\n",
dlfo.dlfo_link_map->l_name, expected);
gap_found = true;
}
}
else
TEST_COMPARE (dlfo_ret, -1);
xmunmap (ptr, 1);
addr += pagesize;
}
if (!gap_found && !find_gap_with_proc_self_map (l))
FAIL ("no ld.so gap found");
}
else
{
puts ("info: ld.so link map is contiguous");
/* Assert that ld.so is truly contiguous in memory. */
volatile long int *p = (volatile long int *) l->l_map_start;
volatile long int *end = (volatile long int *) l->l_map_end;
while (p < end)
{
*p;
++p;
}
}
xdlclose (l);
return 0;
}
#include <support/test-driver.c>
+57
View File
@@ -0,0 +1,57 @@
/* Check that the entire libc.so program image is readable if contiguous.
Copyright (C) 2025 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 <gnu/lib-names.h>
#include <link.h>
#include <support/check.h>
#include <support/xdlfcn.h>
#include <support/xunistd.h>
#include <sys/mman.h>
#include <unistd.h>
static int
do_test (void)
{
struct link_map *l = xdlopen (LIBC_SO, RTLD_NOW);
/* The dynamic loader fills holes with PROT_NONE mappings. */
if (!l->l_contiguous)
FAIL_EXIT1 ("libc.so link map is not contiguous");
/* Direct probing does not work because not everything is readable
due to PROT_NONE mappings. */
int pagesize = getpagesize ();
ElfW(Addr) addr = l->l_map_start;
TEST_COMPARE (addr % pagesize, 0);
while (addr < l->l_map_end)
{
void *expected = (void *) addr;
void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1);
if (ptr == expected)
FAIL ("hole in libc.so memory image after %lu bytes",
(unsigned long int) (addr - l->l_map_start));
xmunmap (ptr, 1);
addr += pagesize;
}
xdlclose (l);
return 0;
}
#include <support/test-driver.c>
+45
View File
@@ -0,0 +1,45 @@
/* Check that the entire main program image is readable if contiguous.
Copyright (C) 2025 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 <link.h>
#include <support/check.h>
#include <support/xdlfcn.h>
static int
do_test (void)
{
struct link_map *l = xdlopen ("", RTLD_NOW);
if (!l->l_contiguous)
FAIL_UNSUPPORTED ("main link map is not contiguous");
/* This check only works if the kernel loaded the main program. The
dynamic loader replaces gaps with PROT_NONE mappings, resulting
in faults. */
volatile long int *p = (volatile long int *) l->l_map_start;
volatile long int *end = (volatile long int *) l->l_map_end;
while (p < end)
{
*p;
++p;
}
xdlclose (l);
return 0;
}
#include <support/test-driver.c>
+60
View File
@@ -0,0 +1,60 @@
/* Test with interposed malloc with dynamic TLS.
Copyright (C) 2024 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 <array_length.h>
#include <stdio.h>
#include <support/check.h>
#include <support/xdlfcn.h>
/* Defined in tst-recursive-tlsmallocmod.so. */
extern __thread unsigned int malloc_subsytem_counter;
static int
do_test (void)
{
/* 16 is large enough to exercise the DTV resizing case. */
void *handles[16];
for (unsigned int i = 0; i < array_length (handles); ++i)
{
/* Re-use the TLS slot for module 0. */
if (i > 0)
xdlclose (handles[0]);
char soname[30];
snprintf (soname, sizeof (soname), "tst-recursive-tlsmod%u.so", i);
handles[i] = xdlopen (soname, RTLD_NOW);
if (i > 0)
{
handles[0] = xdlopen ("tst-recursive-tlsmod0.so", RTLD_NOW);
int (*fptr) (void) = xdlsym (handles[0], "get_threadvar_0");
/* May trigger TLS storage allocation using malloc. */
TEST_COMPARE (fptr (), 0);
}
}
for (unsigned int i = 0; i < array_length (handles); ++i)
xdlclose (handles[i]);
printf ("info: malloc subsystem calls: %u\n", malloc_subsytem_counter);
TEST_VERIFY (malloc_subsytem_counter > 0);
return 0;
}
#include <support/test-driver.c>
+64
View File
@@ -0,0 +1,64 @@
/* Interposed malloc with dynamic TLS.
Copyright (C) 2024 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 <stdlib.h>
#include <dlfcn.h>
__thread unsigned int malloc_subsytem_counter;
static __typeof (malloc) *malloc_fptr;
static __typeof (free) *free_fptr;
static __typeof (calloc) *calloc_fptr;
static __typeof (realloc) *realloc_fptr;
static void __attribute__ ((constructor))
init (void)
{
malloc_fptr = dlsym (RTLD_NEXT, "malloc");
free_fptr = dlsym (RTLD_NEXT, "free");
calloc_fptr = dlsym (RTLD_NEXT, "calloc");
realloc_fptr = dlsym (RTLD_NEXT, "realloc");
}
void *
malloc (size_t size)
{
++malloc_subsytem_counter;
return malloc_fptr (size);
}
void
free (void *ptr)
{
++malloc_subsytem_counter;
return free_fptr (ptr);
}
void *
calloc (size_t a, size_t b)
{
++malloc_subsytem_counter;
return calloc_fptr (a, b);
}
void *
realloc (void *ptr, size_t size)
{
++malloc_subsytem_counter;
return realloc_fptr (ptr, size);
}
+28
View File
@@ -0,0 +1,28 @@
/* Test module with global-dynamic TLS. Used to trigger DTV reallocation.
Copyright (C) 2024 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/>. */
/* Compiled with VAR and FUNC set via -D. FUNC requires some
relocation against TLS variable VAR. */
__thread int VAR;
int
FUNC (void)
{
return VAR;
}
+1
View File
@@ -0,0 +1 @@
#include "tst-rtld-no-malloc.c"
+1
View File
@@ -0,0 +1 @@
#include "tst-rtld-no-malloc.c"
+76
View File
@@ -0,0 +1,76 @@
/* Test that program loading does not call malloc.
Copyright (C) 2024 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 <string.h>
#include <unistd.h>
static void
print (const char *s)
{
const char *end = s + strlen (s);
while (s < end)
{
ssize_t ret = write (STDOUT_FILENO, s, end - s);
if (ret <= 0)
_exit (2);
s += ret;
}
}
static void __attribute__ ((noreturn))
unexpected_call (const char *function)
{
print ("error: unexpected call to ");
print (function);
print ("\n");
_exit (1);
}
/* These are the malloc functions implement in elf/dl-minimal.c. */
void
free (void *ignored)
{
unexpected_call ("free");
}
void *
calloc (size_t ignored1, size_t ignored2)
{
unexpected_call ("calloc");
}
void *
malloc (size_t ignored)
{
unexpected_call ("malloc");
}
void *
realloc (void *ignored1, size_t ignored2)
{
unexpected_call ("realloc");
}
int
main (void)
{
/* Do not use the test wrapper, to avoid spurious malloc calls from it. */
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/* DSO used by tst-tls23.
Copyright (C) 2025 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 <tst-tls23.h>
__thread struct tls tls_var0 __attribute__ ((visibility ("hidden")));
struct tls *
apply_tls (struct tls *p)
{
INIT_TLS_CALL ();
BEFORE_TLS_CALL ();
tls_var0 = *p;
struct tls *ret = &tls_var0;
AFTER_TLS_CALL ();
return ret;
}
+106
View File
@@ -0,0 +1,106 @@
/* Test that __tls_get_addr preserves caller-saved registers.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <pthread.h>
#include <support/xdlfcn.h>
#include <support/xthread.h>
#include <support/check.h>
#include <support/test-driver.h>
#include <tst-tls23.h>
#ifndef IS_SUPPORTED
# define IS_SUPPORTED() true
#endif
/* An architecture can define it to clobber caller-saved registers in
malloc below to verify that __tls_get_addr won't change caller-saved
registers. */
#ifndef PREPARE_MALLOC
# define PREPARE_MALLOC()
#endif
extern void * __libc_malloc (size_t);
size_t malloc_counter = 0;
void *
malloc (size_t n)
{
PREPARE_MALLOC ();
malloc_counter++;
return __libc_malloc (n);
}
static void *mod;
static const char *modname = "tst-tls23-mod.so";
static void
open_mod (void)
{
mod = xdlopen (modname, RTLD_LAZY);
printf ("open %s\n", modname);
}
static void
close_mod (void)
{
xdlclose (mod);
mod = NULL;
printf ("close %s\n", modname);
}
static void
access_mod (const char *sym)
{
struct tls var = { -4, -4, -4, -4 };
struct tls *(*f) (struct tls *) = xdlsym (mod, sym);
/* Check that our malloc is called. */
malloc_counter = 0;
struct tls *p = f (&var);
TEST_VERIFY (malloc_counter != 0);
printf ("access %s: %s() = %p\n", modname, sym, p);
TEST_VERIFY_EXIT (memcmp (p, &var, sizeof (var)) == 0);
++(p->a);
}
static void *
start (void *arg)
{
access_mod ("apply_tls");
return arg;
}
static int
do_test (void)
{
if (!IS_SUPPORTED ())
return EXIT_UNSUPPORTED;
open_mod ();
pthread_t t = xpthread_create (NULL, start, NULL);
xpthread_join (t);
close_mod ();
return 0;
}
#include <support/test-driver.c>
+40
View File
@@ -0,0 +1,40 @@
/* Test that __tls_get_addr preserves caller-saved registers.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdint.h>
struct tls
{
int64_t a, b, c, d;
};
extern struct tls *apply_tls (struct tls *);
/* An architecture can define them to verify that caller-saved registers
aren't changed by __tls_get_addr. */
#ifndef INIT_TLS_CALL
# define INIT_TLS_CALL()
#endif
#ifndef BEFORE_TLS_CALL
# define BEFORE_TLS_CALL()
#endif
#ifndef AFTER_TLS_CALL
# define AFTER_TLS_CALL()
#endif
+60 -1
View File
@@ -17,6 +17,10 @@
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
/* The test uses the tunable_list size, which is only exported for
ld.so. This will result in a copy of tunable_list, which is ununsed by
the test itself. */
#define TUNABLES_INTERNAL 1
#include <dl-tunables.h>
#include <getopt.h>
#include <intprops.h>
@@ -24,12 +28,13 @@
#include <stdlib.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/support.h>
static int restart;
#define CMDLINE_OPTIONS \
{ "restart", no_argument, &restart, 1 },
static const struct test_t
static struct test_t
{
const char *name;
const char *value;
@@ -284,6 +289,29 @@ static const struct test_t
0,
0,
},
/* Also check for repeated tunables with a count larger than the total number
of tunables. */
{
"GLIBC_TUNABLES",
NULL,
2,
0,
0,
},
{
"GLIBC_TUNABLES",
NULL,
1,
0,
0,
},
{
"GLIBC_TUNABLES",
NULL,
0,
0,
0,
},
};
static int
@@ -327,6 +355,37 @@ do_test (int argc, char *argv[])
spargv[i] = NULL;
}
/* Create a tunable line with the duplicate values with a total number
larger than the different number of tunables. */
{
enum { tunables_list_size = array_length (tunable_list) };
const char *value = "";
for (int i = 0; i < tunables_list_size; i++)
value = xasprintf ("%sglibc.malloc.check=2%c",
value,
i == (tunables_list_size - 1) ? '\0' : ':');
tests[33].value = value;
}
/* Same as before, but the last tunable values is differen than the
rest. */
{
enum { tunables_list_size = array_length (tunable_list) };
const char *value = "";
for (int i = 0; i < tunables_list_size - 1; i++)
value = xasprintf ("%sglibc.malloc.check=2:", value);
value = xasprintf ("%sglibc.malloc.check=1", value);
tests[34].value = value;
}
/* Same as before, but with an invalid last entry. */
{
enum { tunables_list_size = array_length (tunable_list) };
const char *value = "";
for (int i = 0; i < tunables_list_size - 1; i++)
value = xasprintf ("%sglibc.malloc.check=2:", value);
value = xasprintf ("%sglibc.malloc.check=1=1", value);
tests[35].value = value;
}
for (int i = 0; i < array_length (tests); i++)
{
snprintf (nteststr, sizeof nteststr, "%d", i);

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