Compare commits

...
Author SHA1 Message Date
Shamil Abdulaev 5dd252cf1d libio: Add test for fopen with an empty ", ccs=" value [BZ #34574]
This goes on top of the fix for CVE-2026-18374.  The test runs the
reproducer from the bug report, plus "w,ccs=" and "w,ccs=,", and
expects NULL with errno set to EINVAL.

Signed-off-by: Shamil Abdulaev <ashamil435@gmail.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit cca93e5d88)
2026-09-05 00:32:59 +02:00
Dongkyun Son f806c45178 libio: Fix CVE-2026-18374 heap buffer overflow in ccs= handling
When fopen() is called with a ,ccs= parameter whose value becomes empty
after strip(), the code must reject it with EINVAL instead of attempting
to use it.  The original upstr() fallback could read past the ',' delimiter
and cause a heap buffer overflow.

The fix checks if the charset specification is empty after strip() and
returns EINVAL immediately, preventing the overflow and following the
approach described in BZ #34574.

CVE-2026-18374 - CVSS 4.9 (AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L)

Reported-by: AISLE in partnership with Red Hat
Signed-off-by: Dongkyun Son <dongkyun.s@samsung.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 9765a538eb)
2026-09-05 00:32:58 +02:00
Florian Weimer 3d141c2389 iconvdata: Test case for bug 34556, bug 34568
Assisted-by: LLM
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 35efcffa97)
2026-08-29 14:27:32 +02:00
Florian Weimer ec116a0fbe iconvdata: EUC_JISX0213 decoding lacks pending character reset (CVE-2026-80489)
This fixes bug 34568.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 4dafa087ff)
2026-08-29 14:27:32 +02:00
Florian Weimer e43e46f943 iconvdata: SHIFT_JISX0213 decoding lacks pending character reset (CVE-2026-77117)
This fixes bug 34556.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 68d94bbe50)
2026-08-29 14:27:32 +02:00
Florian Weimer 5256941bc8 stdlib: Fix right-justification in strfmon (bug 34510, CVE-2026-19499)
The memmove call did not take into account that __printf_buffer_pad
updated the buffer pointers.

Fixes commit e88b9f0e5c
("stdio-common: Convert vfprintf and related functions to buffers"),
which went into glibc 2.37.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit b090cf226f)
2026-08-28 21:25:22 +02:00
Adhemerval Zanella 6826bb0ed0 posix: Remove unnecessary overflow check in wordexp (BZ 34090)
The WRDE_APPEND path duplicates the caller's we_wordv array, which
already holds we_offs + we_wordc + 1 pointers.  Follow-up to commit
e2cefe16c3.

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

(cherry picked from commit 53ec26f173)
2026-08-28 21:19:16 +02:00
Florian Weimer 9318c25715 misc: Fix out-of-bounds array write in tdelete (bug 34506)
Allocate the maximum array sizes directly, instead of resizing
the arrays as needed.  This eliminates alloca usage from the
function, and fixes the out-of-bounds accesses.  The asserts
guard against the bug coming back if the balancing of the tree
turns out not to work correctly.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit e2789c46e3)
2026-08-28 21:06:14 +02:00
Adhemerval Zanella dfc8ef388e posix: Fix wordexp WRDE_APPEND to preserve state on non-NOSPACE errors (BZ 34090, CVE-2026-6368)
The previous implementation saved a copy of the wordexp_t struct at
entry and blindly restored it on error via (*pwordexp = old_word).
This is incorrect when WRDE_APPEND is set because w_addword may have
called realloc on we_wordv during partial processing before the error
was detected.  If realloc relocated the buffer, the saved we_wordv
pointer is dangling; restoring it causes a use-after-free in the
caller (e.g. via wordfree), and the relocated buffer is leaked.

Fix this by duplicating the we_wordv pointer array at entry when
WRDE_APPEND is set, so that all subsequent realloc calls inside
w_addword operate on the copy.

This change also fixes a POSIX conformance issue: if the WRDE_APPEND
flag is specified, pwordexp->we_wordc and pwordexp->we_wordv shall
not be modified.

Also fix two pre-existing error return paths in the '"' and '\'' cases
that returned directly from w_addword failures instead of going through
do_error, which would leak the saved array (and previously would also
skip the word cleanup).

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

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit e2cefe16c3)
2026-08-14 20:07:13 +02:00
Adhemerval Zanella 965b580070 posix: Fix stack overflow in wordexp tilde expansion (BZ 34091, CVE-2026-6791)
The parse_tilde function previously used strndupa to allocate memory
for the parsed username on the stack, and since the input is
user-defined, this can lead to a stack overflow.

This patch fixes the issue by replacing strndupa with scratch_buffer,
by reusing the buffer used in the __getpwnam_r call.

The new “tst-wordexp-tilde.c” test is a test-container to avoid using
system-defined NSS modules.

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

(cherry picked from commit 07c24f3539)
2026-08-14 20:07:13 +02:00
Florian Weimer ca40a19768 resolv: Add test case tst-ns_sprintrr (bug 34033, bug 34069)
This test case covers both input buffer overreads and output buffer
overflows.  It should systematically cover these issues.

I used code auto-generation for updating the test expectations for
truncated RDATA in TXT, ISDN records, after writing the rest
of the test by hand.

Assisted-by: LLM
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 4ba0b79b95)
2026-08-14 20:07:13 +02:00
Florian Weimer 05e1eaea61 resolv: Fix buffer overreads in ns_sprintrrf (CVE-2026-6238)
Check that the RDATA payload does not require more than RDATALEN
bytes while processing it.  The fixes cover A6, LOC records.
(CERT, TKEY, TSIG were fixed before, by switching to the generic
formatter.)

The vulnerable LOC record handling was first introduced before
glibc 2.0, in commit ee188d555b.

CERT, TSIG, TKEY handling came with commit
b43b13ac25, released with glibc 2.2.

A6 record handling was introduced in commit
9163381643 ("* resolv/ns_print.c
(ns_sprintrrf): Handle ns_t_a6 and ns_t_opt."), which went into glibc
2.7.

This fixes bug 34069.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit a7b60d23bb)
2026-08-14 20:07:13 +02:00
Florian Weimer 0e8c56b386 resolv: More types as unknown in ns_sprintrrf (CVE-2026-5435)
Specifically, CERT, TKEY, TSIG, OPT.  This removes the buggy
implementations of TSIG, fixing bug 34033, and partially
fixing bug 34069.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit ca44a6609c)
2026-08-14 20:07:13 +02:00
Florian Weimer 1c77f57252 resolv: Check for inet_ntop failure in ns_sprintrrf
This makes the output more consistent (either failure or complete
output) and helps with systematic testing with varying buffer
sizes.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit cd0db208d5)
2026-08-14 20:07:13 +02:00
Florian Weimer 6448c1174a resolv: Improve formatting of unknown records in ns_sprintrrf
Do not add the "unknown RR type" comment.  After adding the TYPE
prefix, the number is largely redundant.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit d58415eb17)
2026-08-14 20:07:13 +02:00
Florian Weimer 2b789d4ca9 resolv: Fix ns_sprintrrf formatting of class, type values (bug 34289)
The p_class and p_type results could overwrite each other if both
were unknown.  Format unknown values with CLASS and TYPE prefixes,
as in RFC 3597.  Handle A6 separately because it cannot be added
to __p_type_syms for ABI reasons.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit f69b7f95e3)
2026-08-14 20:07:13 +02:00
Florian Weimer 127d20da1c resolv: Declare __p_class_syms, __p_type_syms for internal use
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 360f352c9a)
2026-08-14 20:07:13 +02:00
Fabian Rast 30164ba504 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:01:15 -07:00
Florian Weimer fc7a48bc9e iconv: Suppress intermediate errors with //TRANSLIT (bug 34236)
When tentatively converting characters on behalf of
__gconv_transliterate, do not create a persistent error.  Just
produce a local error, and rely on __gconv_transliterate to
produce the error if all transliteration options are exhausted.

This fixes transliteration of “½” to ASCII, which cannot use the
“ 1⁄2 ” alternative.  Eventually, the “ 1/2 ” alternative is chosen,
but the error sticks.  Therefore, iconv exited with status 1 before
this change.

Adjust iconv/tst-iconv_prog.sh to test both C and en_US.UTF-8 locales.
This requires changing the way the ICONV template is defined, so that
run_program_env is evaluated multiple times.

