Compare commits

...
Author SHA1 Message Date
Miao Wang 729aeec3e6 io: statx, fstatat: Drop nonnull attribute on the path argument
Since Linux 6.11 the kernel allows path to be NULL if flags &
AT_EMPTY_PATH.  Let's allow users to take the advantage if they don't
care running on old kernels.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 55618e1396)
2026-08-30 23:45:49 +01:00
Fabian Rast cb21f7144e 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:02:12 -07:00
Florian Weimer 2db5dd50b2 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:42:08 +02:00
DJ Delorie 9c4023b025 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:42:08 +02:00
Florian Weimer f82c16babf 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 22:30:21 +02:00
Xi Ruoyao 573a7e46ec 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 21:45:09 +02:00
Carlos O'Donell df2bb178a5 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 21:44:54 +02:00
Carlos O'Donell acf870165a 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 21:44:54 +02:00
Florian Weimer d951a94c7d 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:44:34 +01:00
Florian Weimer b5f5f1f3d2 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:44:34 +01:00
Yury Khrustalev 3978f88041 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:44:34 +01:00
Adhemerval Zanella 9fe8576664 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 13:04:25 -03:00
Carlos O'Donell 329c775788 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:44 -05:00
Siddhesh Poyarekar bfc4dd9e52 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 21:32:57 -05:00
Sunil K Pandey d861635092 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-30 13:56:59 -08:00
Florian Weimer 468ca594f8 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)
2025-12-23 20:10:58 +01:00
Florian Weimer 9e2f52c5e0 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)
2025-12-23 20:10:58 +01:00
Collin Funk 6a861d3946 sprof: fix -Wformat warnings on 32-bit hosts
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 9681f645ba)
2025-12-23 20:10:58 +01:00
DJ Delorie 0273c4d18e 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)
2025-12-23 20:10:58 +01:00
H.J. Lu 183f600c80 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)
2025-12-23 20:10:58 +01:00
Sachin Monga 165497e897 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 10:58:34 -05:00
Sachin Monga 4bfd05e2b8 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:40:03 -05:00
Sachin Monga a460dc7bd9 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-20 10:46:42 -05:00
Pierre Blanchard a07f8630bf AArch64: Fix and improve SVE pow(f) special cases
powf:

Update scalar special case function to best use new interface.

pow:

Make specialcase NOINLINE to prevent str/ldr leaking in fast path.
Remove depency in sv_call2, as new callback impl is not a
performance gain.
Replace with vectorised specialcase since structure of scalar
routine is fairly simple.

Throughput gain of about 5-10% on V1 for large values and 25% for subnormal `x`.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit bb6519de1e)
2025-11-18 16:21:55 +00:00
Joe Ramsay b06fc96c20 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:18:33 +00:00
Joe Ramsay 303363922c 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:18:23 +00:00
Yury Khrustalev a66680adf3 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev 1c0ad5ea63 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev df3bcda9ac 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev 899ebf3569 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev 7af8db46d2 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev 51bcc73d95 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)
2025-11-13 14:18:42 +00:00
Yury Khrustalev cdc1665bb1 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)
2025-11-13 14:18:42 +00:00
Florian Weimer e8b9a4bcc2 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 14:57:54 +01:00
Jiamei Xie c0ae045027 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:34 +00:00
Sunil K Pandey c4458286b3 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 12:42:49 -07:00
Sunil K Pandey 43ea89efc0 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 12:42:26 -07:00
Florian Weimer 60795200d4 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 09:36:13 +02:00
Pierre Blanchard 2966a6a3a0 AArch64: Fix SVE powf routine [BZ #33299]
Fix a bug in predicate logic introduced in last change.
A slight performance improvement from relying on all true
predicates during conversion from single to double.
This fixes BZ #33299.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit aac077645a)
2025-09-03 13:36:12 +00:00
Joseph Myers f03a78820e 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:32:37 +02:00
Joseph Myers e20181e510 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:32:37 +02:00
Florian Weimer f7c0193b61 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:56:33 +02:00
H.J. Lu d6f67d835c 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:09:56 -07:00
H.J. Lu d67776356d 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:08:25 -07:00
Florian Weimer 3e335fad35 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:04:04 -07:00
Florian Weimer 340df50b37 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:03:58 -07:00
H.J. Lu 836c9f0e0b 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 14:13:43 -07:00
mengqinggang c789121e02 LoongArch: Regenerate preconfigure. [bug 32521]
Add "mtls_descriptor=desc" to preconfigure.ac and regenerate preconfigure.
Fix failure: elf/tst-gnu2-tls2.

Reported-by: Joseph S. Myers <josmyers@redhat.com>
Reported-by: Andreas K. Huettel <dilfridge@gentoo.org>
(cherry picked from commit d4cdb601df)
2025-08-18 14:08:26 -07:00
Florian Weimer 3533310dd3 elf: Preserve _rtld_global layout for the release branch
Backporting commit 7d649d1c99
("elf: Introduce _dl_debug_change_state") removed the
_ns_debug member.  Keep it to preseve struct layout.
2025-08-18 14:13:49 +02:00
Florian Weimer 87a6ccf0b4 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:07:25 +02:00
Florian Weimer fbc5e95f83 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:07:25 +02:00
Florian Weimer 7d649d1c99 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:07:25 +02:00
Florian Weimer 1eba4921c7 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:07:25 +02:00
Florian Weimer 5177ccdbcb 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:07:25 +02:00
Florian Weimer cadc0a8450 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:07:25 +02:00
Florian Weimer 46adca40b8 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:07:25 +02:00
Florian Weimer bab46c3dbd 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:07:25 +02:00
Florian Weimer 196fce6950 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:07:25 +02:00
Florian Weimer c10543d15b 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:07:25 +02:00
Florian Weimer 341233a250 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:07:25 +02:00
Florian Weimer f86839fc15 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:07:25 +02:00
Florian Weimer 630be04e04 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:07:25 +02:00
Florian Weimer 7fd2dac6d6 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:07:25 +02:00
Florian Weimer 3b03a301e7 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:07:25 +02:00
Florian Weimer 812918bbde 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:07:25 +02:00
Florian Weimer 23f95986fc 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:07:25 +02:00
Florian Weimer d9bd6f3869 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:07:25 +02:00
Florian Weimer 91473c4eea 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:07:25 +02:00
Florian Weimer aeb63faf58 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:07:25 +02:00
Florian Weimer e08360c484 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:07:25 +02:00
H.J. Lu 62e2c1d21f 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:31 +01:00
H.J. Lu 6916013ce9 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:18:16 +01:00
Joe Ramsay 666939940b 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:28:28 +00:00
Jens Remus 1b305e7e53 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:37:30 +02:00
Florian Weimer 434e7e144a 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:37:26 +02:00
Florian Weimer a0cc6a7e1c 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:44:46 +02:00
Florian Weimer ff17e7180a 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:44:41 +02:00
Florian Weimer 2193f42655 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:23:12 +02:00
Florian Weimer 0e1fea8879 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:23:12 +02:00
Florian Weimer e8ac8a9844 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:23:12 +02:00
Luna Lamb 3e5dfac7cc AArch64: Improve codegen SVE log1p helper
Improve codegen by packing coefficients.
4% and 2% improvement in throughput microbenchmark on Neoverse V1, for acosh
and atanh respectively.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 6849c5b791)
2025-08-11 15:34:31 +00:00
Dylan Fleming a79fbf10e7 AArch64: Optimise SVE FP64 Hyperbolics
Reworke SVE FP64 hyperbolics to use the SVE FEXPA
instruction.

Also update the special case handelling for large
inputs to be entirely vectorised.

Performance improvements on Neoverse V1:

cosh_sve: 19% for |x| < 709, 5x otherwise
sinh_sve: 24% for |x| < 709, 5.9x otherwise
tanh_sve: 12% for |x| < 19,  9x otherwise

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit dee22d2a81)
2025-08-11 15:34:26 +00:00
Dylan Fleming 01ab94cf78 AArch64: Optimize SVE exp functions
Improve performance of SVE exps by making better use
of the SVE FEXPA instruction.

Performance improvement on Neoverse V1:
exp2_sve:   21%
exp2f_sve:  24%
exp10f_sve: 23%
expm1_sve:  25%

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 1e3d1ddf97)
2025-08-11 15:34:14 +00:00
Luna Lamb 0348dd8b98 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:34:07 +00:00
Dylan Fleming bfd0490911 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:33:55 +00:00
Pierre Blanchard 2f0c3a5287 AArch64: Optimize algorithm in users of SVE expf helper
Polynomial order was unnecessarily high, unlocking multiple
optimizations.
Max error for new SVE expf is 0.88 +0.5ULP.
Max error for new SVE coshf is 2.56 +0.5ULP.
Performance improvement on Neoverse V1: expf (30%), coshf (26%).

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit cf56eb28fa)
2025-08-11 15:33:49 +00:00
Wilco Dijkstra 95c9b7351c 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:01:58 +00:00
Florian Weimer 2eb180377b 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:19:27 +02:00
Florian Weimer dbc83657e2 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:11 +02:00
Florian Weimer 23a02e382c 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:39:46 +02:00
Carlos O'Donell 7e12550b8e 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-16 18:35:27 -04:00
Carlos O'Donell 672f31b90e 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-16 18:32:45 -04:00
Carlos O'Donell 2ad6e55ea5 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-16 18:28:33 -04:00
Carlos O'Donell 42a5a940c9 ppc64le: Revert "powerpc: Optimized strncmp for power10" (CVE-2025-5745)
This reverts commit 23f0d81608

Reason for revert: Power10 strncmp clobbers non-volatile vector
registers (Bug 33060)

Tested on ppc64le with no regressions.

(cherry picked from commit 63c60101ce)
2025-06-16 18:28:21 -04:00
Florian Weimer c8e10f1432 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:50:41 +02:00
Sunil K Pandey 56e75b810a 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:48:57 -07:00
Florian Weimer 079ac4a172 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:50:45 +02:00
Florian Weimer 61dcce21e0 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:50:45 +02:00
Florian Weimer b3002f303c 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:46:03 +02:00
Florian Weimer 8667345b83 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:59:05 +02:00
Arjun Shankar 7c3c9ae286 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-04-30 12:58:03 +02:00
Arjun Shankar 33b33e9dd0 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-04-30 12:57:55 +02:00
Florian Weimer 8d3dd23e3d 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>
2025-04-29 10:03:26 -04:00
Malte Skarupke 7f71824b80 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-28 12:52:17 -04:00
Malte Skarupke 2ad6949734 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-28 12:52:11 -04:00
Malte Skarupke afbf0d4685 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-28 12:52:06 -04:00
Malte Skarupke fa110993a6 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-28 12:51:57 -04:00
Malte Skarupke a2465f4293 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-28 12:51:51 -04:00
Malte Skarupke 2a259b6d77 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-28 12:51:44 -04:00
Malte Skarupke 136a29f9d0 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-28 12:51:36 -04:00
Malte Skarupke 88d999d840 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-28 12:51:29 -04:00
Frank Barrus 736e673505 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-28 12:51:21 -04:00
H.J. Lu d8a1a1aef7 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-12 12:27:19 -07:00
Sunil K Pandey 9ee8083c4e 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-12 12:24:53 -07:00
Sunil K Pandey 44f92df800 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-12 12:22:25 -07:00
Sunil K Pandey 7c6bd71b4d 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-12 12:22:17 -07:00
Noah Goldstein 8fe27af20c 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-12 12:21:32 -07:00
Florian Weimer a87d9a2c2c 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:27 +02:00
Florian Weimer df22af58f6 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:51 +01:00
Florian Weimer 8fc492bb42 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:51 +01:00
Sunil K Pandey e5f5dfdda2 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-18 10:03:01 -07:00
Sunil K Pandey e854f6d37c 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-18 09:59:36 -07:00
Sunil K Pandey ee1ab93023 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-18 09:59:29 -07:00
Michael Jeanson 3e820e17a8 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:31:34 +00:00
Wilco Dijkstra d8e8342369 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:23:10 +00:00
Wilco Dijkstra d6175a44e9 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:23:10 +00:00
Wilco Dijkstra 7038970f1f 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:23:10 +00:00
Wilco Dijkstra 27fa0268ea 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:23:10 +00:00
Wilco Dijkstra 41eb2f8b58 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:23:10 +00:00
Wilco Dijkstra 544fb349d3 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:22:28 +00:00
Wilco Dijkstra 64896b7d32 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:22:28 +00:00
Wilco Dijkstra fd9a3a36fd Revert "AArch64: Add vector logp1 alias for log1p"
This reverts commit a991a0fc7c.
2025-02-27 20:34:34 +00:00
Yat Long Poon 06fd8ad78f AArch64: Improve codegen for SVE powf
Improve memory access with indexed/unpredicated instructions.
Eliminate register spills.  Speedup on Neoverse V1: 3%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 95e807209b)
2025-02-27 17:08:58 +00:00
Yat Long Poon 7dc549c5a4 AArch64: Improve codegen for SVE pow
Move constants to struct.  Improve memory access with indexed/unpredicated
instructions.  Eliminate register spills.  Speedup on Neoverse V1: 24%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 0b195651db)
2025-02-27 17:08:49 +00:00
Yat Long Poon 194185c289 AArch64: Improve codegen for SVE erfcf
Reduce number of MOV/MOVPRFXs and use unpredicated FMUL.
Replace MUL with LSL.  Speedup on Neoverse V1: 6%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit f5ff34cb3c)
2025-02-27 17:08:42 +00:00
Luna Lamb 4b0bb84eb7 Aarch64: Improve codegen in SVE exp and users, and update expf_inline
Use unpredicted muls, and improve memory access.
7%, 3% and 1% improvement in throughput microbenchmark on Neoverse V1,
for exp, exp2 and cosh respectively.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit c0ff447edf)
2025-02-27 17:08:35 +00:00
Luna Lamb 0ff6a9ff79 Aarch64: Improve codegen in SVE asinh
Use unpredicated muls, use lanewise mla's and improve memory access.
1% regression in throughput microbenchmark on Neoverse V1.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 8f0e7fe61e)
2025-02-27 17:08:28 +00:00
Luna Lamb d983f14c30 AArch64: Improve codegen in SVE expm1f and users
Use unpredicated muls, use absolute compare and improve memory access.
Expm1f, sinhf and tanhf show 7%, 5% and 1% improvement in throughput
microbenchmark on Neoverse V1.

(cherry picked from commit f86b4cf875)
2025-02-27 17:08:16 +00:00
Yat Long Poon aa7c61ea15 AArch64: Improve codegen for SVE log1pf users
Reduce memory access by using lanewise MLA and reduce number of MOVPRFXs.
Move log1pf implementation to inline helper function.
Speedup on Neoverse V1 for log1pf (10%), acoshf (-1%), atanhf (2%), asinhf (2%).

(cherry picked from commit 91c1fadba3)
2025-02-27 17:08:06 +00:00
Yat Long Poon ab5ba6c188 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:07:55 +00:00
Luna Lamb 5f45c0f91e 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:07:37 +00:00
Luna Lamb abfd20ebbd AArch64: Improve codegen in AdvSIMD asinh
Improves memory access and removes spills.
Load the polynomial evaluation coefficients into 2 vectors and use lanewise
MLAs.  Reduces MOVs 6->3 , LDR 11->5, STR/STP 2->0, ADRP 3->2.