Fixes commit 9a4b0eaf72 ("iconv: do not
report error exit with transliteration [BZ #32448]"),
commit 6cbf845fcd ("iconv: Preserve
iconv -c error exit on invalid inputs (bug 32046)"), and bug 34236.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit e9325bd7d0)
2026-06-23 06:39:25 +02:00
Rocket Ma 1a74f82eed stdio-common: Fix buffer overflow in scanf %mc [BZ #34008]
* stdio-common/vfscanf-internal.c: When enlarging allocated buffer with
format %mc or %mC, glibc allocates one byte less, leading to
user-controlled one byte overflow. This commit fixes BZ #34008, or
CVE-2026-5450.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Signed-off-by: Rocket Ma <marocketbd@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 8398987772)
2026-06-23 06:37:59 +02:00
DJ Delorie 248f5e876f stdio-common: Allow partially-filled %mc buffers [BZ #12701]
This is a backwards-compatible alternative to the main solution to
the %mc part of 12701.  The allocated buffer is expanded to the
requested size and NUL padded, but truncated reads are allowed.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-06-23 06:35:51 +02:00
Maciej W. Rozycki 372a64662f stdio-common: Reject insufficient character data in scanf [BZ #12701]
Reject invalid formatted scanf character data with the 'c' conversion
where there is not enough input available to satisfy the field width
requested.  It is required by ISO C that this conversion matches a
sequence of characters of exactly the number specified by the field
width and it is also already documented as such in our own manual:

"It reads precisely the next N characters, and fails if it cannot get
that many."

Currently a matching success is instead incorrectly produced where the
EOF condition is encountered before the required number of characters
has been retrieved, and the characters actually obtained are stored in
the buffer provided.

Add test cases accordingly and remove placeholders from 'c' conversion
input data for the existing scanf tests.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

[This is a modified version of commit 2b16c76609, which tests for the
old behavior and only includes the test cases, for older branches
and downstream backports - DJ]

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-06-23 06:35:43 +02:00
Maciej W. Rozycki b214eb550e support: Implement 'xfmemopen' for seamless 'fmemopen' use
Add 'xfmemopen' wrapper for seamless 'fmemopen' use in tests, following
'xfopen', 'xfclose', etc., and providing a standardized error reporting
facility.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit fe709cc245)

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-06-23 06:35:37 +02:00
Rocket Ma 8941538b92 libio: Fix ungetwc operating on byte stream [BZ #33998]
* libio/wgenops.c: When _IO_wdefault_pbackfail attempts to push back one
character, it accidently compare the wchar to push back with the last
char from byte stream, instead of wide stream. Under specific coding,
attacker may exploit this to leak information. This commit fix bug
33998, or CVE-2026-5928.

Signed-off-by: Rocket Ma <marocketbd@gmail.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit ef3bfb5f91)
2026-06-23 06:33:24 +02:00
Florian Weimer b676adadbc 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:15:30 +02:00
DJ Delorie df2d5e2361 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:15:30 +02:00
Florian Weimer 61737f43b1 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 21:52:02 +02:00
Michael Jeanson 47c0cc364d tests: fix tst-rseq with Linux 7.0
A sub-test of tst-rseq is to validate the return code and errno of the
rseq syscall when attempting to register the exact same rseq area as was
done in the dynamic loader.

This involves finding the rseq area address by adding the
'__rseq_offset' to the thread pointer and calculating the area size from
the AT_RSEQ_FEATURE_SIZE auxiliary vector. However the test currently
calculates the size of the rseq area allocation in the TLS block which
must be a multiple of AT_RSEQ_ALIGN.

Up until now that happened to be the same value since the feature size
and alignment exposed by the kernel were below the minimum ABI size of
32. Starting with Linux 7.0 the feature size has reached 33 while the
alignment is now 64.

This results in the test trying to re-register the rseq area with a
different size and thus not getting the expected errno value.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
(cherry picked from commit 67f303b47d)
2026-03-29 16:41:11 +02:00
Xi Ruoyao c812169b57 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 16:41:03 +02:00
Carlos O'Donell 502861645b 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-28 15:13:58 +01:00
Carlos O'Donell dbd8335c8c 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-28 15:13:55 +01:00
Florian Weimer 81e8f4e08b 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:43:00 +01:00
Florian Weimer 61a5190ee5 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:43:00 +01:00
Yury Khrustalev e494d26262 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:43:00 +01:00
Florian Weimer 8c00f7809b nss: Missing checks in __nss_configure_lookup, __nss_database_get (bug 28940)
This avoids a null pointer dereference in the
nss_database_check_reload_and_get function, and assertion failures.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 5b713b4944)
2026-02-18 08:59:13 +01:00
Florian Weimer 872728982d Linux: In getlogin_r, use utmp fallback only for specific errors
Most importantly, if getwpuid_r fails, it does not make sense to retry
via utmp because the user ID obtained from there is less reliable than
the one from /proc/self/loginuid.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 28660f4b45)
2026-02-18 08:59:13 +01:00
Florian Weimer 3136abefc5 nss: Introduce dedicated struct nss_database_for_fork type
The initialized field in struct nss_database_data is rather confusing
because it is not used by the regular NSS code, only by the fork
state synchronization code.  Introduce a separate type and place
the initialized field there.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 7bb859f419)
2026-02-18 08:59:13 +01:00
Florian Weimer 16e03cec84 Switch currency symbol for the bg_BG locale to euro
Bulgaria joined the eurozone on 2026-01-01.

Suggested-by: Йордан Гигов <jgigov@abv.bg>
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
(cherry picked from commit 78fdb2d6b1)
2026-01-24 13:26:31 +01:00
Adhemerval Zanella fb4db64a04 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 12:36:02 -03:00
Carlos O'Donell 15c9839a0b 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:33 -05:00
Siddhesh Poyarekar 1e2c1ea430 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:13:57 -05:00
Sunil K Pandey c96b4ed1e2 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:57:22 -08:00
Florian Weimer 6b74a7c444 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 19:25:43 +01:00
Florian Weimer d07b87d766 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 19:25:43 +01:00
Collin Funk 473359f17a 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 19:25:43 +01:00
DJ Delorie 6bcdbc7dfd 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 19:25:43 +01:00
Sachin Monga 6a0b8e3665 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 04:09:52 -05:00
Sachin Monga f8cdc03e1e 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:31:08 -05:00
Sachin Monga 040256e79b ppc64le: Restore optimized strcmp for power10
This patch addresses the actual cause of CVE-2025-5702

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

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

Signed-off-by: Sachin Monga <smonga@linux.ibm.com>
Co-authored-by: Paul Murphy <paumurph@redhat.com>
(cherry picked from commit 9a40b1cda5)
2025-11-21 01:30:45 -05:00
Pierre Blanchard 5c6445672a 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:12:52 +00:00
Pierre Blanchard 1e16b570bb AArch64: fix SVE tanpi(f) [BZ #33642]
Fixed svld1rq using incorrect predicates (BZ #33642).
Next to no performance variations (tested on V1).

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit e889160273)
2025-11-18 16:12:52 +00:00
Joe Ramsay 442cc3901b AArch64: Fix instability in AdvSIMD sinh
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. No measured change in performance. This patch applies cleanly as
far back as 2.41, however there are conflicts with 2.40 where sinh was
first introduced.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit e45af510bc)
2025-11-18 16:12:52 +00:00
Joe Ramsay ca489fc802 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:12:52 +00:00
Joe Ramsay 360f60fb63 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:12:52 +00:00
Yury Khrustalev 215e9155ea 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)
2025-11-13 13:38:09 +00:00
Florian Weimer 75b6b263e9 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>
2025-11-13 14:33:09 +01:00
Yury Khrustalev 5bf8ee7ad5 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)
2025-11-10 11:31:05 +00:00
Yury Khrustalev e4ffcf32b9 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)
2025-11-10 11:31:05 +00:00
Yury Khrustalev 889ae4bdbb 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)
2025-11-10 11:31:05 +00:00
Yury Khrustalev 1a0ee26714 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>
2025-11-10 11:31:04 +00:00
Yury Khrustalev 97076e0cf1 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)
2025-11-10 11:28:19 +00:00
Yury Khrustalev 1f57ffdf35 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)
2025-11-10 11:28:19 +00:00
Jiamei Xie 580746904b 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:22 +00:00
Sunil K Pandey 7c0632472d 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 11:36:36 -07:00
Sunil K Pandey 4b1f8c90f9 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 11:36:14 -07:00
Florian Weimer cf926cd7fb 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:20:48 +02:00
Pierre Blanchard 9867e44cdc 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:31:38 +00:00
Florian Weimer a52c9b75c7 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:06:40 +02:00
H.J. Lu ed4672abb5 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 16:20:46 -07:00
H.J. Lu 7aa907241c 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 06:39:13 -07:00
H.J. Lu c1bec0b52d 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 12:44:54 -07:00
Florian Weimer aa5dbd5332 elf: Preserve _rtld_global layout for the release branch
Backporting commit 9d6577fdff
("elf: Introduce _dl_debug_change_state") removed the
_ns_debug member.  Keep it to preseve struct layout.
2025-08-18 14:15:33 +02:00
Florian Weimer 42f9c70ac2 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:06:12 +02:00
Florian Weimer 3f3b4fdd0b 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:06:12 +02:00
H.J. Lu e2d9e9eb26 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:22 +01:00
H.J. Lu dd87fcda43 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:17:42 +01:00
Florian Weimer 85780b6055 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-15 19:43:48 +02:00
Florian Weimer b05ce0de3d 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-15 19:43:48 +02:00
Florian Weimer 9d6577fdff 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-15 19:43:48 +02:00
Florian Weimer 4a3e5f1e4c 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-15 19:43:48 +02:00
Jens Remus 940d821afb 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:07:42 +02:00
Florian Weimer 5d8614b284 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 11:41:34 +02:00
Florian Weimer f409ec073f 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:41:34 +02:00
Florian Weimer 330cd035df 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:41:34 +02:00
Luna Lamb c467918138 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:31:30 +00:00
Dylan Fleming 6db0f659c8 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:31:16 +00:00
Dylan Fleming 503f7a7d33 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:31:10 +00:00
Luna Lamb 307a8a4434 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:30:54 +00:00
Dylan Fleming 2a0b52fdd6 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:30:38 +00:00
Pierre Blanchard 0bb6dad5af 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:30:28 +00:00
Wilco Dijkstra daa4de5253 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 14:58:23 +00:00
Adhemerval Zanella 1502c248d5 nptl: Fix SYSCALL_CANCEL for return values larger than INT_MAX (BZ 33245)
The SYSCALL_CANCEL calls __syscall_cancel, which in turn
calls __internal_syscall_cancel with an 'int' return instead of the
expected 'long int'.  This causes issues with syscalls that return
values larger than INT_MAX, such as copy_file_range [1].

Checked on x86_64-linux-gnu.

[1] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79139

Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
(cherry picked from commit 7107bebf19)
2025-08-01 17:43:29 -03:00
Florian Weimer 513629b14d 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-01 19:28:30 +02:00
Florian Weimer f48de98bce 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-01 19:28:30 +02:00
Florian Weimer 62928cf7d8 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-01 19:28:30 +02:00
Davide Cavalca 373408c19f stdlib: resolve a double lock init issue after fork [BZ #32994]
The __abort_fork_reset_child (introduced in
d40ac01cbb) call resets the lock after the
fork. This causes a DRD regression in valgrind
(https://bugs.kde.org/show_bug.cgi?id=503668), as it's effectively a
double initialization, despite it being actually ok in this case. As
suggested in https://sourceware.org/bugzilla/show_bug.cgi?id=32994#c2
we replace it here with a memcpy of another initialized lock instead,
which makes valgrind happy.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit d9a348d092)
2025-08-01 13:42:43 +02:00
Florian Weimer e7c419a295 iconv: iconv -o should not create executable files (bug 33164)
The mistake is that open must use 0666 to pick up the umask,
and not 0777 (which is required by mkdir).

Fixes commit 8ef3cff9d1
("iconv: Support in-place conversions (bug 10460, bug 32033)").

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit cdcf24ee14)
2025-07-24 09:53:50 +02:00
Florian Weimer 1e16d0096d 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:06 +02:00
Florian Weimer 6e489c17f8 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:38:57 +02:00
Florian Weimer 11e634ccf3 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:11:00 +02:00
Adhemerval Zanella 61e461ed0c sparc: Fix sparc32 Fix argument passing to __libc_start_main (BZ 32981)
Commit 404526ee2e changed _start to write
the last argument to __libc_start_main without taking into consideration
that the function did not create a full stack frame, which leads to
overwriting the argv[0].

(cherry picked from commit 8788bd77d6)
2025-06-18 11:22:24 -03:00
Carlos O'Donell 0c76c95162 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:17:36 -04:00
Carlos O'Donell b48d7ab036 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:17:29 -04:00
Carlos O'Donell 55cdcadf73 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:17:18 -04:00
Carlos O'Donell 84bdbf8a6f 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:17:11 -04:00
Adhemerval Zanella d952c6efaa sparc: Fix argument passing to __libc_start_main (BZ 32981)
sparc start.S does not provide the final argument for
__libc_start_main, which is the highest stack address used to
update the __libc_stack_end.A

This fixes elf/tst-execstack-prog-static-tunable on sparc64.
On sparcv9 this does not happen because the kernel puts an
auxv value, which turns to point to a value in the stack itself.

Checked on sparc64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 404526ee2e)
2025-06-03 09:59:01 -03:00
Florian Weimer 515d4166f4 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:10 +02:00
Sunil K Pandey 899dd3ab2f 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:28 -07:00
Florian Weimer 624285af3b 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:45:06 +02:00
Florian Weimer 2ca34d7627 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:41:26 +02:00
Florian Weimer dab44a3b2b 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 17:04:08 +02:00
Adhemerval Zanella 5cf17ebc65 hurd: Fix tst-stack2 test build on Hurd
It requires $(shared-thread-library).  Fixes 0c34259423.

Checked on a i686-gnu build.

(cherry picked from commit f66cb3c9eb)
2025-05-09 10:25:19 -03:00
Adhemerval Zanella 5b4c461701 nptl: Fix pthread_getattr_np when modules with execstack are allowed (BZ 32897)
The BZ 32653 fix (12a497c716) kept the
stack pointer zeroing from make_main_stack_executable on
_dl_make_stack_executable.  However, previously the 'stack_endp'
pointed to temporary variable created before the call of
_dl_map_object_from_fd; while now we use the __libc_stack_end
directly.

Since pthread_getattr_np relies on correct __libc_stack_end, if
_dl_make_stack_executable is called (for instance, when
glibc.rtld.execstack=2 is set) __libc_stack_end will be set to zero,
and the call will always fail.

The __libc_stack_end zero was used a mitigation hardening, but since
52a01100ad it is used solely on
pthread_getattr_np code.  So there is no point in zeroing anymore.

Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Sam James <sam@gentoo.org>

(cherry picked from commit 0c34259423)
2025-04-29 15:27:21 -03:00
Aurelien Jarno 5cb575ca9a elf: tst-audit10: split AVX512F code into dedicated functions [BZ #32882]
"Recent" GCC versions (since commit fc62716fe8d1, backported to stable
branches) emit a vzeroupper instruction at the end of functions
containing AVX instructions. This causes the tst-audit10 test to fail
on CPUs lacking AVX instructions, despite the AVX512F check. The crash
occurs in the pltenter function of tst-auditmod10b.c.

Fix that by moving the code guarded by the check_avx512 function into
specific functions using the target ("avx512f") attribute. Note that
since commit 5359c3bc91 ("x86-64: Remove compiler -mavx512f check") it
is safe to assume that the compiler has AVX512F support, thus the
__AVX512F__ checks can be dropped.

Tested on non-AVX, AVX2 and AVX512F machines.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit e78caeb4ff)
2025-04-23 23:08:42 +02:00
H.J. Lu 046b33800c 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:02:15 -07:00
Sunil K Pandey a53e764657 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:02:03 -07:00
Sunil K Pandey aca31d2712 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:01:51 -07:00
Sunil K Pandey f68b407d4b 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:01:22 -07:00
Adhemerval Zanella d6d56af6e7 elf: Fix arm-linux-gnueabihf build break from b861755a84 2025-04-10 12:08:22 +00:00
Adhemerval Zanella b861755a84 elf: Extend glibc.rtld.execstack tunable to force executable stack (BZ 32653)
From the bug report [1], multiple programs still require to dlopen
shared libraries with either missing PT_GNU_STACK or with the executable
bit set.  Although, in some cases, it seems to be a hard-craft assembly
source without the required .note.GNU-stack marking (so the static linker
is forced to set the stack executable if the ABI requires it), other
cases seem that the library uses trampolines [2].

Unfortunately, READ_IMPLIES_EXEC is not an option since on some ABIs
(x86_64), the kernel clears the bit, making it unsupported.  To avoid
reinstating the broken code that changes stack permission on dlopen
(0ca8785a28), this patch extends the glibc.rtld.execstack tunable to
allow an option to force an executable stack at the program startup.

The tunable is a security issue because it defeats the PT_GNU_STACK
hardening.  It has the slight advantage of making it explicit by the
caller, and, as for other tunables, this is disabled for setuid binaries.
A tunable also allows us to eventually remove it, but from previous
experiences, it would require some time.

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

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=32653
[2] https://github.com/conda-forge/ctng-compiler-activation-feedstock/issues/143
Reviewed-by: Sam James <sam@gentoo.org>

(cherry picked from commit 12a497c716)
2025-04-09 13:19:36 +00:00
Florian Weimer 200d20123c 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:06 +02:00
Florian Weimer 80cd656649 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 09:43:57 +01:00
Florian Weimer a282e2c0ae 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 09:42:31 +01:00
Sunil K Pandey bcd4cf9d5f 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:01:25 -07:00
Sunil K Pandey 7e72fa7577 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:58:14 -07:00
Sunil K Pandey 6a3a4a5e58 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:58:03 -07:00
Adhemerval Zanella ce9b765522 nptl: Check if thread is already terminated in sigcancel_handler (BZ 32782)
The SIGCANCEL signal handler should not issue __syscall_do_cancel,
which calls __do_cancel and __pthread_unwind, if the cancellation
is already in proces (and libgcc unwind is not reentrant).  Any
cancellation signal received after is ignored.

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

Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Florian Weimer <fweimer@redhat.com>

(cherry picked from commit 360cce0b06)
2025-03-13 10:33:54 -03:00
Florian Weimer 98c712855d nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions (bug 32786)
The new initializer and struct layout does not initialize the
__g_signals field in the old struct layout before the change in
commit c36fc50781 ("nptl: Remove
g_refs from condition variables").  Bring back fields at the end
of struct __pthread_cond_s, so that they are again zero-initialized.

Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit dbc5a50d12)
2025-03-13 07:45:21 +01:00
Michael Jeanson e22c132484 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:24:43 +00:00
Florian Weimer 33bfd9020f Linux: Remove attribute access from sched_getattr (bug 32781)
The GCC attribute expects an element count, not bytes.

(cherry picked from commit 74c68fa61b)
2025-03-12 10:47:03 +01:00
Aurelien Jarno 66fc3bd758 math: Remove an extra semicolon in math function declarations
Commit 6bc301672b ("math: Remove __XXX math functions from installed
math.h [BZ #32418]") left an extra semicolon after macro expansion. For
instance the ceil declaration after expansion is:

  extern double ceil (double __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));;

This chokes very naive parsers like gauche c-wrapper. Fix that by
removing that extra semicolon in the macro.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 443cb0b5f2)
2025-03-08 13:35:03 +01:00
Florian Weimer 1a3083b999 posix: Move environ helper variables next to environ definition (bug 32541)
This helps with statically interposing getenv.

Updates commit 7a61e7f557
("stdlib: Make getenv thread-safe in more cases").

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6ef0bd02db)
2025-03-07 21:41:13 +01:00
Florian Weimer 91f8cff2c4 configure: Fix spelling of -Wl,--no-error-execstack option
BFD ld recognizes all -no-* options (with a single leading dash)
unconditionally.