(cherry picked from commit 140b985e5a)
2025-02-27 17:07:30 +00:00
Joana Cruz bf2b60a560 AArch64: Improve codegen of AdvSIMD expf family
Load the polynomial evaluation coefficients into 2 vectors and use lanewise MLAs.
Also use intrinsics instead of native operations.
expf: 3% improvement in throughput microbenchmark on Neoverse V1, exp2f: 5%,
exp10f: 13%, coshf: 14%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit cff9648d0b)
2025-02-27 17:07:22 +00:00
Joana Cruz 41dc9e7c2d 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:07:15 +00:00
Joana Cruz 9170b921fa 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:07:08 +00:00
Pierre Blanchard 2aed9796bf AArch64: Improve codegen in users of ADVSIMD log1p helper
Add inline helper for log1p and rearrange operations so MOV
is not necessary in reduction or around the special-case handler.
Reduce memory access by using more indexed MLAs in polynomial.
Speedup on Neoverse V1 for log1p (3.5%), acosh (7.5%) and atanh (10%).

(cherry picked from commit ca0c0d0f26)
2025-02-27 17:07:01 +00:00
Pierre Blanchard ae04f63087 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:06:54 +00:00
Pierre Blanchard 4148940836 AArch64: Improve codegen in AdvSIMD pow
Remove spurious ADRP. Improve memory access by shuffling constants and
using more indexed MLAs.

A few more optimisation with no impact on accuracy
- force fmas contraction
- switch from shift-aided rint to rint instruction

Between 1 and 5% throughput improvement on Neoverse
V1 depending on benchmark.

(cherry picked from commit 569cfaaf49)
2025-02-27 17:06:45 +00:00
Joe Ramsay 76c923fe9d AArch64: Remove SVE erf and erfc tables
By using a combination of mask-and-add instead of the shift-based
index calculation the routines can share the same table as other
variants with no performance degradation.

The tables change name because of other changes in downstream AOR.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 2d82d781a5)
2025-02-27 17:06:35 +00:00
Joe Ramsay 9ff7559b27 AArch64: Small optimisation in AdvSIMD erf and erfc
In both routines, reduce register pressure such that GCC 14 emits no
spills for erf and fewer spills for erfc.  Also use more efficient
comparison for the special-case in erf.

Benchtests show erf improves by 6.4%, erfc by 1.0%.

(cherry picked from commit 1cf29fbc5b)
2025-02-27 17:06:25 +00:00
Joe Ramsay 68f2eb20de 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:06:18 +00:00
Joe Ramsay a947a43b95 AArch64: Improve codegen in users of ADVSIMD expm1f helper
Rearrange operations so MOV is not necessary in reduction or around
the special-case handler.  Reduce memory access by using more indexed
MLAs in polynomial.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 7900ac490d)
2025-02-27 17:06:09 +00:00
Joe Ramsay 5202401730 AArch64: Improve codegen in users of AdvSIMD log1pf helper
log1pf is quite register-intensive - use fewer registers for the
polynomial, and make various changes to shorten dependency chains in
parent routines.  There is now no spilling with GCC 14.  Accuracy moves
around a little - comments adjusted accordingly but does not require
regen-ulps.

Use the helper in log1pf as well, instead of having separate
implementations.  The more accurate polynomial means special-casing can
be simplified, and the shorter dependency chain avoids the usual dance
around v0, which is otherwise difficult.

There is a small duplication of vectors containing 1.0f (or 0x3f800000) -
GCC is not currently able to efficiently handle values which fit in FMOV
but not MOVI, and are reinterpreted to integer.  There may be potential
for more optimisation if this is fixed.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 5bc100bd4b)
2025-02-27 17:06:01 +00:00
Joe Ramsay c4373426e3 AArch64: Improve codegen in SVE F32 logs
Reduce MOVPRFXs by using unpredicated (non-destructive) instructions
where possible.  Similar to the recent change to AdvSIMD F32 logs,
adjust special-case arguments and bounds to allow for more optimal
register usage.  For all 3 routines one MOVPRFX remains in the
reduction, which cannot be avoided as immediate AND and ASR are both
destructive.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit a15b1394b5)
2025-02-27 17:05:53 +00:00
Joe Ramsay 354aeaf213 AArch64: Improve codegen in SVE expf & related routines
Reduce MOV and MOVPRFX by improving special-case handling.  Use inline
helper to duplicate the entire computation between the special- and
non-special case branches, removing the contention for z0 between x
and the return value.

Also rearrange some MLAs and MLSs - by making the multiplicand the
destination we can avoid a MOVPRFX in several cases.  Also change which
constants go in the vector used for lanewise ops - the last lane is no
longer wasted.

Spotted that shift was incorrect in exp2f and exp10f, w.r.t. to the
comment that explains it.  Fixed - worst-case ULP for exp2f moves
around but it doesn't change significantly for either routine.