Fixes commit a2bd5008a9
("Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack
is used [PR32717]").

(cherry picked from commit 59dc232df2)
2025-03-07 07:22:10 +00:00
H.J. Lu fd202462c5 elf: Check if __attribute__ ((aligned (65536))) is supported
The BZ #32763 tests fail to build for MicroBlaze (which defines
MAX_OFILE_ALIGNMENT to (32768*8) in GCC, so __attribute__ ((aligned
(65536))) is unsupported).  Add a configure-time check to enable BZ #32763
tests only if __attribute__ ((aligned (65536))) is supported.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 9b91484bee)
2025-03-07 14:05:30 +08:00
H.J. Lu 746ef8e939 static-pie: Skip the empty PT_LOAD segment at offset 0 [BZ #32763]
As shown in

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

linker may generate an empty PT_LOAD segments at offset 0:

Elf file type is EXEC (Executable file)
Entry point 0x4000e8
There are 3 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000000f0 0x00000000000000f0  R E    0x1000
  LOAD           0x0000000000000000 0x0000000000410000 0x0000000000410000
                 0x0000000000000000 0x0000000000b5dce8  RW     0x10000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10

 Section to Segment mapping:
  Segment Sections...
   00     .text
   01     .bss
   02

Skip the empty PT_LOAD segment at offset 0 to support such binaries.
This fixes BZ #32763.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 596130591a)
2025-03-06 07:49:27 +08:00
Sam James 56609f8df1 Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack is used [PR32717]
When GNU Binutils is configured with --enable-error-execstack=yes, a handful
of our tests which rely on -Wl,-z,execstack fail. Pass --Wl,--no-error-execstack
to override the behaviour and get a warning instead.

Bug: https://sourceware.org/PR32717
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit a2bd5008a9)
2025-03-05 22:58:39 +00:00
Wilco Dijkstra 89be78704e 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:11:05 +00:00
Wilco Dijkstra c47c3890f1 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:11:05 +00:00
Wilco Dijkstra e0bc5f64ea 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:11:05 +00:00
Yury Khrustalev 009c5a2dca aarch64: Add GCS test with signal handler
Test that when we return from a function that enabled GCS at runtime
we get SIGSEGV. Also test that ucontext contains GCS block with the
GCS pointer.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 09:49:37 +00:00
Yury Khrustalev 8d98ee8d70 aarch64: Add GCS tests for dlopen
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 09:49:37 +00:00
Yury Khrustalev 61ba3cdfa9 aarch64: Add GCS tests for transitive dependencies
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 09:49:37 +00:00
Yury Khrustalev fda5730898 aarch64: Add tests for Guarded Control Stack
These tests validate that GCS tunable works as expected depending
on the GCS markings in the test binaries.

Tests validate both static and dynamically linked binaries.

These new tests are AArch64 specific. Moreover, they are included only
if linker supports the "-z gcs=<value>" option. If built, these tests
will run on systems with and without HWCAP_GCS. In the latter case the
tests will be reported as UNSUPPORTED.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 09:49:37 +00:00
Yury Khrustalev 6d1f97bb06 aarch64: Add configure checks for GCS support
- Add check that linker supports -z gcs=...
 - Add checks that main and test compiler support
   -mbranch-protection=gcs

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 09:49:37 +00:00
Yat Long Poon 7774a9d07a 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 15:19:32 +00:00
Yat Long Poon 2025e27a81 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 15:19:23 +00:00
Yat Long Poon f3d9c116cb 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 15:19:13 +00:00
Luna Lamb 94859e8680 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 15:19:04 +00:00
Luna Lamb 7c9a086807 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 15:18:54 +00:00
Yangyu Chen 30992cb5e9 RISC-V: Fix IFUNC resolver cannot access gp pointer
In some cases, an IFUNC resolver may need to access the gp pointer to
access global variables. Such an object may have l_relocated == 0 at
this time. In this case, an IFUNC resolver will fail to access a global
variable and cause a SIGSEGV.

This patch fixes this issue by relaxing the check of l_relocated in
elf_machine_runtime_setup, but added a check for SHARED case to avoid
using this code in static-linked executables. Such object have already
set up the gp pointer in load_gp function and l->l_scope will be NULL if
it is a pie object. So if we use these code to set up the gp pointer
again for static-pie, it will causing a SIGSEGV in glibc as original bug
on BZ #31317.

I have also reproduced and checked BZ #31317 using the mold commit
bed5b1731b ("illumos: Treat absolute symbols specially"), this patch can
fix the issue.

Also, we used the wrong gp pointer previously because ref->st_value is
not the relocated address but just the offset from the base address of
ELF. An edge case may happen if we reference gp pointer in a IFUNC
resolver in a PIE object, but it will not happen in compiler-generated
codes since -pie will disable relax to gp. In this case, the GP will be
initialized incorrectly since the ref->st_value is not the address after
relocation. This patch fixes this issue by adding the l->l_addr to
ref->st_value to get the relocated address for the gp pointer. We don't
use SYMBOL_ADDRESS macro here because __global_pointer$ is a special
symbol that has SHN_ABS type, but it will use PC-relative addressing in
the load_gp function using lla.

Closes: BZ #32269
Fixes: 96d1b9ac23 ("RISC-V: Fix the static-PIE non-relocated object check")

Co-authored-by: Vivian Wang <dramforever@live.com>
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
(cherry picked from commit 3fd2ff7685)
2025-02-26 19:22:07 +01:00
John David Anglin 07288c7445 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 15:59:49 -05:00
koraynilay 2cb04444b9 math: Fix unknown type name '__float128' for clang 3.4 to 3.8.1 (bug 32694)
When compiling a program that includes <bits/floatn.h> using a clang version
between 3.4 (included) and 3.8.1 (included), clang will fail with `unknown type
name '__float128'; did you mean '__cfloat128'?`. This changes fixes the clang
prerequirements macro call in floatn.h to check for clang 3.9 instead of 3.4,
since support for __float128 was actually enabled in 3.9 by:

commit 50f29e06a1b6a38f0bba9360cbff72c82d46cdd4
Author: Nemanja Ivanovic <nemanja.i.ibm@gmail.com>
Date:   Wed Apr 13 09:49:45 2016 +0000

    Enable support for __float128 in Clang

This fixes bug 32694.

Signed-off-by: koraynilay <koray.fra@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 29803ed3ce)
2025-02-23 13:37:58 +08:00
H.J. Lu a900dbaf70 x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL compiler [BZ #32723]
Intel compiler always defines __INTEL_LLVM_COMPILER.  When SYCL is
enabled by -fsycl, it also defines SYCL_LANGUAGE_VERSION.  Since Intel
SYCL compiler doesn't support _Float128:

https://github.com/intel/llvm/issues/16903

define __HAVE_FLOAT128 to 0 for Intel SYCL compiler.

This fixes BZ #32723.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 5a4573be6f)
2025-02-20 09:02:38 +08:00
Aurelien Jarno 1e0e33e1b1 Fix tst-aarch64-pkey to handle ENOSPC as not supported
The syscall pkey_alloc can return ENOSPC to indicate either that all
keys are in use or that the system runs in a mode in which memory
protection keys are disabled. In such case the test should not fail and
just return unsupported.

This matches the behaviour of the generic tst-pkey.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 60f2d6be65)
2025-02-15 11:12:18 +01:00
Siddhesh Poyarekar 69fda28279 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:38:18 -05:00
Adhemerval Zanella cf88351b68 math: Fix tanf for some inputs (BZ 32630)
The logic was copied wrong from CORE-MATH.

(cherry picked from commit 09e7f4d594)
2025-02-03 09:44:45 -03:00
John David Anglin cb7f206537 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:46:24 -05:00
Adhemerval Zanella d85a771953 math: Fix sinhf for some inputs (BZ 32627)
The logic was copied wrong from CORE-MATH.
2025-01-31 13:11:38 -03:00
Adhemerval Zanella bdccbfbc52 math: Fix log10p1f internal table value (BZ 32626)
It was copied wrong from CORE-MATH.

(cherry picked from commit c79277a167)
2025-01-31 13:10:45 -03:00
Andreas K. Hüttel 0a7c7a3e28 NEWS: start new section
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2025-01-28 21:11:22 +01:00
Andreas K. Hüttel 9f48a8abb2 Remove advisories from release branch
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2025-01-28 18:45:20 +01:00
352 changed files with 10004 additions and 3313 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
+1 -1
View File
@@ -633,7 +633,7 @@ link-libc-printers-tests = $(link-libc-rpath) \
$(link-libc-tests-after-rpath-link)
# This is how to find at build-time things that will be installed there.
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support misc
rpath-link = \
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
else # build-static
+41
View File
@@ -5,6 +5,47 @@ 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.41.1
Deprecated and removed features, and other changes affecting compatibility:
* The glibc.rtld.execstack now supports a compatibility mode to allow
programs that require an executable stack through dynamic loaded
shared libraries.
The following bugs were resolved with this release:
[19341] ctype: Fallback initialization of TLS using relocations
[29190] Fix handling of symbol versions which hash to zero
[31943] _dl_find_object can fail if ld.so contains gaps between load segments
[32483] ctype macros segfault in multithreaded programs with multiple libc.so
[32269] RISC-V IFUNC resolver cannot access gp pointer
[32626] math: math: log10p1f is not correctly rounded
[32627] math: math: sinhf is not correctly rounded
[32630] math: math: tanf is not correctly rounded for all rounding
modes
[32653] dynamic-link: Review options for improving both security and
backwards compatibility of glibc 2.41 dlopen / execstack handling
[32781] Linux: Remove attribute access from sched_getattr
[32782] nptl: Race conditions in pthread cancellation causing crash
[32786] nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions
[32810] Crash on x86-64 if XSAVEC disable via tunable
[32882] tst-audit10 fails with SIGILL on CPUs without AVX
[32897] dynamic-link: pthread_getattr_np fails when executable stack
tunable is set
[32981] ports: elf/tst-execstack-prog-static-tunable fails on
sparc64-linux-gnu
[32987] elf: Fix subprocess status handling for tst-dlopen-sgid
[32994] stdlib: resolve a double lock init issue after fork
[33164] iconv -o should not create executable files
[33185] Fix double-free after allocation failure in regcomp
[33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables
[33245] nptl: nptl: error in internal cancellation syscall handling
[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.41
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)
-25
View File
@@ -1,25 +0,0 @@
assert: Buffer overflow when printing assertion failure message
When the assert() function fails, it does not allocate enough space for the
assertion failure message string and size information, which may lead to a
buffer overflow if the message string size aligns to page size.
This bug can be triggered when an assertion in a program fails. The assertion
failure message is allocated to allow developers to see this failure in core
dumps and it typically includes, in addition to the invariant assertion
string and function name, the name of the program. If the name of the failing
program is user controlled, for example on a local system, this could allow an
attacker to control the assertion failure to trigger this buffer overflow.
The only viable vector for exploitation of this bug is local, if a setuid
program exists that has an existing bug that results in an assertion failure.
No such program has been discovered at the time of publishing this advisory,
but the presence of custom setuid programs, although strongly discouraged as a
security practice, cannot be discounted.
CVE-Id: CVE-2025-0395
Public-Date: 2025-01-22
Vulnerable-Commit: f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 (2.13-175)
Fix-Commit: 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578 (2.41)
Fix-Commit: 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c (2.40-66)
Reported-By: Qualys Security Advisory
-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
@@ -39,6 +39,7 @@ tests := \
test-assert-perr \
tst-assert-c++ \
tst-assert-g++ \
tst-assert-sa-2025-0001 \
# tests
ifeq ($(have-cxx-thread_local),yes)
+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
+1
View File
@@ -53,6 +53,7 @@ c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@
enable-werror = @enable_werror@
have-z-execstack = @libc_cv_z_execstack@
have-no-error-execstack = @libc_cv_no_error_execstack@
have-protected-data = @libc_cv_protected_data@
have-insert = @libc_cv_insert@
have-glob-dat-reloc = @libc_cv_has_glob_dat@
Vendored
+200
View File
@@ -659,6 +659,7 @@ libc_cv_has_glob_dat
libc_cv_fpie
libc_cv_test_static_pie
libc_cv_z_execstack
libc_cv_no_error_execstack
ASFLAGS_config
libc_cv_cc_with_libunwind
libc_cv_insert
@@ -4928,6 +4929,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
@@ -7114,6 +7118,40 @@ if test $libc_cv_as_noexecstack = yes; then
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-error-execstack" >&5
printf %s "checking for linker that supports --no-error-execstack... " >&6; }
libc_linker_feature=no
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
-Wl,--no-error-execstack -nostdlib -nostartfiles
-fPIC -shared -o conftest.so conftest.c
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
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,--no-error-execstack -nostdlib \
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
| grep "warning: --no-error-execstack ignored" > /dev/null 2>&1; then
true
else
libc_linker_feature=yes
fi
fi
rm -f conftest*
if test $libc_linker_feature = yes; then
libc_cv_no_error_execstack=yes
else
libc_cv_no_error_execstack=no
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
printf "%s\n" "$libc_linker_feature" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z execstack" >&5
printf %s "checking for linker that supports -z execstack... " >&6; }
libc_linker_feature=no
@@ -7452,6 +7490,41 @@ rm -f conftest*
config_vars="$config_vars
have-test-mtls-descriptor = $libc_cv_test_mtls_descriptor"
cat > conftest.c <<EOF
$conftest_code
EOF
saved_CC="$CC"
CC="$TEST_CC"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for traditional tls support in testing" >&5
printf %s "checking for traditional tls support in testing... " >&6; }
if test ${libc_cv_test_mtls_traditional+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) 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 ;;
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; }
CC="$saved_CC"
rm -f conftest*
config_vars="$config_vars
have-test-mtls-traditional = $libc_cv_test_mtls_traditional"
conftest_code="
void __foo (void)
{
@@ -8643,6 +8716,35 @@ if test $libc_cv_builtin_trap = yes; then
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports __attribute__ ((aligned (65536)))" >&5
printf %s "checking whether the compiler supports __attribute__ ((aligned (65536)))... " >&6; }
if test ${libc_cv_aligned_65536+y}
then :
printf %s "(cached) " >&6
else case e in #(
e)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
char bss0xb5dce8 __attribute__ ((aligned (65536)));
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
libc_cv_aligned_65536=yes
else case e in #(
e) libc_cv_aligned_65536=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aligned_65536" >&5
printf "%s\n" "$libc_cv_aligned_65536" >&6; }
config_vars="$config_vars
aligned-65536 = $libc_cv_aligned_65536"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -8908,6 +9010,104 @@ printf "%s\n" "$libc_linker_feature" >&6; }
config_vars="$config_vars
load-address-ldflag = $libc_cv_load_address_ldflag"
# Check if compilers support GCS in branch protection:
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5
printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; }
if test ${libc_cv_cc_gcs+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
{ { 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_cc_gcs=yes
else case e in #(
e) libc_cv_cc_gcs=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5
printf "%s\n" "$libc_cv_cc_gcs" >&6; }
if test "$TEST_CC" = "$CC"; then
libc_cv_test_cc_gcs=$libc_cv_cc_gcs
else
saved_CC="$CC"
CC="$TEST_CC"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5
printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; }
if test ${libc_cv_test_cc_gcs+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
{ { 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_cc_gcs=yes
else case e in #(
e) libc_cv_test_cc_gcs=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5
printf "%s\n" "$libc_cv_test_cc_gcs" >&6; }
CC="$saved_CC"
fi
config_vars="$config_vars
have-cc-gcs = $libc_cv_cc_gcs"
config_vars="$config_vars
have-test-cc-gcs = $libc_cv_test_cc_gcs"
# Check if linker supports GCS marking
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5
printf %s "checking for linker that supports -z gcs=always... " >&6; }
libc_linker_feature=no
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
-Wl,-z,gcs=always -nostdlib -nostartfiles
-fPIC -shared -o conftest.so conftest.c
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
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
| grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then
true
else
libc_linker_feature=yes
fi
fi
rm -f conftest*
if test $libc_linker_feature = yes; then
libc_cv_ld_gcs=yes
else
libc_cv_ld_gcs=no
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
printf "%s\n" "$libc_linker_feature" >&6; }
config_vars="$config_vars
have-ld-gcs = $libc_cv_ld_gcs"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
printf %s "checking if we can build programs as PIE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+45
View File
@@ -483,6 +483,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])
@@ -1318,6 +1321,10 @@ if test $libc_cv_as_noexecstack = yes; then
fi
AC_SUBST(ASFLAGS_config)
LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,--no-error-execstack],
[libc_cv_no_error_execstack=yes], [libc_cv_no_error_execstack=no])
AC_SUBST(libc_cv_no_error_execstack)
LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
[libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
AC_SUBST(libc_cv_z_execstack)
@@ -1396,6 +1403,16 @@ LIBC_TRY_TEST_CC_COMMAND([for tls descriptor support],
LIBC_CONFIG_VAR([have-test-mtls-descriptor],
[$libc_cv_test_mtls_descriptor])
dnl Check if TEST_CC support traditional tls.
LIBC_TRY_TEST_CC_COMMAND([for traditional tls support],
[$conftest_code],
[-fPIC -mtls-dialect=$mtls_traditional -nostdlib -nostartfiles -shared],
libc_cv_test_mtls_traditional,
[libc_cv_test_mtls_traditional=$mtls_traditional],
[libc_cv_test_mtls_traditional=no])
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
@@ -1820,6 +1837,17 @@ if test $libc_cv_builtin_trap = yes; then
AC_DEFINE([HAVE_BUILTIN_TRAP])
fi
dnl Check if
AC_CACHE_CHECK([whether the compiler supports __attribute__ ((aligned (65536)))],
libc_cv_aligned_65536, [
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
char bss[0xb5dce8] __attribute__ ((aligned (65536)));
])],
[libc_cv_aligned_65536=yes],
[libc_cv_aligned_65536=no])
])
LIBC_CONFIG_VAR([aligned-65536], [$libc_cv_aligned_65536])
dnl C++ feature tests.
AC_LANG_PUSH([C++])
@@ -1992,6 +2020,23 @@ LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
[libc_cv_load_address_ldflag=])
LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
# Check if compilers support GCS in branch protection:
LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -mbranch-protection=gcs],
[-Werror -mbranch-protection=gcs],
libc_cv_cc_gcs,
[libc_cv_cc_gcs=yes],
[libc_cv_cc_gcs=no],
libc_cv_test_cc_gcs,
[libc_cv_test_cc_gcs=yes],
[libc_cv_test_cc_gcs=no])
LIBC_CONFIG_VAR([have-cc-gcs], [$libc_cv_cc_gcs])
LIBC_CONFIG_VAR([have-test-cc-gcs], [$libc_cv_test_cc_gcs])
# Check if linker supports GCS marking
LIBC_LINKER_FEATURE([-z gcs=always], [-Wl,-z,gcs=always],
[libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no])
LIBC_CONFIG_VAR([have-ld-gcs], [$libc_cv_ld_gcs])
AC_MSG_CHECKING(if we can build programs as PIE)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
# error PIE is not supported
+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-2025 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>
+92 -2
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,12 @@ dl-routines = \
dl-close \
dl-debug \
dl-debug-symbols \
dl-debug_state \
dl-deps \
dl-exception \
dl-execstack \
dl-execstack-tunable \
dl-find_object \
dl-fini \
dl-init \
dl-load \
@@ -266,6 +268,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 \
@@ -379,6 +382,7 @@ tests += \
tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit-tlsdesc-dlopen2 \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@@ -415,7 +419,10 @@ 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 \
@@ -490,6 +497,7 @@ tests += \
tst-tls21 \
tst-tls22 \
tst-tls22-gnu2 \
tst-tls23 \
tst-tlsalign \
tst-tlsalign-extern \
tst-tlsgap \
@@ -497,6 +505,7 @@ tests += \
tst-unique2 \
tst-unwind-ctor \
tst-unwind-main \
tst-version-hash-zero \
unload3 \
unload4 \
unload5 \
@@ -532,6 +541,8 @@ tests-internal += \
tst-dl_find_object-threads \
tst-dlmopen2 \
tst-hash-collision3 \
tst-link-map-contiguous-ldso \
tst-link-map-contiguous-libc \
tst-ptrguard1 \
tst-stackguard1 \
tst-tls-surplus \
@@ -543,6 +554,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 \
@@ -567,9 +582,11 @@ tests-execstack-yes = \
tst-execstack \
tst-execstack-needed \
tst-execstack-prog \
tst-execstack-tunable \
# tests-execstack-yes
tests-execstack-static-yes = \
tst-execstack-prog-static
tst-execstack-prog-static \
tst-execstack-prog-static-tunable \
# tests-execstack-static-yes
ifeq (yes,$(run-built-tests))
tests-execstack-special-yes = \
@@ -863,6 +880,7 @@ modules-names += \
tst-auditmanymod8 \
tst-auditmanymod9 \
tst-auditmod-tlsdesc \
tst-auditmod-tlsdesc2 \
tst-auditmod1 \
tst-auditmod11 \
tst-auditmod12 \
@@ -905,6 +923,9 @@ modules-names += \
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 \
@@ -1003,6 +1024,7 @@ modules-names += \
tst-tls22-mod1-gnu2 \
tst-tls22-mod2 \
tst-tls22-mod2-gnu2 \
tst-tls23-mod \
tst-tlsalign-lib \
tst-tlsgap-mod0 \
tst-tlsgap-mod1 \
@@ -1033,6 +1055,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 \
@@ -1144,6 +1169,10 @@ tests-pie += \
tst-pie1 \
tst-pie2 \
# tests-pie
ifeq (yes,$(aligned-65536))
tests += tst-pie-bss
tests-pie += tst-pie-bss
endif
ifneq (,$(load-address-ldflag))
tests += \
tst-pie-address \
@@ -1159,6 +1188,10 @@ tests += \
tests-static += \
tst-pie-address-static \
# tests-static
ifeq (yes,$(aligned-65536))
tests += tst-pie-bss-static
tests-static += tst-pie-bss-static
endif
LDFLAGS-tst-pie-address-static += \
$(load-address-ldflag)=$(pde-load-address)
endif
@@ -1988,6 +2021,9 @@ $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
CPPFLAGS-tst-execstack.c += -DUSE_PTHREADS=0
LDFLAGS-tst-execstack = -Wl,-z,noexecstack
LDFLAGS-tst-execstack-mod.so = -Wl,-z,execstack
ifeq ($(have-no-error-execstack),yes)
LDFLAGS-tst-execstack-mod.so += -Wl,--no-error-execstack
endif
$(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
@@ -1996,7 +2032,18 @@ LDFLAGS-tst-execstack-prog = -Wl,-z,execstack
CFLAGS-tst-execstack-prog.c += -Wno-trampolines
CFLAGS-tst-execstack-mod.c += -Wno-trampolines
# It expects loading a module with executable stack to work.
CFLAGS-tst-execstack-tunable.c += -DUSE_PTHREADS=0 -DDEFAULT_RWX_STACK=1
$(objpfx)tst-execstack-tunable.out: $(objpfx)tst-execstack-mod.so
tst-execstack-tunable-ENV = GLIBC_TUNABLES=glibc.rtld.execstack=2
LDFLAGS-tst-execstack-prog-static-tunable = -Wl,-z,noexecstack
tst-execstack-prog-static-tunable-ENV = GLIBC_TUNABLES=glibc.rtld.execstack=2
LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack
ifeq ($(have-no-error-execstack),yes)
LDFLAGS-tst-execstack-prog-static += -Wl,--no-error-execstack
endif
CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines
ifeq (yes,$(build-hardcoded-path-in-tests))
@@ -2074,6 +2121,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
CFLAGS-tst-pie1.c += $(pie-ccflag)
CFLAGS-tst-pie2.c += $(pie-ccflag)
CFLAGS-tst-pie-bss.c += $(pie-ccflag)
CFLAGS-tst-pie-address.c += $(pie-ccflag)
$(objpfx)tst-piemod1.so: $(libsupport)
@@ -2206,6 +2254,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
@@ -3189,6 +3244,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 \
@@ -3354,6 +3412,13 @@ tst-tls22-mod1-gnu2.so-no-z-defs = yes
tst-tls22-mod2.so-no-z-defs = yes
tst-tls22-mod2-gnu2.so-no-z-defs = yes
$(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
ifeq ($(have-test-cc-cflags-fsemantic-interposition),yes)
# Compiler may default to -fno-semantic-interposition. These modules
# must be compiled with -fsemantic-interposition.
@@ -3392,3 +3457,28 @@ $(objpfx)tst-nolink-libc-2: $(objpfx)tst-nolink-libc.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-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so
$(objpfx)tst-version-hash-zero.out: \
$(objpfx)tst-version-hash-zero-mod.so \
$(objpfx)tst-version-hash-zero-refmod.so
LDFLAGS-tst-version-hash-zero-mod.so = \
-Wl,--version-script=tst-version-hash-zero-mod.map
# The run-time test module tst-version-hash-zero-refmod.so is linked
# to a stub module, tst-version-hash-zero-linkmod.so, to produce an
# expected relocation error.
$(objpfx)tst-version-hash-zero-refmod.so: \
$(objpfx)tst-version-hash-zero-linkmod.so
LDFLAGS-tst-version-hash-zero-linkmod.so = \
-Wl,--version-script=tst-version-hash-zero-linkmod.map \
-Wl,--soname=tst-version-hash-zero-mod.so
$(objpfx)tst-version-hash-zero-refmod.so: \
$(objpfx)tst-version-hash-zero-linkmod.so
tst-version-hash-zero-refmod.so-no-z-defs = yes
$(objpfx)tst-dlopen-constructor-null: \
$(objpfx)tst-dlopen-constructor-null-mod1.so \
$(objpfx)tst-dlopen-constructor-null-mod2.so
$(objpfx)tst-dlopen-constructor-null-mod2.so: \
$(objpfx)tst-dlopen-constructor-null-mod1.so
+2 -4
View File
@@ -433,8 +433,7 @@ _dl_close_worker (struct link_map *map, bool force)
/* 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)
@@ -726,8 +725,7 @@ _dl_close_worker (struct link_map *map, bool force)
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
/* Notify the debugger those objects are finalized and gone. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
_dl_debug_change_state (r, RT_CONSISTENT);
LIBC_PROBE (unmap_complete, 2, nsid, r);
#ifdef SHARED
+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)
+39
View File
@@ -0,0 +1,39 @@
/* Stack executability handling for GNU dynamic linker.
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 <ldsodefs.h>
#include <dl-tunables.h>
void
_dl_handle_execstack_tunable (void)
{
switch (TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL))
{
case stack_tunable_mode_disable:
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X))
_dl_fatal_printf (
"Fatal glibc error: executable stack is not allowed\n");
break;
case stack_tunable_mode_force:
if (_dl_make_stack_executable (__libc_stack_end) != 0)
_dl_fatal_printf (
"Fatal glibc error: cannot enable executable stack as tunable requires");
break;
}
}
+1 -1
View File
@@ -23,7 +23,7 @@
so as to mprotect it. */
int
_dl_make_stack_executable (void **stack_endp)
_dl_make_stack_executable (const void *stack_endp)
{
return ENOSYS;
}
+47 -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,18 @@ _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 && is_rtld_link_map (l))
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)
{
@@ -765,7 +781,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)
+3 -4
View File
@@ -921,8 +921,7 @@ _dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l)
/* 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 ();
_dl_debug_change_state (r, RT_ADD);
LIBC_PROBE (map_start, 2, nsid, r);
}
else
@@ -945,7 +944,7 @@ struct link_map *
_dl_map_object_from_fd (const char *name, const char *origname, int fd,
struct filebuf *fbp, char *realname,
struct link_map *loader, int l_type, int mode,
void **stack_endp, Lmid_t nsid)
const void *stack_endp, Lmid_t nsid)
{
struct link_map *l = NULL;
const ElfW(Ehdr) *header;
@@ -2180,7 +2179,7 @@ _dl_map_object (struct link_map *loader, const char *name,
void *stack_end = __libc_stack_end;
return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader,
type, mode, &stack_end, nsid);
type, mode, stack_end, nsid);
}
struct add_path_state
+16 -6
View File
@@ -100,12 +100,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
+12 -3
View File
@@ -594,6 +594,16 @@ dl_open_worker_begin (void *a)
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
add_to_global_update (new);
/* 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;
}
@@ -771,8 +781,7 @@ dl_open_worker (void *a)
#ifdef SHARED
bool was_not_consistent = r->r_state != RT_CONSISTENT;
#endif
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
_dl_debug_change_state (r, RT_CONSISTENT);
LIBC_PROBE (map_complete, 3, nsid, r, args->map);
#ifdef SHARED
@@ -841,7 +850,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
+2 -1
View File
@@ -51,7 +51,8 @@ _dl_relocate_static_pie (void)
switch (ph->p_type)
{
case PT_LOAD:
if (ph->p_offset == 0)
/* Skip the empty PT_LOAD segment at offset 0. */
if (ph->p_filesz != 0 && ph->p_offset == 0)
file_p_vaddr = ph->p_vaddr;
break;
case PT_DYNAMIC:
+1 -3
View File
@@ -332,9 +332,7 @@ _dl_non_dynamic_init (void)
break;
}
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
&& TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
_dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n");
_dl_handle_execstack_tunable ();
call_function_static_weak (_dl_find_object_init);
+7
View File
@@ -560,6 +560,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
{
+1 -1
View File
@@ -138,7 +138,7 @@ glibc {
execstack {
type: INT_32
minval: 0
maxval: 1
maxval: 2
default: 1
}
}
+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
+63 -34
View File
@@ -1242,6 +1242,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;
_dl_rtld_map.l_phdr = rtld_phdr;
_dl_rtld_map.l_phnum = rtld_ehdr->e_phnum;
_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 (_dl_rtld_map.l_contiguous && expected_load_address != 0
&& expected_load_address != mapstart)
_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)
{
_dl_rtld_map.l_relro_addr = rtld_phdr[cnt].p_vaddr;
_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
@@ -1626,9 +1680,9 @@ dl_main (const ElfW(Phdr) *phdr,
bool has_interp = rtld_setup_main_map (main_map);
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
&& TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
_dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n");
/* Handle this after PT_GNU_STACK parse, because it updates dl_stack_flags
if required. */
_dl_handle_execstack_tunable ();
/* If the current libname is different from the SONAME, add the
latter as well. */
@@ -1710,33 +1764,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;
_dl_rtld_map.l_phdr = rtld_phdr;
_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)
{
_dl_rtld_map.l_relro_addr = rtld_phdr[cnt].p_vaddr;
_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 (_dl_rtld_map.l_tls_blocksize != 0)
@@ -1783,8 +1811,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
@@ -2319,6 +2346,9 @@ dl_main (const ElfW(Phdr) *phdr,
__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. */
@@ -2339,8 +2369,7 @@ dl_main (const ElfW(Phdr) *phdr,
/* 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. */
+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>
+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;
+55
View File
@@ -0,0 +1,55 @@
/* Module calling dlopen (NULL, RTLD_LAZY) to obtain the global scope.
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int mod1_status;
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlopen-constructor-null-mod1.so constructor");
void *handle = dlopen (NULL, RTLD_LAZY);
if (handle == NULL)
{
printf ("error: %s\n", dlerror ());
exit (1);
}
puts ("info: dlopen returned");
if (dlsym (handle, "malloc") != malloc)
{
puts ("error: dlsym did not produce expected result");
exit (1);
}
dlclose (handle);
/* Check that the second module's constructor has not executed. */
if (getenv ("mod2_status") != NULL)
{
printf ("error: mod2_status environment variable set: %s\n",
getenv ("mod2_status"));
exit (1);
}
/* Communicate to the second module that the constructor executed. */
mod1_status = 1;
}
+37
View File
@@ -0,0 +1,37 @@
/* Module whose constructor should not be invoked by dlopen (NULL, RTLD_LAZY).
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
extern int mod1_status;
int mod2_status;
static void __attribute__ ((constructor))
init (void)
{
printf ("info: tst-dlopen-constructor-null-mod2.so constructor"
" (mod1_status=%d)", mod1_status);
if (!(mod1_status == 1 && mod2_status == 0))
{
puts ("error: mod1_status == 1 && mod2_status == 0 expected");
exit (1);
}
setenv ("mod2_status", "constructed", 1);
mod2_status = 1;
}
+38
View File
@@ -0,0 +1,38 @@
/* Verify that dlopen (NULL, RTLD_LAZY) does not complete initialization.
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This test mimics what the glvndSetupPthreads function in libglvnd
does. */
#include <stdlib.h>
#include <support/check.h>
/* Defined and initialized in the shared objects. */
extern int mod1_status;
extern int mod2_status;
static int
do_test (void)
{
TEST_COMPARE (mod1_status, 1);
TEST_COMPARE (mod2_status, 1);
TEST_COMPARE_STRING (getenv ("mod2_status"), "constructed");
return 0;
}
#include <support/test-driver.c>
+1
View File
@@ -0,0 +1 @@
/* Opening this object should not succeed. */
+106
View File
@@ -0,0 +1,106 @@
/* Test case for ignored LD_LIBRARY_PATH in static startug (bug 32976).
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <gnu/lib-names.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <sys/wait.h>
#include <unistd.h>
/* This is the name of our test object. Use a custom module for
testing, so that this object does not get picked up from the system
path. */
static const char dso_name[] = "tst-dlopen-sgid-mod.so";
/* Used to mark the recursive invocation. */
static const char magic_argument[] = "run-actual-test";
static int
do_test (void)
{
/* Pathname of the directory that receives the shared objects this
test attempts to load. */
char *libdir = support_create_temp_directory ("tst-dlopen-sgid-");
/* This is supposed to be ignored and stripped. */
TEST_COMPARE (setenv ("LD_LIBRARY_PATH", libdir, 1), 0);
/* Copy of libc.so.6. */
{
char *from = xasprintf ("%s/%s", support_objdir_root, LIBC_SO);
char *to = xasprintf ("%s/%s", libdir, LIBC_SO);
add_temp_file (to);
support_copy_file (from, to);
free (to);
free (from);
}
/* Copy of the test object. */
{
char *from = xasprintf ("%s/elf/%s", support_objdir_root, dso_name);
char *to = xasprintf ("%s/%s", libdir, dso_name);
add_temp_file (to);
support_copy_file (from, to);
free (to);
free (from);
}
free (libdir);
support_capture_subprogram_self_sgid (magic_argument);
return 0;
}
static void
alternative_main (int argc, char **argv)
{
if (argc == 2 && strcmp (argv[1], magic_argument) == 0)
{
if (getgid () == getegid ())
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
/* Should be removed due to SGID. */
TEST_COMPARE_STRING (getenv ("LD_LIBRARY_PATH"), NULL);
TEST_VERIFY (dlopen (dso_name, RTLD_NOW) == NULL);
{
const char *message = dlerror ();
TEST_COMPARE_STRING (message,
"tst-dlopen-sgid-mod.so:"
" cannot open shared object file:"
" No such file or directory");
}
support_record_failure_barrier ();
exit (EXIT_SUCCESS);
}
}
#define PREPARE alternative_main
#include <support/test-driver.c>
+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;
}
+1
View File
@@ -0,0 +1 @@
#include <tst-execstack-prog-static.c>
+1
View File
@@ -0,0 +1 @@
#include <tst-execstack.c>
+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>
+19
View File
@@ -0,0 +1,19 @@
/* Test static PIE with an empty PT_LOAD segment at offset 0.
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-pie-bss.c"
+30
View File
@@ -0,0 +1,30 @@
/* Test PIE with an empty PT_LOAD segment at offset 0.
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 <stdio.h>
char bss[0xb5dce8] __attribute__ ((aligned (65536)));
static int
do_test (void)
{
printf ("Hello\n");
return 0;
}
#include <support/test-driver.c>
+1 -1
View File
@@ -13,6 +13,6 @@ glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0x[f]+)
glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
glibc.rtld.enable_secure: 0 (min: 0, max: 1)
glibc.rtld.execstack: 1 (min: 0, max: 1)
glibc.rtld.execstack: 1 (min: 0, max: 2)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
+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>
@@ -1,5 +1,5 @@
/* x86-64 PLT trampoline register save macros.
Copyright (C) 2024-2025 Free Software Foundation, Inc.
/* 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
@@ -16,19 +16,25 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef DL_STACK_ALIGNMENT
/* Due to GCC bug:
#include <stdint.h>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
struct tls
{
int64_t a, b, c, d;
};
__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
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
/* 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)
#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>
+2 -1
View File
@@ -138,7 +138,8 @@ $(objpfx)test-iconvconfig.out: $(objpfx)iconvconfig
rm -f $$tmp) > $@; \
$(evaluate-test)
$(objpfx)tst-iconv_prog.out: tst-iconv_prog.sh $(objpfx)iconv_prog
$(objpfx)tst-iconv_prog.out: tst-iconv_prog.sh $(objpfx)iconv_prog \
$(gen-locales)
$(BASH) $< $(common-objdir) '$(test-wrapper-env)' \
'$(run-program-env)' > $@; \
$(evaluate-test)
+2 -2
View File
@@ -436,7 +436,7 @@ input_error (const char *path)
static void
open_output_direct (void)
{
output_fd = open64 (output_file, O_WRONLY | O_CREAT | O_TRUNC, 0777);
output_fd = open64 (output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output_fd < 0)
output_error ();
}
@@ -457,7 +457,7 @@ prepare_output_file (char **argv)
else
{
/* If iconv creates the output file, no overlap is possible. */
output_fd = open64 (output_file, O_WRONLY | O_CREAT | O_EXCL, 0777);
output_fd = open64 (output_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (output_fd >= 0)
output_buffer_size = copy_buffer_size;
else
+4 -2
View File
@@ -144,8 +144,10 @@
if (irreversible == NULL) \
{ \
/* This means we are in call from __gconv_transliterate. In this \
case we are not doing any error recovery ourselves. */ \
result = __gconv_mark_illegal_input (step_data); \
case we are not doing any error recovery ourselves. Do not create \
a persistent error state. If __gconv_transliterate exhausts all \
alternatives, it will call __gconv_mark_illegal_input itself. */ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
\
+4
View File
@@ -75,6 +75,10 @@ run_iconv () {
}
check_out_expected () {
if test -x "$tmp/out" ; then
echo "error: iconv output file is executable"
failure=true
fi
if ! cmp -s "$tmp/out" "$tmp/expected" ; then
echo "error: iconv output difference" >&$logfd
echo "*** expected ***" >&$logfd
+20 -10
View File
@@ -27,10 +27,10 @@ LIBPATH=$codir:$codir/iconvdata
# How the start the iconv(1) program. $from is not defined/expanded yet.
ICONV='
$test_wrapper_env $run_program_env
$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so
$codir/iconv/iconv_prog
'
ICONV="$test_wrapper_env $run_program_env $ICONV"
TIMEOUTFACTOR=${TIMEOUTFACTOR:-1}
@@ -218,6 +218,7 @@ testarray=(
"\x00\x00;;INVALID;UTF-8;1"
"\x00\x00;;UTF-8;INVALID;1"
"\xc3\xa9;;UTF-8;ASCII//TRANSLIT;0"
"X\xc2\xbdY;;UTF-8;ASCII//TRANSLIT;0"
)
# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret
@@ -278,12 +279,21 @@ check_errtest_result ()
fi
}
for testcommand in "${testarray[@]}"; do
twobyte="$(echo "$testcommand" | cut -d";" -f 1)"
c="$(echo "$testcommand" | cut -d";" -f 2)"
from="$(echo "$testcommand" | cut -d";" -f 3)"
to="$(echo "$testcommand" | cut -d";" -f 4)"
eret="$(echo "$testcommand" | cut -d";" -f 5)"
execute_test
check_errtest_result
done
run_test_array ()
{
for testcommand in "${testarray[@]}"; do
twobyte="$(echo "$testcommand" | cut -d";" -f 1)"
c="$(echo "$testcommand" | cut -d";" -f 2)"
from="$(echo "$testcommand" | cut -d";" -f 3)"
to="$(echo "$testcommand" | cut -d";" -f 4)"
eret="$(echo "$testcommand" | cut -d";" -f 5)"
execute_test
check_errtest_result
done
}
echo "info: testing C locale"
run_test_array
echo "info: testing en_US.UTF-8 locale"
run_program_env="$run_program_env LC_ALL=en_US.UTF-8"
run_test_array
+6 -1
View File
@@ -76,7 +76,8 @@ 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 \
tst-jisx0213-progress
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -333,6 +334,10 @@ $(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)tst-jisx0213-progress.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; \
+3
View File
@@ -224,6 +224,9 @@
STANDARD_FROM_LOOP_ERR_HANDLER (1); \
} \
} \
else \
/* There was a pending character. Clear it. */ \
*statep = 0; \
\
put32 (outptr, ch); \
outptr += 4; \
+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) \
{ \
+3
View File
@@ -226,6 +226,9 @@
STANDARD_FROM_LOOP_ERR_HANDLER (1); \
} \
} \
else \
/* There was a pending character. Clear it. */ \
*statep = 0; \
\
put32 (outptr, ch); \
outptr += 4; \
+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>
+124
View File
@@ -0,0 +1,124 @@
/* Test JISX0213 combining character conversion progress (bug 34556, bug 34568).
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/>. */
/* Certain JISX0213 byte sequences map to a combining sequence, for
example U+304B (HIRAGANA LETTER KA) followed by U+309A (COMBINING
SEMI-VOICED SOUND MARK). When converting to internal encoding
(actually UTF-32) with a small output buffer, the first code point
is emitted and the second is queued in the converter state. This
test verifies that the queued code point is consumed exactly once
on retry, so that the conversion makes progress and terminates. */
#include <errno.h>
#include <iconv.h>
#include <stdio.h>
#include <string.h>
#include <support/check.h>
#include <support/support.h>
static void
test_one (const char *charset, const char *input, size_t outbufsize)
{
printf ("info: %s: testing output buffer size %zu\n", charset, outbufsize);
/* Expected UTF-32 output. */
static const wchar_t expected[] = { 0x304b, 0x309a, 'A' };
/* Use WCHAR_T encoding to avoid the BOM. */
iconv_t cd = iconv_open ("WCHAR_T", charset);
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
char result[64];
size_t result_len = 0;
char *inptr = (char *) input;
size_t inleft = strlen (input);
char outbuf[64];
int iterations = 0;
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;
TEST_VERIFY_EXIT (result_len + produced <= sizeof (result));
memcpy (result + result_len, outbuf, produced);
result_len += produced;
if (ret == (size_t) -1 && errno == E2BIG)
{
if (produced == 0 && inleft == inleft_before)
{
/* Output buffer too small for a single code point. */
TEST_VERIFY_EXIT (outbufsize < 4);
break;
}
/* Bound iterations to detect non-progress bugs. */
if (++iterations < 10)
continue;
else
{
FAIL ("%s: no progress", charset);
goto out;
}
}
if (ret == (size_t) -1)
FAIL_EXIT1 ("outbufsize %zu: iconv: %m", outbufsize);
break;
}
/* Flush pending converter state. */
{
char *outptr = outbuf;
size_t outleft = outbufsize;
size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
TEST_VERIFY (ret == 0);
size_t produced = outptr - outbuf;
memcpy (result + result_len, outbuf, produced);
result_len += produced;
}
if (outbufsize >= 4)
{
TEST_COMPARE (inleft, 0);
TEST_COMPARE_BLOB (result, result_len,
expected, sizeof (expected));
}
out:
TEST_VERIFY_EXIT (iconv_close (cd) == 0);
}
static int
do_test (void)
{
for (size_t outbufsize = 1; outbufsize <= 16; outbufsize++)
{
test_one ("EUC-JISX0213", "\244\367A", outbufsize);
test_one ("SHIFT_JISX0213", "\202\365A", outbufsize);
}
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
+2
View File
@@ -365,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"
+5
View File
@@ -70,6 +70,11 @@ libc_hidden_proto (__libc_res_nameinquery)
extern __typeof (__res_queriesmatch) __libc_res_queriesmatch;
libc_hidden_proto (__libc_res_queriesmatch)
extern const struct res_sym __p_class_syms[];
libresolv_hidden_proto (__p_class_syms)
extern const struct res_sym __p_type_syms[];
libresolv_hidden_proto (__p_type_syms)
/* Variant of res_hnok which operates on binary (but uncompressed) names. */
bool __res_binary_hnok (const unsigned char *dn) attribute_hidden;
+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)
+4
View File
@@ -18,6 +18,10 @@
#include <errno.h>
#include <fcntl.h>
#ifndef __O_CLOEXEC
# error __O_CLOEXEC not defined by fcntl.h/cloexec.h
#endif
/* Perform file control operations on FD. */
int
__fcntl (int fd, int cmd, ...)
+2
View File
@@ -83,6 +83,7 @@ tests = \
bug-ungetwc1 \
bug-ungetwc2 \
bug-wfflush \
bug-wgenops-bz33998 \
bug-wmemstream1 \
bug-wsetpos \
test-fmemopen \
@@ -104,6 +105,7 @@ tests = \
tst-fgetc-after-eof \
tst-fgetwc \
tst-fgetws \
tst-fopen-ccs-empty \
tst-fopenloc2 \
tst-fputws \
tst-freopen \
+54
View File
@@ -0,0 +1,54 @@
/* Regression test for ungetwc operating on byte stream (BZ #33998)
Copyright (C) 2026 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/>. */
#include "support/temp_file.h"
#include "support/xstdio.h"
#include "support/xunistd.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <wchar.h>
#include <support/check.h>
static int
do_test (void)
{
char *filename;
int fd = create_temp_file ("tst-bz33998-", &filename);
TEST_VERIFY (fd != -1);
xwrite (fd, "A", sizeof ("A")); // write "A\0" by design
xclose (fd);
FILE *fp = xfopen (filename, "r+");
TEST_COMPARE (getwc (fp), L'A');
/* If the bug is fixed, then ungetwc should not touch byte stream.
If the bug is not fixed, ungetwc firstly match last read char, L'A',
failed, then the pbackfail branch, matching last read char in byte
stream, that is, '\0' (initialized when setup wide stream). */
char *old_read_ptr = fp->_IO_read_ptr;
TEST_COMPARE (ungetwc (L'\0', fp), L'\0');
TEST_VERIFY (fp->_IO_read_ptr == old_read_ptr);
xfclose (fp);
free (filename);
return 0;
}
#include <support/test-driver.c>
+7 -5
View File
@@ -306,12 +306,14 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
*((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
strip (ccs, ccs);
if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
? upstr (ccs, cs + 5) : ccs) != 0)
/* After stripping, ccs[2] == '\0' means the charset name is empty.
This is not a valid charset and would cause problems downstream.
Reject it with EINVAL (BZ #34574, CVE-2026-18374). */
if (ccs[2] == '\0' || __wcsmbs_named_conv (&fcts, ccs) != 0)
{
/* Something went wrong, we cannot load the conversion modules.
This means we cannot proceed since the user explicitly asked
for these. */
/* Either the charset name is empty after strip(), or conversion
modules cannot be loaded. This means we cannot proceed since
the user explicitly asked for character conversion. */
(void) _IO_file_close_it (fp);
free (ccs);
__set_errno (EINVAL);

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