Worst-case error for coshf increases due to passing x to exp rather
than abs(x) - updated the comment, but does not require regen-ulps.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 7b8c134b54)
2025-02-27 17:05:45 +00:00
Joe Ramsay a991a0fc7c AArch64: Add vector logp1 alias for log1p
This enables vectorisation of C23 logp1, which is an alias for log1p.
There are no new tests or ulp entries because the new symbols are simply
aliases.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 751a5502be)
2025-02-27 17:05:38 +00:00
Joe Ramsay ff10623706 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:05:29 +00:00
John David Anglin 523f855581 math: Add optimization barrier to ensure a1 + u.d is not reused [BZ #30664]
A number of fma tests started to fail on hppa when gcc was changed to
use Ranger rather than EVRP.  Eventually I found that the value of
a1 + u.d in this is block of code was being computed in FE_TOWARDZERO
mode and not the original rounding mode:

    if (TININESS_AFTER_ROUNDING)
      {
        w.d = a1 + u.d;
        if (w.ieee.exponent == 109)
          return w.d * 0x1p-108;
      }

This caused the exponent value to be wrong and the wrong return path
to be used.

Here we add an optimization barrier after the rounding mode is reset
to ensure that the previous value of a1 + u.d is not reused.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2025-02-25 16:00:49 -05:00
Siddhesh Poyarekar d6c156c326 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:46:50 -05:00
John David Anglin e899ca3651 nptl: Correct stack size attribute when stack grows up [BZ #32574]
Set stack size attribute to the size of the mmap'd region only
when the size of the remaining stack space is less than the size
of the mmap'd region.

This was reversed.  As a result, the initial stack size was only
135168 bytes.  On architectures where the stack grows down, the
initial stack size is approximately 8384512 bytes with the default
rlimit settings.  The small main stack size on hppa broke
applications like ruby that check for stack overflows.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2025-02-02 17:47:15 -05:00
H.J. Lu 8566822197 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:01:50 +08:00
Sam James be48b8f6ad 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:08:12 +00:00
H.J. Lu aef8f8d6a9 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:07:59 +00:00
Siddhesh Poyarekar 7d4b6bcae9 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 08:31:28 -05:00
Andreas Schwab 473597d816 Fix missing randomness in __gen_tempname (bug 32214)
Make sure to update the random value also if getrandom fails.

Fixes: 686d542025 ("posix: Sync tempname with gnulib")
(cherry picked from commit 5f62cf88c4)
2025-01-20 08:06:47 +01:00
John David Anglin 7648e3c8e8 hppa: Simplify handling of sanity check errors in clone.S.
This simplifies the handling of sanity check errors in clone.S.
Adjusted a couple of comments to reflect current code.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2024-12-22 10:00:26 -05:00
John David Anglin 9fbfbd924f hppa: Fix strace detach-vfork test
This change implements vfork.S for direct support of the vfork
syscall.  clone.S is revised to correct child support for the
vfork case.

The main bug was creating a frame prior to the clone syscall.
This was done to allow the rp and r4 registers to be saved and
restored from the stack frame.  r4 was used to save and restore
the PIC register, r19, across the system call and the call to
set errno.  But in the vfork case, it is undefined behavior
for the child to return from the function in which vfork was
called.  It is surprising that this usually worked.

Syscalls on hppa save and restore rp and r19, so we don't need
to create a frame prior to the clone syscall.  We only need a
frame when __syscall_error is called.  We also don't need to
save and restore r19 around the call to $$dyncall as r19 is not
used in the code after $$dyncall.

This considerably simplifies clone.S.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2024-12-19 11:32:13 -05:00
Florian Weimer 94e4a8c7d6 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:51:34 +01:00
Adhemerval Zanella 0b39fe8012 linux: Fix tst-syscall-restart.c on old gcc (BZ 32283)
To avoid a parameter name omitted error.

(cherry picked from commit ab564362d0)
2024-12-12 11:04:10 -08:00
H.J. Lu 9af64ca64c 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-12 09:55:02 -08:00
Adhemerval Zanella 11d9f49ceb sparc: Fix restartable syscalls (BZ 32173)
The commit 'sparc: Use Linux kABI for syscall return'
(86c5d2cf0c) did not take into account
a subtle sparc syscall kABI constraint.  For syscalls that might block
indefinitely, on an interrupt (like SIGCONT) the kernel will set the
instruction pointer to just before the syscall:

arch/sparc/kernel/signal_64.c
476 static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
477 {
[...]
525                 if (restart_syscall) {
526                         switch (regs->u_regs[UREG_I0]) {
527                         case ERESTARTNOHAND:
528                         case ERESTARTSYS:
529                         case ERESTARTNOINTR:
530                                 /* replay the system call when we are done */
531                                 regs->u_regs[UREG_I0] = orig_i0;
532                                 regs->tpc -= 4;
533                                 regs->tnpc -= 4;
534                                 pt_regs_clear_syscall(regs);
535                                 fallthrough;
536                         case ERESTART_RESTARTBLOCK:
537                                 regs->u_regs[UREG_G1] = __NR_restart_syscall;
538                                 regs->tpc -= 4;
539                                 regs->tnpc -= 4;
540                                 pt_regs_clear_syscall(regs);
541                         }

However, on a SIGCONT it seems that 'g1' register is being clobbered after the
syscall returns.  Before 86c5d2cf0c, the 'g1' was always placed jus
before the 'ta' instruction which then reloads the syscall number and restarts
the syscall.

On master, where 'g1' might be placed before 'ta':

  $ cat test.c
  #include <unistd.h>

  int main ()
  {
    pause ();
  }
  $ gcc test.c -o test
  $ strace -f ./t
  [...]
  ppoll(NULL, 0, NULL, NULL, 0

On another terminal

  $ kill -STOP 2262828

  $ strace -f ./t
  [...]
  --- SIGSTOP {si_signo=SIGSTOP, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  --- stopped by SIGSTOP ---

And then

  $ kill -CONT 2262828

Results in:

  --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  restart_syscall(<... resuming interrupted ppoll ...>) = -1 EINTR (Interrupted system call)

Where the expected behaviour would be:

  $ strace -f ./t
  [...]
  ppoll(NULL, 0, NULL, NULL, 0)           = ? ERESTARTNOHAND (To be restarted if no handler)
  --- SIGSTOP {si_signo=SIGSTOP, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  --- stopped by SIGSTOP ---
  --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  ppoll(NULL, 0, NULL, NULL, 0

Just moving the 'g1' setting near the syscall asm is not suffice,
the compiler might optimize it away (as I saw on cancellation.c by
trying this fix).  Instead, I have change the inline asm to put the
'g1' setup in ithe asm block.  This would require to change the asm
constraint for INTERNAL_SYSCALL_NCS, since the syscall number is not
constant.

Checked on sparc64-linux-gnu.

Reported-by: René Rebe <rene@exactcode.de>
Tested-by: Sam James <sam@gentoo.org>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 2c1903cbba)
(cherry picked from commit 1cd7e13289b91e1495a1865c1f678196d1bb7be4)
2024-12-12 04:14:47 +00:00
Adhemerval Zanella 846e64257e support: Make support_process_state_wait return the found state
So caller can check which state was found if multiple ones are
asked.

Checked on x86_64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 38316352e0)
(cherry picked from commit 2e38c5a090b3a54040b6e508d42e5a76e492c6e8)
2024-12-12 04:14:45 +00:00
Sam James c6cdab1e01 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:04 +00:00
Michael Jeanson 091dd12831 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-04 21:48:04 +00:00
Michael Jeanson 9b9545ba27 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-04 21:46:58 +00:00
Aurelien Jarno 626c048f32 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)
2024-11-15 21:40:35 +01:00
Adhemerval Zanella efb710034e linux: sparc: Fix clone for LEON/sparcv8 (BZ 31394)
The sparc clone mitigation (faeaa3bc9f) added the use of
flushw, which is not support by LEON/sparcv8.  As discussed on
the libc-alpha, 'ta 3' is a working alternative [1].

[1] https://sourceware.org/pipermail/libc-alpha/2024-August/158905.html

Checked with a build for sparcv8-linux-gnu targetting leon.

Acked-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
(cherry picked from commit 5e8cfc5d62)
2024-11-07 20:56:35 +01:00
Michael Karcher 2344580243 Mitigation for "clone on sparc might fail with -EFAULT for no valid reason" (bz 31394)
It seems the kernel can not deal with uncommitted stack space in the area intended
for the register window when executing the clone() system call. So create a nested
frame (proxy for the kernel frame) and flush it from the processor to memory to
force committing pages to the stack before invoking the system call.

Bug: https://www.mail-archive.com/debian-glibc@lists.debian.org/msg62592.html
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31394
See-also: https://lore.kernel.org/sparclinux/62f9be9d-a086-4134-9a9f-5df8822708af@mkarcher.dialup.fu-berlin.de/
Signed-off-by: Michael Karcher <sourceware-bugzilla@mkarcher.dialup.fu-berlin.de>
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit faeaa3bc9f)
2024-11-08 15:55:04 +01:00
Florian Weimer 3a34851103 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:21 +01:00
Joseph Myers 85e5850f2f 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:00 +02:00
H.J. Lu 5c06c6e0b5 libio: Set _vtable_offset before calling _IO_link_in [BZ #32148]
Since _IO_vtable_offset is used to detect the old binaries, set it
in _IO_old_file_init_internal before calling _IO_link_in which checks
_IO_vtable_offset.  Add a glibc 2.0 test with copy relocation on
_IO_stderr_@GLIBC_2.0 to verify that fopen won't cause memory corruption.
This fixes BZ #32148.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 9dfea3de7f)
2024-10-01 11:18:53 +08:00
Joseph Myers cc256952ec 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:11 +02:00
Joseph Myers 8f40dfbe2a 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:02 +02:00
Joseph Myers 4a9b6cdc88 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:24:57 +02:00
Florian Weimer 5a10d05c39 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:24:50 +02:00
Joseph Myers c4cc72d2ef 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:24:43 +02:00
Joseph Myers ad93c2047d 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:24:33 +02:00
Joseph Myers cac10d88c6 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:24:26 +02:00
Joseph Myers d0c1792ad2 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:24:21 +02:00
Joseph Myers e06153665f 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:24:13 +02:00
Joseph Myers 9bc76c7ca4 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:24:03 +02:00
Joseph Myers 61b6464f8d 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:15:33 +02:00
Sergey Kolosov 77018fd9f9 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:23 +02:00
Siddhesh Poyarekar 7073164add 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:47:22 +02:00
Florian Weimer adfb14e71f 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:04 +02:00
Florian Weimer f4a9b6e97b 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:30:30 +02:00
Florian Weimer f496b750f1 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:30:28 +02:00
Florian Weimer b7edcfa0f4 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:14:09 +02:00
Maciej W. Rozycki 3414b17e9d 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:26:48 -04:00
Maciej W. Rozycki 3b3350d7ba 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:26:11 -04:00
Siddhesh Poyarekar e24902f409 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:23:08 -04:00
Siddhesh Poyarekar dac7a0694b 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:23:08 -04:00
Siddhesh Poyarekar 2f749d2b15 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:23:08 -04:00
Maciej W. Rozycki 27fb563bfe 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:23:08 -04:00
Maciej W. Rozycki bc240ba7c8 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:23:08 -04:00
Florian Weimer 709319f9de 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:12:08 +02:00
Florian Weimer 586e4cd8c6 Define __libc_initial for the static libc
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit eb0e50e9a1)
2024-08-19 16:12:08 +02:00
Noah Goldstein c0af0c2ba0 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 10:00:11 -07:00
H.J. Lu 898f25e0b1 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 09:04:09 -07:00
H.J. Lu e3556937c2 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 09:04:00 -07:00
Florian Weimer 39ee60a719 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:01:57 +02:00
Arjun Shankar 5641780762 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:44:52 +02:00
Andreas Schwab 6a97e2ba14 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)
2024-08-06 08:18:31 +02:00
Florian Weimer aa533d58ff 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)
2024-08-02 18:12:58 +02:00
Florian Weimer 928769737c 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:15 +02:00
H.J. Lu ca53bc68ab 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:39:08 +02:00
H.J. Lu 2eb2d78ca7 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:39:08 +02:00
H.J. Lu 3433a35842 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:39:08 +02:00
Florian Weimer 46f19b2342 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:20:12 +02:00
Florian Weimer 509166c9a5 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:20:12 +02:00
Lukas Bulwahn 132a72f93c 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 16:04:22 +02:00
Arjun Shankar 65fbcfe589 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:00:50 +02:00
Miguel Martín 5d2a931a81 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 14:59:08 +02:00
Miguel Martín 2aebac5e15 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 14:59:08 +02:00
Florian Weimer 145b588637 Fix version number in NEWS file 2024-07-24 13:42:16 +02:00
Florian Weimer b6aeba2de1 manual: Do not mention STATIC_TLS in dynamic linker hardening recommendations
The current toolchain does not consistently generate it, and
glibc does not use it.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 90842d3980)
2024-07-24 12:50:43 +02:00
Florian Weimer ef14142663 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 12:49:07 +02:00
Florian Weimer 8bbb8d7b16 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 12:48:39 +02:00
Andreas K. Hüttel 6daa771045 Replace advisories directory
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2024-07-21 19:02:10 +02:00
452 changed files with 19657 additions and 15061 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
+29
View File
@@ -5,6 +5,35 @@ 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.40.1
The following bugs are resolved with this release:
[19341] ctype: Fallback initialization of TLS using relocations
[27821] ungetc: Fix backup buffer leak on program exit
[30081] resolv: Do not wait for non-existing second DNS response after error
[31394] clone on sparc might fail with -EFAULT for no valid reason
[31717] elf: Avoid re-initializing already allocated TLS in dlopen
[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
[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
[32214] Fix missing randomness in __gen_tempname
[32231] elf: Change ldconfig auxcache magic number
[32245] glibc -Wstringop-overflow= build failure on hppa
[32470] x86: Avoid integer truncation with large cache sizes
[32483] ctype macros segfault in multithreaded programs with multiple libc.so
[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
[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.40
Major new features:
-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)
-28
View File
@@ -1,28 +0,0 @@
ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence
The iconv() function in the GNU C Library versions 2.39 and older may
overflow the output buffer passed to it by up to 4 bytes when converting
strings to the ISO-2022-CN-EXT character set, which may be used to
crash an application or overwrite a neighbouring variable.
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'.
CVE-Id: CVE-2024-2961
Public-Date: 2024-04-17
Vulnerable-Commit: 755104edc75c53f4a0e7440334e944ad3c6b32fc (2.1.93-169)
Fix-Commit: f9dc609e06b1136bb0408be9605ce7973a767ada (2.40)
Fix-Commit: 31da30f23cddd36db29d5b6a1c7619361b271fb4 (2.39-31)
Fix-Commit: e1135387deded5d73924f6ca20c72a35dc8e1bda (2.38-66)
Fix-Commit: 89ce64b269a897a7780e4c73a7412016381c6ecf (2.37-89)
Fix-Commit: 4ed98540a7fd19f458287e783ae59c41e64df7b5 (2.36-164)
Fix-Commit: 36280d1ce5e245aabefb877fe4d3c6cff95dabfa (2.35-315)
Fix-Commit: a8b0561db4b9847ebfbfec20075697d5492a363c (2.34-459)
Fix-Commit: ed4f16ff6bed3037266f1fa682ebd32a18fce29c (2.33-263)
Fix-Commit: 682ad4c8623e611a971839990ceef00346289cc9 (2.32-140)
Fix-Commit: 3703c32a8d304c1ee12126134ce69be965f38000 (2.31-154)
Reported-By: Charles Fol
-22
View File
@@ -1,22 +0,0 @@
nscd: Stack-based buffer overflow in netgroup cache
If the Name Service Cache Daemon's (nscd) fixed size cache is exhausted
by client requests then a subsequent client request for netgroup data
may result in a stack-based buffer overflow. This flaw was introduced
in glibc 2.15 when the cache was added to nscd.
This vulnerability is only present in the nscd binary.
CVE-Id: CVE-2024-33599
Public-Date: 2024-04-23
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
Fix-Commit: 69c58d5ef9f584ea198bd00f7964d364d0e6b921 (2.31-155)
Fix-Commit: a77064893bfe8a701770e2f53a4d33805bc47a5a (2.32-141)
Fix-Commit: 5c75001a96abcd50cbdb74df24c3f013188d076e (2.33-264)
Fix-Commit: 52f73e5c4e29b14e79167272297977f360ae1e97 (2.34-460)
Fix-Commit: 7a95873543ce225376faf13bb71c43dea6d24f86 (2.35-316)
Fix-Commit: caa3151ca460bdd9330adeedd68c3112d97bffe4 (2.36-165)
Fix-Commit: f75c298e747b2b8b41b1c2f551c011a52c41bfd1 (2.37-91)
Fix-Commit: 5968aebb86164034b8f8421b4abab2f837a5bdaf (2.38-72)
Fix-Commit: 1263d583d2e28afb8be53f8d6922f0842036f35d (2.39-35)
Fix-Commit: 87801a8fd06db1d654eea3e4f7626ff476a9bdaa (2.40)
-32
View File
@@ -1,32 +0,0 @@
nscd: Null pointer crash after notfound response
If the Name Service Cache Daemon's (nscd) cache fails to add a not-found
netgroup response to the cache, the client request can result in a null
pointer dereference. This flaw was introduced in glibc 2.15 when the
cache was added to nscd.
This vulnerability is only present in the nscd binary.
CVE-Id: CVE-2024-33600
Public-Date: 2024-04-24
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
Fix-Commit: b048a482f088e53144d26a61c390bed0210f49f2 (2.40)
Fix-Commit: 7835b00dbce53c3c87bbbb1754a95fb5e58187aa (2.40)
Fix-Commit: c99f886de54446cd4447db6b44be93dabbdc2f8b (2.39-37)
Fix-Commit: 5a508e0b508c8ad53bd0d2fb48fd71b242626341 (2.39-36)
Fix-Commit: 2ae9446c1b7a3064743b4a51c0bbae668ee43e4c (2.38-74)
Fix-Commit: 541ea5172aa658c4bd5c6c6d6fd13903c3d5bb0a (2.38-73)
Fix-Commit: a8070b31043c7585c36ba68a74298c4f7af075c3 (2.37-93)
Fix-Commit: 5eea50c4402e39588de98aa1d4469a79774703d4 (2.37-92)
Fix-Commit: f205b3af56740e3b014915b1bd3b162afe3407ef (2.36-167)
Fix-Commit: c34f470a615b136170abd16142da5dd0c024f7d1 (2.36-166)
Fix-Commit: bafadc589fbe21ae330e8c2af74db9da44a17660 (2.35-318)
Fix-Commit: 4370bef52b0f3f3652c6aa13d7a9bb3ac079746d (2.35-317)
Fix-Commit: 1f94122289a9bf7dba573f5d60327aaa2b85cf2e (2.34-462)
Fix-Commit: 966d6ac9e40222b84bb21674cc4f83c8d72a5a26 (2.34-461)
Fix-Commit: e3eef1b8fbdd3a7917af466ca9c4b7477251ca79 (2.33-266)
Fix-Commit: f20a8d696b13c6261b52a6434899121f8b19d5a7 (2.33-265)
Fix-Commit: be602180146de37582a3da3a0caa4b719645de9c (2.32-143)
Fix-Commit: 394eae338199078b7961b051c191539870742d7b (2.32-142)
Fix-Commit: 8d7949183760170c61e55def723c1d8050187874 (2.31-157)
Fix-Commit: 304ce5fe466c4762b21b36c26926a4657b59b53e (2.31-156)
-28
View File
@@ -1,28 +0,0 @@
nscd: netgroup cache may terminate daemon on memory allocation failure
The Name Service Cache Daemon's (nscd) netgroup cache uses xmalloc or
xrealloc and these functions may terminate the process due to a memory
allocation failure resulting in a denial of service to the clients. The
flaw was introduced in glibc 2.15 when the cache was added to nscd.
This vulnerability is only present in the nscd binary.
Subsequent refactoring of the netgroup cache only added more uses of
xmalloc and xrealloc. Uses of xmalloc and xrealloc in other parts of
nscd only occur during startup of the daemon and so are not affected by
client requests that could trigger an out of memory followed by
termination.
CVE-Id: CVE-2024-33601
Public-Date: 2024-04-24
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40)
Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38)
Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75)
Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94)
Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168)
Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319)
Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463)
Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267)
Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144)
Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158)
-26
View File
@@ -1,26 +0,0 @@
nscd: netgroup cache assumes NSS callback uses in-buffer strings
The Name Service Cache Daemon's (nscd) netgroup cache can corrupt memory
when the NSS callback does not store all strings in the provided buffer.
The flaw was introduced in glibc 2.15 when the cache was added to nscd.
This vulnerability is only present in the nscd binary.
There is no guarantee from the NSS callback API that the returned
strings are all within the buffer. However, the netgroup cache code
assumes that the NSS callback uses in-buffer strings and if it doesn't
the buffer resizing logic could lead to potential memory corruption.
CVE-Id: CVE-2024-33602
Public-Date: 2024-04-24
Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15)
Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40)
Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38)
Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75)
Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94)
Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168)
Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319)
Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463)
Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267)
Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144)
Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158)
-77
View File
@@ -1,77 +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.
Reported-By:
The entity that reported this issue. There could be multiple entries, one for
each reporter.
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
Vendored
+36
View File
@@ -4901,6 +4901,9 @@ 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
@@ -7223,6 +7226,39 @@ printf "%s\n" "$libc_cv_mtls_descriptor" >&6; }
config_vars="$config_vars
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; }
if test ${libc_cv_wno_ignored_attributes+y}
+25
View File
@@ -469,6 +469,9 @@ 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])
@@ -1334,6 +1337,28 @@ rm -f conftest*])
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.
dnl It is a usual pattern for weak_alias, where multiple alias point to
+17
View File
@@ -36,6 +36,23 @@ aux := ctype-info
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"
@@ -1,5 +1,5 @@
/* Optimized memchr implementation for POWER10/PPC64.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
/* 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
@@ -16,13 +16,22 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if defined __LITTLE_ENDIAN__ && IS_IN (libc)
#define MEMCHR __memchr_power10
#include <ctype.h>
#undef libc_hidden_builtin_def
#define libc_hidden_builtin_def(name)
#undef weak_alias
#define weak_alias(name,alias)
int
my_isalpha (int ch)
{
return isalpha (ch);
}
#include <sysdeps/powerpc/powerpc64/le/power10/memchr.S>
#endif
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");
+128 -1
View File
@@ -34,7 +34,6 @@ routines = \
dl-addr \
dl-addr-obj \
dl-early_allocate \
dl-find_object \
dl-iteratephdr \
dl-libc \
dl-origin \
@@ -58,9 +57,11 @@ dl-routines = \
dl-close \
dl-debug \
dl-debug-symbols \
dl-debug_state \
dl-deps \
dl-exception \
dl-execstack \
dl-find_object \
dl-fini \
dl-init \
dl-load \
@@ -266,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 \
@@ -378,6 +380,7 @@ tests += \
tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit-tlsdesc-dlopen2 \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@@ -414,8 +417,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 \
@@ -448,6 +459,9 @@ tests += \
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 \
@@ -472,6 +486,7 @@ tests += \
tst-tls19 \
tst-tls20 \
tst-tls21 \
tst-tls23 \
tst-tlsalign \
tst-tlsalign-extern \
tst-tlsgap \
@@ -479,6 +494,7 @@ tests += \
tst-unique2 \
tst-unwind-ctor \
tst-unwind-main \
tst-version-hash-zero \
unload3 \
unload4 \
unload5 \
@@ -509,6 +525,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 \
@@ -520,6 +538,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 \
@@ -813,6 +835,7 @@ modules-names += \
tst-auditmanymod8 \
tst-auditmanymod9 \
tst-auditmod-tlsdesc \
tst-auditmod-tlsdesc2 \
tst-auditmod1 \
tst-auditmod11 \
tst-auditmod12 \
@@ -853,6 +876,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 \
@@ -934,6 +965,7 @@ modules-names += \
tst-tls19mod3 \
tst-tls20mod-bad \
tst-tls21mod \
tst-tls23-mod \
tst-tlsalign-lib \
tst-tlsgap-mod0 \
tst-tlsgap-mod1 \
@@ -964,6 +996,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 \
@@ -2050,6 +2085,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
@@ -3033,6 +3075,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 \
@@ -3118,3 +3163,85 @@ $(objpfx)tst-recursive-tls.out: \
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
$(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-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
# 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-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)
+59 -32
View File
@@ -356,7 +356,7 @@ _dlfo_lookup (uintptr_t pc, struct dl_find_object_internal *first1, size_t size)
}
int
__dl_find_object (void *pc1, struct dl_find_object *result)
_dl_find_object (void *pc1, struct dl_find_object *result)
{
uintptr_t pc = (uintptr_t) pc1;
@@ -463,8 +463,38 @@ __dl_find_object (void *pc1, struct dl_find_object *result)
return -1;
} /* Transaction retry loop. */
}
hidden_def (__dl_find_object)
weak_alias (__dl_find_object, _dl_find_object)
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
@@ -477,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)
@@ -511,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)
{
@@ -662,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
@@ -757,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
@@ -918,6 +918,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. */
@@ -1018,6 +1048,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
@@ -1442,33 +1474,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));
+1 -2
View File
@@ -338,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
+53 -11
View File
@@ -528,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
{
@@ -552,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. */
@@ -627,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;
@@ -661,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)
@@ -1094,9 +1110,32 @@ _dl_tls_initial_modid_limit_setup (void)
}
void
/* 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. */
@@ -1152,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
+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
+8
View File
@@ -17,6 +17,7 @@
#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
@@ -30,4 +31,11 @@ endswithn (const char *name, size_t n, const char *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 */
+119 -107
View File
@@ -1284,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
@@ -1750,33 +1804,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)
@@ -1823,8 +1851,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
@@ -1983,43 +2010,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
@@ -2269,25 +2290,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);
@@ -2310,9 +2331,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)
@@ -2338,7 +2358,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)
@@ -2347,36 +2367,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. */
@@ -2389,16 +2402,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, NULL);
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;
}
@@ -1,4 +1,4 @@
/* x86-64 PLT trampoline register save macros.
/* 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.
@@ -16,19 +16,23 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef DL_STACK_ALIGNMENT
/* Due to GCC bug:
/* This test mimics what the glvndSetupPthreads function in libglvnd
does. */
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
#include <stdlib.h>
#include <support/check.h>
__tls_get_addr may be called with 8-byte stack alignment. Although
this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume
that stack will be always aligned at 16 bytes. */
# define DL_STACK_ALIGNMENT 8
#endif
/* Defined and initialized in the shared objects. */
extern int mod1_status;
extern int mod2_status;
/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align
stack to 16 bytes before calling _dl_fixup. */
#define DL_RUNTIME_RESOLVE_REALIGN_STACK \
(STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \
|| 16 > DL_STACK_ALIGNMENT)
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
@@ -147,10 +147,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
{
@@ -174,17 +171,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;
}
+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>
+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
+22
View File
@@ -0,0 +1,22 @@
/* Stub module for linking tst-version-hash-zero-refmod.so.
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
/* The version script assigns a different symbol version for the stub
module. Loading the module with the incorrect version is expected
to fail. */
#include "tst-version-hash-zero-mod.c"
+7
View File
@@ -0,0 +1,7 @@
Base {
local: *;
};
OTHER_VERSION {
global: global_variable;
} Base;
+20
View File
@@ -0,0 +1,20 @@
/* Test module with a zero version symbol hash.
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
/* The symbol version is assigned by version script. */
int global_variable;
+13
View File
@@ -0,0 +1,13 @@
Base {
local: *;
};
/* Define the version so that tst-version-hash-zero-refmod.so passes
the initial symbol version check. */
OTHER_VERSION {
} Base;
/* This version string hashes to zero. */
PPPPPPPPPPPP {
global: global_variable;
} Base;
+23
View File
@@ -0,0 +1,23 @@
/* Test module that triggers a relocation failure in tst-version-hash-zero.
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
/* This is bound to global_variable@@OTHER_VERSION via
tst-version-hash-zero-linkmod.so, but at run time, only
global_variable@PPPPPPPPPPPP exists. */
extern int global_variable;
int *pointer_variable = &global_variable;
+56
View File
@@ -0,0 +1,56 @@
/* Symbols with version hash zero should not match any version (bug 29190).
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <support/check.h>
#include <support/xdlfcn.h>
#include <stddef.h>
#include <string.h>
static int
do_test (void)
{
void *handle = xdlopen ("tst-version-hash-zero-mod.so", RTLD_NOW);
/* This used to crash because some struct r_found_version entries
with hash zero did not have valid version strings. */
TEST_VERIFY (xdlvsym (handle, "global_variable", "PPPPPPPPPPPP") != NULL);
/* Consistency check. */
TEST_VERIFY (xdlsym (handle, "global_variable")
== xdlvsym (handle, "global_variable", "PPPPPPPPPPPP"));
/* This symbol version is supposed to be missing. */
TEST_VERIFY (dlvsym (handle, "global_variable", "OTHER_VERSION") == NULL);
/* tst-version-hash-zero-refmod.so references
global_variable@@OTHER_VERSION and is expected to fail to load.
dlvsym sets the hidden flag during lookup. Relocation does not,
so this exercises a different failure case. */
TEST_VERIFY_EXIT (dlopen ("tst-version-hash-zero-refmod.so", RTLD_NOW)
== NULL);
const char *message = dlerror ();
if (strstr (message,
": undefined symbol: global_variable, version OTHER_VERSION")
== NULL)
FAIL_EXIT1 ("unexpected dlopen failure: %s", message);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>
+3 -1
View File
@@ -76,7 +76,7 @@ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
bug-iconv13 bug-iconv14 bug-iconv15 \
tst-iconv-iso-2022-cn-ext
tst-iconv-iso-2022-cn-ext tst-bug33980
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -333,6 +333,8 @@ $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh \
$(addprefix $(objpfx), $(gconv-modules)) \
+1 -1
View File
@@ -407,7 +407,7 @@ static const char from_ucs4[][2] =
is also available. */ \
uint32_t ch2; \
\
if (inptr + 1 >= inend) \
if (inend - inptr <= 1) \
{ \
/* The second character is not available. */ \
result = __GCONV_INCOMPLETE_INPUT; \
+55 -15
View File
@@ -67,12 +67,29 @@
/* Since this is a stateful encoding we have to provide code which resets
the output state to the initial state. This has to be done during the
flushing. */
flushing. For the to-internal direction (FROM_DIRECTION is true),
there may be a pending character that needs flushing. */
#define EMIT_SHIFT_TO_INIT \
if ((data->__statep->__count & ~7) != sb) \
{ \
if (FROM_DIRECTION) \
data->__statep->__count &= 7; \
{ \
uint32_t ch = data->__statep->__count >> 7; \
if (__glibc_unlikely (ch != 0)) \
{ \
if (__glibc_unlikely (outend - outbuf < 4)) \
status = __GCONV_FULL_OUTPUT; \
else \
{ \
put32 (outbuf, ch); \
outbuf += 4; \
/* Clear character and db bit. */ \
data->__statep->__count &= 7; \
} \
} \
else \
data->__statep->__count &= 7; \
} \
else \
{ \
/* We are not in the initial state. To switch back we have \
@@ -99,11 +116,13 @@
*curcsp = save_curcs
/* Current codeset type. */
/* Current codeset type. The bit is stored in the __count variable of
the conversion state. If the db bit is set, bit 7 and above store
a pending UCS-4 code point if non-zero. */
enum
{
sb = 0,
db = 64
sb = 0, /* Single byte mode. */
db = 64 /* Double byte mode. */
};
@@ -119,21 +138,29 @@ enum
} \
else \
{ \
/* This is a combined character. Make sure we have room. */ \
if (__glibc_unlikely (outptr + 8 > outend)) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
const struct divide *cmbp \
= &DB_TO_UCS4_COMB[ch - __TO_UCS4_COMBINED_MIN]; \
assert (cmbp->res1 != 0 && cmbp->res2 != 0); \
\
put32 (outptr, cmbp->res1); \
outptr += 4; \
put32 (outptr, cmbp->res2); \
outptr += 4; \
\
/* See whether we have room for the second character. */ \
if (outend - outptr >= 4) \
{ \
put32 (outptr, cmbp->res2); \
outptr += 4; \
} \
else \
{ \
/* Otherwise store only the first character now, and \
put the second one into the queue. */ \
curcs |= cmbp->res2 << 7; \
inptr += 2; \
/* Tell the caller why we terminate the loop. */ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
} \
}
#else
@@ -153,7 +180,20 @@ enum
#define LOOPFCT FROM_LOOP
#define BODY \
{ \
uint32_t ch = *inptr; \
uint32_t ch; \
\
ch = curcs >> 7; \
if (__glibc_unlikely (ch != 0)) \
{ \
put32 (outptr, ch); \
outptr += 4; \
/* Remove the pending character, but preserve state bits. */ \
curcs &= (1 << 7) - 1; \
continue; \
} \
\
/* Otherwise read the next input byte. */ \
ch = *inptr; \
\
if (__builtin_expect (ch, 0) == SO) \
{ \
+153
View File
@@ -0,0 +1,153 @@
/* Test for bug 33980: combining characters in IBM1390/IBM1399.
Copyright (C) 2026 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 <alloc_buffer.h>
#include <errno.h>
#include <iconv.h>
#include <stdbool.h>
#include <string.h>
#include <support/check.h>
#include <support/next_to_fault.h>
#include <support/support.h>
/* Run iconv in a loop with a small output buffer of OUTBUFSIZE bytes
starting at OUTBUF. OUTBUF should be right before an unmapped page
so that writing past the end will fault. Skip SHIFT bytes at the
start of the input and output, to exercise different buffer
alignment. TRUNCATE indicates skipped bytes at the end of
input (0 and 1 a valid). */
static void
test_one (const char *encoding, unsigned int shift, unsigned int truncate,
char *outbuf, size_t outbufsize)
{
/* In IBM1390 and IBM1399, the DBCS code 0xECB5 expands to two
Unicode code points when translated. */
static char input[] =
{
/* 8 letters X. */
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
/* SO, 0xECB5, SI: shift to DBCS, special character, shift back. */
0x0e, 0xec, 0xb5, 0x0f
};
/* Expected output after UTF-8 conversion. */
static char expected[] =
{
'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
/* U+304B (HIRAGANA LETTER KA). */
0xe3, 0x81, 0x8b,
/* U+309A (COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK). */
0xe3, 0x82, 0x9a
};
iconv_t cd = iconv_open ("UTF-8", encoding);
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
char result_storage[64];
struct alloc_buffer result_buf
= alloc_buffer_create (result_storage, sizeof (result_storage));
char *inptr = &input[shift];
size_t inleft = sizeof (input) - shift - truncate;
while (inleft > 0)
{
char *outptr = outbuf;
size_t outleft = outbufsize;
size_t inleft_before = inleft;
size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);
size_t produced = outptr - outbuf;
alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
if (ret == (size_t) -1 && errno == E2BIG)
{
if (produced == 0 && inleft == inleft_before)
{
/* Output buffer too small to make progress. This is
expected for very small output buffer sizes. */
TEST_VERIFY_EXIT (outbufsize < 3);
break;
}
continue;
}
if (ret == (size_t) -1)
FAIL_EXIT1 ("%s (outbufsize %zu): iconv: %m", encoding, outbufsize);
break;
}
/* Flush any pending state (e.g. a buffered combined character).
With outbufsize < 3, we could not store the first character, so
the second character did not become pending, and there is nothing
to flush. */
{
char *outptr = outbuf;
size_t outleft = outbufsize;
size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
TEST_VERIFY_EXIT (ret == 0);
size_t produced = outptr - outbuf;
alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
/* Second flush does not provide more data. */
outptr = outbuf;
outleft = outbufsize;
ret = iconv (cd, NULL, NULL, &outptr, &outleft);
TEST_VERIFY_EXIT (ret == 0);
TEST_VERIFY (outptr == outbuf);
}
TEST_VERIFY_EXIT (!alloc_buffer_has_failed (&result_buf));
size_t result_used
= sizeof (result_storage) - alloc_buffer_size (&result_buf);
if (outbufsize >= 3)
{
TEST_COMPARE (inleft, 0);
TEST_COMPARE (result_used, sizeof (expected) - shift);
TEST_COMPARE_BLOB (result_storage, result_used,
&expected[shift], sizeof (expected) - shift);
}
else
/* If the buffer is too small, only the leading X could be converted. */
TEST_COMPARE (result_used, 8 - shift);
TEST_VERIFY_EXIT (iconv_close (cd) == 0);
}
static int
do_test (void)
{
struct support_next_to_fault ntf
= support_next_to_fault_allocate (8);
for (int shift = 0; shift <= 8; ++shift)
for (int truncate = 0; truncate < 2; ++truncate)
for (size_t outbufsize = 1; outbufsize <= 8; outbufsize++)
{
char *outbuf = ntf.buffer + ntf.length - outbufsize;
test_one ("IBM1390", shift, truncate, outbuf, outbufsize);
test_one ("IBM1399", shift, truncate, outbuf, outbufsize);
}
support_next_to_fault_free (&ntf);
return 0;
}
#include <support/test-driver.c>
+14 -7
View File
@@ -24,33 +24,35 @@ libc_hidden_proto (toupper)
NL_CURRENT_INDIRECT. */
# include "../locale/localeinfo.h"
# include <libc-tsd.h>
# ifndef CTYPE_EXTERN_INLINE /* Used by ctype/ctype-info.c, which see. */
# define CTYPE_EXTERN_INLINE extern inline
# endif
__libc_tsd_define (extern, const uint16_t *, CTYPE_B)
__libc_tsd_define (extern, const int32_t *, CTYPE_TOUPPER)
__libc_tsd_define (extern, const int32_t *, CTYPE_TOLOWER)
extern __thread const uint16_t * __libc_tsd_CTYPE_B
attribute_hidden attribute_tls_model_ie;
extern __thread const int32_t * __libc_tsd_CTYPE_TOUPPER
attribute_hidden attribute_tls_model_ie;
extern __thread const int32_t * __libc_tsd_CTYPE_TOLOWER
attribute_hidden attribute_tls_model_ie;
CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const))
__ctype_b_loc (void)
{
return __libc_tsd_address (const uint16_t *, CTYPE_B);
return &__libc_tsd_CTYPE_B;
}
CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
__ctype_toupper_loc (void)
{
return __libc_tsd_address (const int32_t *, CTYPE_TOUPPER);
return &__libc_tsd_CTYPE_TOUPPER;
}
CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const))
__ctype_tolower_loc (void)
{
return __libc_tsd_address (const int32_t *, CTYPE_TOLOWER);
return &__libc_tsd_CTYPE_TOLOWER;
}
# ifndef __NO_CTYPE
@@ -64,6 +66,11 @@ __ctype_tolower_loc (void)
# define __isdigit_l(c, l) ({ int __c = (c); __c >= '0' && __c <= '9'; })
# endif /* Not __NO_CTYPE. */
/* For use in initializers. */
extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
extern const uint32_t _nl_C_LC_CTYPE_toupper[] attribute_hidden;
extern const uint32_t _nl_C_LC_CTYPE_tolower[] attribute_hidden;
# endif /* IS_IN (libc). */
#endif /* Not _ISOMAC. */
+1 -2
View File
@@ -4,8 +4,7 @@
#include <link.h> /* For ElfW. */
#include <stdbool.h>
extern __typeof (_dl_find_object) __dl_find_object;
hidden_proto (__dl_find_object)
rtld_hidden_proto (_dl_find_object)
/* Internally used flag. */
#define __RTLD_DLOPEN 0x80000000
+3
View File
@@ -53,6 +53,9 @@ extern __typeof (__profile_frequency) __profile_frequency attribute_hidden;
is not for an audit module, not loaded via dlmopen, and not loaded
via static dlopen either). */
extern _Bool __libc_initial attribute_hidden;
#else
/* The static libc is always the initial namespace. */
# define __libc_initial ((_Bool) 1)
#endif
#endif /* _LIBC_INTERNAL */
+3
View File
@@ -212,6 +212,7 @@ struct link_map
unsigned int l_find_object_processed:1; /* Zero if _dl_find_object_update
needs to process this
lt_library map. */
unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen. */
/* NODELETE status of the map. Only valid for maps of type
lt_loaded. Lazy binding sets l_nodelete_active directly,
@@ -364,6 +365,8 @@ struct auditstate
dynamic linker. */
extern struct r_debug_extended _r_debug_extended attribute_hidden;
rtld_hidden_proto (_r_debug)
#if __ELF_NATIVE_CLASS == 32
# define symbind symbind32
# define LA_SYMBIND "la_symbind32"
+4 -1
View File
@@ -130,7 +130,10 @@ fabsf128 (_Float128 x)
}
# endif
# if !(defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0)
/* NB: Internal tests don't have access to internal symbols. */
# if !IS_IN (testsuite_internal) \
&& !(defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0)
# ifndef NO_MATH_REDIRECT
/* Declare some functions for use within GLIBC. Compilers typically
inline those functions as a single instruction. Use an asm to
+2 -3
View File
@@ -3,8 +3,6 @@
# ifndef _ISOMAC
#include <libc-tsd.h>
/* Now define the internal interfaces. */
extern unsigned long _create_xid (void);
@@ -47,7 +45,8 @@ extern void __rpc_thread_key_cleanup (void) attribute_hidden;
extern void __rpc_thread_destroy (void) attribute_hidden;
__libc_tsd_define (extern, struct rpc_thread_variables *, RPC_VARS)
extern __thread struct rpc_thread_variables *__libc_tsd_RPC_VARS
attribute_hidden attribute_tls_model_ie;
#define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x)

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