Compare commits

...
Author SHA1 Message Date
Adhemerval Zanella 1d8ed2067a 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-21 09:31:38 -03:00
Carlos O'Donell d210011f15 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:33:58 -05:00
Siddhesh Poyarekar 011293b4fd 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-16 11:45:49 +01:00
Sunil K Pandey 81e0072416 nptl: Optimize trylock for high cache contention workloads (BZ #33704)
Check lock availability before acquisition to reduce cache line
bouncing.  Significantly improves trylock throughput on multi-core
systems under heavy contention.

Tested on x86_64.

Fixes BZ #33704.

Co-authored-by: Alex M Wells <alex.m.wells@intel.com>
Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 63716823db)
2025-12-18 11:00:44 -08:00
H.J. Lu 68cca6e1e8 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-18 01:06:48 +01:00
Florian Weimer 1ec499b165 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 12:11:24 +02:00
Stefan Liebler 5f08d1df2c s390x: Fix segfault in wcsncmp [BZ #31934]
The z13/vector-optimized wcsncmp implementation segfaults if n=1
and there is only one character (equal on both strings) before
the page end.  Then it loads and compares one character and misses
to check n again.  The following load fails.

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

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

(cherry picked from commit 9b76514103)
2024-07-16 10:34:50 +02:00
H.J. Lu d0916db233 Force DT_RPATH for --enable-hardcoded-path-in-tests
On Fedora 40/x86-64, linker enables --enable-new-dtags by default which
generates DT_RUNPATH instead of DT_RPATH.  Unlike DT_RPATH, DT_RUNPATH
only applies to DT_NEEDED entries in the executable and doesn't applies
to DT_NEEDED entries in shared libraries which are loaded via DT_NEEDED
entries in the executable.  Some glibc tests have libstdc++.so.6 in
DT_NEEDED, which has libm.so.6 in DT_NEEDED.  When DT_RUNPATH is generated,
/lib64/libm.so.6 is loaded for such tests.  If the newly built glibc is
older than glibc 2.36, these tests fail with

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

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

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 2dcaf70643)
2024-05-10 05:46:28 -07:00
Florian Weimer 430e825909 elf: Disable some subtests of ifuncmain1, ifuncmain5 for !PIE
(cherry picked from commit 9cc9d61ee1)
2024-05-09 16:47:01 -07:00
Florian Weimer 1e398f406b nscd: Use time_t for return type of addgetnetgrentX
Using int may give false results for future dates (timeouts after the
year 2028).

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

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 4bbca1a446)
2024-05-03 09:22:44 +02:00
Florian Weimer 4d27d4b9a1 CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
This avoids potential memory corruption when the underlying NSS
callback function does not use the buffer space to store all strings
(e.g., for constant strings).

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

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

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

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

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

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

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 87801a8fd0)
2024-04-25 16:07:52 +02:00
Charles FolandAdhemerval Zanella ed4f16ff6b iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
(as specified by RFC 1922).  While the SOdesignation has the expected
bounds checks, neither SS2designation nor SS3designation have its;
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.

Checked on aarch64-linux-gnu.

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

(cherry picked from commit f9dc609e06)
2024-04-17 14:03:53 -03:00
Wilco Dijkstra 91ac82d0c6 aarch64: Use memcpy_simd as the default memcpy
Since __memcpy_simd is the fastest memcpy on almost all cores, replace
the generic memcpy with it.

(cherry picked from commit e6f3fe362f)
2024-04-09 18:52:29 +01:00
Andreas Schwab 4818620ee2 aarch64: correct CFI in rawmemchr (bug 31113)
The .cfi_return_column directive changes the return column for the whole
FDE range.  But the actual intent is to tell the unwinder that the value
in x30 (lr) now resides in x15 after the move, and that is expressed by
the .cfi_register directive.

(cherry picked from commit 3f79842788)
2024-04-09 18:43:49 +01:00
Wilco Dijkstra 062d8a648f AArch64: Improve strrchr
Use shrn for narrowing the mask which simplifies code and speeds up small
strings.  Unroll the first search loop to improve performance on large
strings.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 55599d4804)
2024-04-09 18:41:06 +01:00
Wilco Dijkstra 3527d31d0b AArch64: Optimize strnlen
Optimize strnlen using the shrn instruction and improve the main loop.
Small strings are around 10% faster, large strings are 40% faster on
modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit ad098893ba)
2024-04-09 18:40:41 +01:00
Wilco Dijkstra 12784e1d82 AArch64: Optimize strlen
Optimize strlen by unrolling the main loop.  Large strings are 64% faster on
modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 03c8ce5000)
2024-04-09 18:40:17 +01:00
Wilco Dijkstra b01d60fdef AArch64: Optimize strcpy
Unroll the main loop.  Large strings are around 20% faster on modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 349e48c01e)
2024-04-09 18:39:53 +01:00
Wilco Dijkstra 7d628ab7cf AArch64: Improve strchrnul
Unroll the main loop, which improves performance slightly.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 09ebd8549b)
2024-04-09 18:39:28 +01:00
Wilco Dijkstra a7eae18db2 AArch64: Optimize strchr
Simplify calculation of the mask using shrn.  Unroll the main loop.
Small strings are 20% faster on modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 51541a2297)
2024-04-09 18:38:42 +01:00
Wilco Dijkstra 97b1c803cb AArch64: Improve strlen_asimd
Use shrn for the mask, merge tst+bne into cbnz, and tweak code alignment.
Performance improves slightly as a result.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 1bbb1a2022)
2024-04-09 18:38:04 +01:00
Wilco Dijkstra 0604c9d255 AArch64: Optimize memrchr
Optimize the main loop - large strings are 43% faster on modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 0077624177)
2024-04-09 18:37:38 +01:00
Wilco Dijkstra 50ebfdfe8a AArch64: Optimize memchr
Optimize the main loop - large strings are 40% faster on modern CPUs.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit ce758d4f06)
2024-04-09 18:37:21 +01:00
Danila Kutenin fa9cd4fd3c aarch64: Optimize string functions with shrn instruction
We found that string functions were using AND+ADDP
to find the nibble/syndrome mask but there is an easier
opportunity through `SHRN dst.8b, src.8h, 4` (shift
right every 2 bytes by 4 and narrow to 1 byte) and has
same latency on all SIMD ARMv8 targets as ADDP. There
are also possible gaps for memcmp but that's for
another patch.

We see 10-20% savings for small-mid size cases (<=128)
which are primary cases for general workloads.

(cherry picked from commit 3c99806989)
2024-04-09 18:30:02 +01:00
Wilco Dijkstra ea547d896d AArch64: Optimize memcmp
Rewrite memcmp to improve performance. On small and medium inputs performance
is 10-20% better. Large inputs use a SIMD loop processing 64 bytes per
iteration, which is 30-50% faster depending on the size.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit b51eb35c57)
2024-04-09 18:28:20 +01:00
Wilco Dijkstra ce54f78828 AArch64: Improve strnlen performance
Optimize strnlen by avoiding UMINV which is slow on most cores. On Neoverse N1
large strings are 1.8x faster than the current version, and bench-strnlen is
50% faster overall. This version is MTE compatible.

Reviewed-by: Szabolcs Nagy  <szabolcs.nagy@arm.com>
(cherry picked from commit 252cad02d4)
2024-04-09 18:28:11 +01:00
Sunil K Pandey 3b8d158b38 x86_64: Optimize ffsll function code size.
Ffsll function randomly regress by ~20%, depending on how code gets
aligned in memory.  Ffsll function code size is 17 bytes.  Since default
function alignment is 16 bytes, it can load on 16, 32, 48 or 64 bytes
aligned memory.  When ffsll function load at 16, 32 or 64 bytes aligned
memory, entire code fits in single 64 bytes cache line.  When ffsll
function load at 48 bytes aligned memory, it splits in two cache line,
hence random regression.

Ffsll function size reduction from 17 bytes to 12 bytes ensures that it
will always fit in single 64 bytes cache line.

This patch fixes ffsll function random performance regression.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 9d94997b5f)
2024-01-31 18:56:23 -08:00
Noah Goldstein 1a200935e1 x86: Fix incorrect scope of setting shared_per_thread [BZ# 30745]
The:

```
    if (shared_per_thread > 0 && threads > 0)
      shared_per_thread /= threads;
```

Code was accidentally moved to inside the else scope.  This doesn't
match how it was previously (before af992e7abd).

This patch fixes that by putting the division after the `else` block.

(cherry picked from commit 084fb31bc2)
2023-09-11 22:47:08 -05:00
Noah Goldstein 6c8475a3f7 x86: Use 3/4*sizeof(per-thread-L3) as low bound for NT threshold.
On some machines we end up with incomplete cache information. This can
make the new calculation of `sizeof(total-L3)/custom-divisor` end up
lower than intended (and lower than the prior value). So reintroduce
the old bound as a lower bound to avoid potentially regressing code
where we don't have complete information to make the decision.
Reviewed-by: DJ Delorie <dj@redhat.com>

(cherry picked from commit 8b9a0af8ca)
2023-09-11 22:47:08 -05:00
Noah Goldstein 31b06441f9 x86: Fix slight bug in shared_per_thread cache size calculation.
After:
```
    commit af992e7abd
    Author: Noah Goldstein <goldstein.w.n@gmail.com>
    Date:   Wed Jun 7 13:18:01 2023 -0500

        x86: Increase `non_temporal_threshold` to roughly `sizeof_L3 / 4`
```

Split `shared` (cumulative cache size) from `shared_per_thread` (cache
size per socket), the `shared_per_thread` *can* be slightly off from
the previous calculation.

Previously we added `core` even if `threads_l2` was invalid, and only
used `threads_l2` to divide `core` if it was present. The changed
version only included `core` if `threads_l2` was valid.

This change restores the old behavior if `threads_l2` is invalid by
adding the entire value of `core`.
Reviewed-by: DJ Delorie <dj@redhat.com>

(cherry picked from commit 47f7472178)
2023-09-11 22:47:08 -05:00
Noah Goldstein 5e2d2d7cbd x86: Increase non_temporal_threshold to roughly sizeof_L3 / 4
Current `non_temporal_threshold` set to roughly '3/4 * sizeof_L3 /
ncores_per_socket'. This patch updates that value to roughly
'sizeof_L3 / 4`

The original value (specifically dividing the `ncores_per_socket`) was
done to limit the amount of other threads' data a `memcpy`/`memset`
could evict.

Dividing by 'ncores_per_socket', however leads to exceedingly low
non-temporal thresholds and leads to using non-temporal stores in
cases where REP MOVSB is multiple times faster.

Furthermore, non-temporal stores are written directly to main memory
so using it at a size much smaller than L3 can place soon to be
accessed data much further away than it otherwise could be. As well,
modern machines are able to detect streaming patterns (especially if
REP MOVSB is used) and provide LRU hints to the memory subsystem. This
in affect caps the total amount of eviction at 1/cache_associativity,
far below meaningfully thrashing the entire cache.

As best I can tell, the benchmarks that lead this small threshold
where done comparing non-temporal stores versus standard cacheable
stores. A better comparison (linked below) is to be REP MOVSB which,
on the measure systems, is nearly 2x faster than non-temporal stores
at the low-end of the previous threshold, and within 10% for over
100MB copies (well past even the current threshold). In cases with a
low number of threads competing for bandwidth, REP MOVSB is ~2x faster
up to `sizeof_L3`.

The divisor of `4` is a somewhat arbitrary value. From benchmarks it
seems Skylake and Icelake both prefer a divisor of `2`, but older CPUs
such as Broadwell prefer something closer to `8`. This patch is meant
to be followed up by another one to make the divisor cpu-specific, but
in the meantime (and for easier backporting), this patch settles on
`4` as a middle-ground.

Benchmarks comparing non-temporal stores, REP MOVSB, and cacheable
stores where done using:
https://github.com/goldsteinn/memcpy-nt-benchmarks

Sheets results (also available in pdf on the github):
https://docs.google.com/spreadsheets/d/e/2PACX-1vS183r0rW_jRX6tG_E90m9qVuFiMbRIJvi5VAE8yYOvEOIEEc3aSNuEsrFbuXw5c3nGboxMmrupZD7K/pubhtml
Reviewed-by: DJ Delorie <dj@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit af992e7abd)
2023-09-11 22:47:08 -05:00
Florian Weimer aef97dc952 debug: Mark libSegFault.so as NODELETE
The signal handler installed in the ELF constructor cannot easily
be removed again (because the program may have changed handlers
in the meantime).  Mark the object as NODELETE so that the registered
handler function is never unloaded.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 23ee92deea)
2023-07-21 16:39:46 +02:00
H.J. Lu eed27b3e46 Document BZ #20975 fix 2023-05-23 16:47:45 -07:00
H.J. Lu 24302748fc __check_pf: Add a cancellation cleanup handler [BZ #20975]
There are reports for hang in __check_pf:

https://github.com/JoeDog/siege/issues/4

It is reproducible only under specific configurations:

1. Large number of cores (>= 64) and large number of threads (> 3X of
the number of cores) with long lived socket connection.
2. Low power (frequency) mode.
3. Power management is enabled.

While holding lock, __check_pf calls make_request which calls __sendto
and __recvmsg.  Since __sendto and __recvmsg are cancellation points,
lock held by __check_pf won't be released and can cause deadlock when
thread cancellation happens in __sendto or __recvmsg.  Add a cancellation
cleanup handler for __check_pf to unlock the lock when cancelled by
another thread.  This fixes BZ #20975 and the siege hang issue.

(cherry picked from commit a443bd3fb2)
2023-05-23 16:06:42 -07:00
Noah Goldstein 017b9df5ea x86: Fix wcsnlen-avx2 page cross length comparison [BZ #29591]
Previous implementation was adjusting length (rsi) to match
bytes (eax), but since there is no bound to length this can cause
overflow.

Fix is to just convert the byte-count (eax) to length by dividing by
sizeof (wchar_t) before the comparison.

Full check passes on x86-64 and build succeeds w/ and w/o multiarch.

(cherry picked from commit b0969fa53a)
2022-11-24 15:12:44 -08:00
Aurelien Jarno 67e310afb9 x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations
The AVX2 strrchr and wcsrchr implementation uses the 'blsmsk'
instruction which belongs to the BMI1 CPU feature and the 'shrx'
instruction, which belongs to the BMI2 CPU feature.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Reviewed-by: Noah Goldstein  <goldstein.w.n@gmail.com>
(cherry picked from commit b80f16adbd)
2022-10-04 00:03:19 +02:00
Wangyang Guo ea326b2e98 nptl: Add backoff mechanism to spinlock loop
When mutiple threads waiting for lock at the same time, once lock owner
releases the lock, waiters will see lock available and all try to lock,
which may cause an expensive CAS storm.

Binary exponential backoff with random jitter is introduced. As try-lock
attempt increases, there is more likely that a larger number threads
compete for adaptive mutex lock, so increase wait time in exponential.
A random jitter is also added to avoid synchronous try-lock from other
threads.

v2: Remove read-check before try-lock for performance.

v3:
1. Restore read-check since it works well in some platform.
2. Make backoff arch dependent, and enable it for x86_64.
3. Limit max backoff to reduce latency in large critical section.

v4: Fix strict-prototypes error in sysdeps/nptl/pthread_mutex_backoff.h

v5: Commit log updated for regression in large critical section.

Result of pthread-mutex-locks bench

Test Platform: Xeon 8280L (2 socket, 112 CPUs in total)
First Row: thread number
First Col: critical section length
Values: backoff vs upstream, time based, low is better

non-critical-length: 1
	1	2	4	8	16	32	64	112	140
0	0.99	0.58	0.52	0.49	0.43	0.44	0.46	0.52	0.54
1	0.98	0.43	0.56	0.50	0.44	0.45	0.50	0.56	0.57
2	0.99	0.41	0.57	0.51	0.45	0.47	0.48	0.60	0.61
4	0.99	0.45	0.59	0.53	0.48	0.49	0.52	0.64	0.65
8	1.00	0.66	0.71	0.63	0.56	0.59	0.66	0.72	0.71
16	0.97	0.78	0.91	0.73	0.67	0.70	0.79	0.80	0.80
32	0.95	1.17	0.98	0.87	0.82	0.86	0.89	0.90	0.90
64	0.96	0.95	1.01	1.01	0.98	1.00	1.03	0.99	0.99
128	0.99	1.01	1.01	1.17	1.08	1.12	1.02	0.97	1.02

non-critical-length: 32
	1	2	4	8	16	32	64	112	140
0	1.03	0.97	0.75	0.65	0.58	0.58	0.56	0.70	0.70
1	0.94	0.95	0.76	0.65	0.58	0.58	0.61	0.71	0.72
2	0.97	0.96	0.77	0.66	0.58	0.59	0.62	0.74	0.74
4	0.99	0.96	0.78	0.66	0.60	0.61	0.66	0.76	0.77
8	0.99	0.99	0.84	0.70	0.64	0.66	0.71	0.80	0.80
16	0.98	0.97	0.95	0.76	0.70	0.73	0.81	0.85	0.84
32	1.04	1.12	1.04	0.89	0.82	0.86	0.93	0.91	0.91
64	0.99	1.15	1.07	1.00	0.99	1.01	1.05	0.99	0.99
128	1.00	1.21	1.20	1.22	1.25	1.31	1.12	1.10	0.99

non-critical-length: 128
	1	2	4	8	16	32	64	112	140
0	1.02	1.00	0.99	0.67	0.61	0.61	0.61	0.74	0.73
1	0.95	0.99	1.00	0.68	0.61	0.60	0.60	0.74	0.74
2	1.00	1.04	1.00	0.68	0.59	0.61	0.65	0.76	0.76
4	1.00	0.96	0.98	0.70	0.63	0.63	0.67	0.78	0.77
8	1.01	1.02	0.89	0.73	0.65	0.67	0.71	0.81	0.80
16	0.99	0.96	0.96	0.79	0.71	0.73	0.80	0.84	0.84
32	0.99	0.95	1.05	0.89	0.84	0.85	0.94	0.92	0.91
64	1.00	0.99	1.16	1.04	1.00	1.02	1.06	0.99	0.99
128	1.00	1.06	0.98	1.14	1.39	1.26	1.08	1.02	0.98

There is regression in large critical section. But adaptive mutex is
aimed for "quick" locks. Small critical section is more common when
users choose to use adaptive pthread_mutex.

Signed-off-by: Wangyang Guo <wangyang.guo@intel.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 8162147872)
2022-09-28 15:36:46 -07:00
Noah Goldstein 870d564e7c sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h
'get_fast_jitter' is meant to be used purely for performance
purposes. In all cases it's used it should be acceptable to get no
randomness (see default case). An example use case is in setting
jitter for retries between threads at a lock. There is a
performance benefit to having jitter, but only if the jitter can
be generated very quickly and ultimately there is no serious issue
if no jitter is generated.

The implementation generally uses 'HP_TIMING_NOW' iff it is
inlined (avoid any potential syscall paths).
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 911c63a51c)
2022-09-28 13:53:11 -07:00
Jangwoong Kim 8b9ad5ec93 nptl: Effectively skip CAS in spinlock loop
The commit:
"Add LLL_MUTEX_READ_LOCK [BZ #28537]"
SHA1: d672a98a1a

introduced LLL_MUTEX_READ_LOCK, to skip CAS in spinlock loop
if atomic load fails. But, "continue" inside of do-while loop
does not skip the evaluation of escape expression, thus CAS
is not skipped.

Replace do-while with while and skip LLL_MUTEX_TRYLOCK if
LLL_MUTEX_READ_LOCK fails.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6b8dbbd03a)
2022-09-28 13:52:51 -07:00
H.J. Lu 60b8295333 Move assignment out of the CAS condition
Update

commit 49302b8fdf
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Nov 11 06:54:01 2021 -0800

    Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]

    Replace boolean CAS with value CAS to avoid the extra load.

and

commit 0b82747dc4
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Nov 11 06:31:51 2021 -0800

    Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]

    Replace boolean CAS with value CAS to avoid the extra load.

by moving assignment out of the CAS condition.

(cherry picked from commit 120ac6d238)
2022-09-28 13:52:25 -07:00
H.J. Lu 8844d9b22d Add LLL_MUTEX_READ_LOCK [BZ #28537]
CAS instruction is expensive.  From the x86 CPU's point of view, getting
a cache line for writing is more expensive than reading.  See Appendix
A.2 Spinlock in:

https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/xeon-lock-scaling-analysis-paper.pdf

The full compare and swap will grab the cache line exclusive and cause
excessive cache line bouncing.

Add LLL_MUTEX_READ_LOCK to do an atomic load and skip CAS in spinlock
loop if compare may fail to reduce cache line bouncing on contended locks.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit d672a98a1a)
2022-09-28 13:47:29 -07:00
H.J. Lu 0ec276739a Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
Replace boolean CAS with value CAS to avoid the extra load.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 49302b8fdf)
2022-09-28 13:47:16 -07:00
H.J. Lu f5a70409db Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
Replace boolean CAS with value CAS to avoid the extra load.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 0b82747dc4)
2022-09-28 13:47:04 -07:00
Florian Weimer da7afc97ad elf: Call __libc_early_init for reused namespaces (bug 29528)
libc_map is never reset to NULL, neither during dlclose nor on a
dlopen call which reuses the namespace structure.  As a result, if a
namespace is reused, its libc is not initialized properly.  The most
visible result is a crash in the <ctype.h> functions.

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

(cherry picked from commit d0e357ff45)
2022-08-30 16:53:14 +02:00
Noah Goldstein 0631ff369d x86: Add missing IS_IN (libc) check to strncmp-sse4_2.S
Was missing to for the multiarch build rtld-strncmp-sse4_2.os was
being built and exporting symbols:

build/glibc/string/rtld-strncmp-sse4_2.os:
0000000000000000 T __strncmp_sse42

Introduced in:

commit 11ffcacb64
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Jun 21 12:10:50 2017 -0700

    x86-64: Implement strcmp family IFUNC selectors in C

(cherry picked from commit 96ac447d91)
2022-07-18 22:13:57 -07:00
Noah Goldstein fd5f93749d x86: Move mem{p}{mov|cpy}_{chk_}erms to its own file
The primary memmove_{impl}_unaligned_erms implementations don't
interact with this function. Putting them in same file both
wastes space and unnecessarily bloats a hot code section.

(cherry picked from commit 21925f6473)
2022-07-18 22:13:57 -07:00
Noah Goldstein 2abec4be8a x86: Move and slightly improve memset_erms
Implementation wise:
    1. Remove the VZEROUPPER as memset_{impl}_unaligned_erms does not
       use the L(stosb) label that was previously defined.

    2. Don't give the hotpath (fallthrough) to zero size.

Code positioning wise:

Move memset_{chk}_erms to its own file.  Leaving it in between the
memset_{impl}_unaligned both adds unnecessary complexity to the
file and wastes space in a relatively hot cache section.

(cherry picked from commit 4a3f29e7e4)
2022-07-18 22:13:57 -07:00
Noah Goldstein abbc822b05 x86: Add definition for __wmemset_chk AVX2 RTM in ifunc impl list
This was simply missing and meant we weren't testing it properly.

(cherry picked from commit 2a1099020c)
2022-07-18 22:13:57 -07:00
Noah Goldstein 44ec1e10ca x86: Put wcs{n}len-sse4.1 in the sse4.1 text section
Previously was missing but the two implementations shouldn't get in
the sse2 (generic) text section.

(cherry picked from commit afc6e4328f)
2022-07-18 22:13:57 -07:00
Noah Goldstein 17d929ab2e x86: Align entry for memrchr to 64-bytes.
The function was tuned around 64-byte entry alignment and performs
better for all sizes with it.

As well different code boths where explicitly written to touch the
minimum number of cache line i.e sizes <= 32 touch only the entry
cache line.

(cherry picked from commit 227afaa672)
2022-07-18 22:13:57 -07:00
Noah Goldstein e063a461a5 x86: Add BMI1/BMI2 checks for ISA_V3 check
BMI1/BMI2 are part of the ISA V3 requirements:
https://en.wikipedia.org/wiki/X86-64

And defined by GCC when building with `-march=x86-64-v3`

(cherry picked from commit 8da9f346cb)
2022-07-18 22:13:57 -07:00
Noah Goldstein 4e7f3b34a4 x86: Cleanup bounds checking in large memcpy case
1. Fix incorrect lower-bound threshold in L(large_memcpy_2x).
   Previously was using `__x86_rep_movsb_threshold` and should
   have been using `__x86_shared_non_temporal_threshold`.

2. Avoid reloading __x86_shared_non_temporal_threshold before
   the L(large_memcpy_4x) bounds check.

3. Document the second bounds check for L(large_memcpy_4x)
   more clearly.

(cherry picked from commit 89a25c6f64)
2022-07-18 22:13:57 -07:00
Noah Goldstein 2416fd15b9 x86: Add bounds x86_non_temporal_threshold
The lower-bound (16448) and upper-bound (SIZE_MAX / 16) are assumed
by memmove-vec-unaligned-erms.

The lower-bound is needed because memmove-vec-unaligned-erms unrolls
the loop aggressively in the L(large_memset_4x) case.

The upper-bound is needed because memmove-vec-unaligned-erms
right-shifts the value of `x86_non_temporal_threshold` by
LOG_4X_MEMCPY_THRESH (4) which without a bound may overflow.

The lack of lower-bound can be a correctness issue. The lack of
upper-bound cannot.

(cherry picked from commit b446822b6a)
2022-07-18 22:13:57 -07:00
Noah Goldstein cfa13a8205 x86: Add sse42 implementation to strcmp's ifunc
This has been missing since the the ifuncs where added.

The performance of SSE4.2 is preferable to to SSE2.

Measured on Tigerlake with N = 20 runs.
Geometric Mean of all benchmarks SSE4.2 / SSE2: 0.906

(cherry picked from commit ff439c4717)
2022-07-18 22:13:57 -07:00
Noah Goldstein 20bfbb3a57 x86: Fix misordered logic for setting rep_movsb_stop_threshold
Move the setting of `rep_movsb_stop_threshold` to after the tunables
have been collected so that the `rep_movsb_stop_threshold` (which
is used to redirect control flow to the non_temporal case) will
use any user value for `non_temporal_threshold` (set using
glibc.cpu.x86_non_temporal_threshold)

(cherry picked from commit 0355915514)
2022-07-18 22:13:57 -07:00
Noah Goldstein b64acbbe26 x86: Align varshift table to 32-bytes
This ensures the load will never split a cache line.

(cherry picked from commit 0f91811333)
2022-07-18 22:13:57 -07:00
Noah Goldstein a2e10e7a02 x86: ZERO_UPPER_VEC_REGISTERS_RETURN_XTEST expect no transactions
Give fall-through path to `vzeroupper` and taken-path to `vzeroall`.

Generally even on machines with RTM the expectation is the
string-library functions will not be called in transactions.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit c28db9cb29)
2022-07-18 22:13:57 -07:00
Noah Goldstein 289f772721 x86: Shrink code size of memchr-evex.S
This is not meant as a performance optimization. The previous code was
far to liberal in aligning targets and wasted code size unnecissarily.

The total code size saving is: 64 bytes

There are no non-negligible changes in the benchmarks.
Geometric Mean of all benchmarks New / Old: 1.000

Full xcheck passes on x86_64.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 56da3fe1dd)
2022-07-18 22:13:57 -07:00
Noah Goldstein 992086b659 x86: Shrink code size of memchr-avx2.S
This is not meant as a performance optimization. The previous code was
far to liberal in aligning targets and wasted code size unnecissarily.

The total code size saving is: 59 bytes

There are no major changes in the benchmarks.
Geometric Mean of all benchmarks New / Old: 0.967

Full xcheck passes on x86_64.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 6dcbb7d95d)

x86: Fix page cross case in rawmemchr-avx2 [BZ #29234]

commit 6dcbb7d95d
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Mon Jun 6 21:11:33 2022 -0700

    x86: Shrink code size of memchr-avx2.S

Changed how the page cross case aligned string (rdi) in
rawmemchr. This was incompatible with how
`L(cross_page_continue)` expected the pointer to be aligned and
would cause rawmemchr to read data start started before the
beginning of the string. What it would read was in valid memory
but could count CHAR matches resulting in an incorrect return
value.

This commit fixes that issue by essentially reverting the changes to
the L(page_cross) case as they didn't really matter.

Test cases added and all pass with the new code (and where confirmed
to fail with the old code).
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 2c9af8421d)
2022-07-18 22:13:57 -07:00
Noah Goldstein 58ca9728a8 x86: Optimize memrchr-avx2.S
The new code:
    1. prioritizes smaller user-arg lengths more.
    2. optimizes target placement more carefully
    3. reuses logic more
    4. fixes up various inefficiencies in the logic. The biggest
       case here is the `lzcnt` logic for checking returns which
       saves either a branch or multiple instructions.

The total code size saving is: 306 bytes
Geometric Mean of all benchmarks New / Old: 0.760

Regressions:
There are some regressions. Particularly where the length (user arg
length) is large but the position of the match char is near the
beginning of the string (in first VEC). This case has roughly a
10-20% regression.

This is because the new logic gives the hot path for immediate matches
to shorter lengths (the more common input). This case has roughly
a 15-45% speedup.

Full xcheck passes on x86_64.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit af5306a735)
2022-07-18 22:13:57 -07:00
Noah Goldstein 11946110f8 x86: Optimize memrchr-evex.S
The new code:
    1. prioritizes smaller user-arg lengths more.
    2. optimizes target placement more carefully
    3. reuses logic more
    4. fixes up various inefficiencies in the logic. The biggest
       case here is the `lzcnt` logic for checking returns which
       saves either a branch or multiple instructions.

The total code size saving is: 263 bytes
Geometric Mean of all benchmarks New / Old: 0.755

Regressions:
There are some regressions. Particularly where the length (user arg
length) is large but the position of the match char is near the
beginning of the string (in first VEC). This case has roughly a
20% regression.

This is because the new logic gives the hot path for immediate matches
to shorter lengths (the more common input). This case has roughly
a 35% speedup.

Full xcheck passes on x86_64.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit b4209615a0)
2022-07-18 22:13:57 -07:00
Noah Goldstein 6742c432db x86: Optimize memrchr-sse2.S
The new code:
    1. prioritizes smaller lengths more.
    2. optimizes target placement more carefully.
    3. reuses logic more.
    4. fixes up various inefficiencies in the logic.

The total code size saving is: 394 bytes
Geometric Mean of all benchmarks New / Old: 0.874

Regressions:
    1. The page cross case is now colder, especially re-entry from the
       page cross case if a match is not found in the first VEC
       (roughly 50%). My general opinion with this patch is this is
       acceptable given the "coldness" of this case (less than 4%) and
       generally performance improvement in the other far more common
       cases.

    2. There are some regressions 5-15% for medium/large user-arg
       lengths that have a match in the first VEC. This is because the
       logic was rewritten to optimize finds in the first VEC if the
       user-arg length is shorter (where we see roughly 20-50%
       performance improvements). It is not always the case this is a
       regression. My intuition is some frontend quirk is partially
       explaining the data although I haven't been able to find the
       root cause.

Full xcheck passes on x86_64.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 731feee386)
2022-07-18 22:13:56 -07:00
Noah Goldstein 0edbcc85cc x86: Add COND_VZEROUPPER that can replace vzeroupper if no ret
The RTM vzeroupper mitigation has no way of replacing inline
vzeroupper not before a return.

This can be useful when hoisting a vzeroupper to save code size
for example:

```
L(foo):
	cmpl	%eax, %edx
	jz	L(bar)
	tzcntl	%eax, %eax
	addq	%rdi, %rax
	VZEROUPPER_RETURN

L(bar):
	xorl	%eax, %eax
	VZEROUPPER_RETURN
```

Can become:

```
L(foo):
	COND_VZEROUPPER
	cmpl	%eax, %edx
	jz	L(bar)
	tzcntl	%eax, %eax
	addq	%rdi, %rax
	ret

L(bar):
	xorl	%eax, %eax
	ret
```

This code does not change any existing functionality.

There is no difference in the objdump of libc.so before and after this
patch.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit dd5c483b25)
2022-07-18 22:13:56 -07:00
Noah Goldstein 4f15b723fe x86: Create header for VEC classes in x86 strings library
This patch does not touch any existing code and is only meant to be a
tool for future patches so that simple source files can more easily be
maintained to target multiple VEC classes.

There is no difference in the objdump of libc.so before and after this
patch.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 8a780a6b91)
2022-07-18 22:13:56 -07:00
Raghuveer Devulapalli b38e8c5405 x86_64: Add strstr function with 512-bit EVEX
Adding a 512-bit EVEX version of strstr. The algorithm works as follows:

(1) We spend a few cycles at the begining to peek into the needle. We
locate an edge in the needle (first occurance of 2 consequent distinct
characters) and also store the first 64-bytes into a zmm register.

(2) We search for the edge in the haystack by looking into one cache
line of the haystack at a time. This avoids having to read past a page
boundary which can cause a seg fault.

(3) If an edge is found in the haystack we first compare the first
64-bytes of the needle (already stored in a zmm register) before we
proceed with a full string compare performed byte by byte.

Benchmarking results: (old = strstr_sse2_unaligned, new = strstr_avx512)

Geometric mean of all benchmarks: new / old =  0.66

Difficult skiptable(0) : new / old =  0.02
Difficult skiptable(1) : new / old =  0.01
Difficult 2-way : new / old =  0.25
Difficult testing first 2 : new / old =  1.26
Difficult skiptable(0) : new / old =  0.05
Difficult skiptable(1) : new / old =  0.06
Difficult 2-way : new / old =  0.26
Difficult testing first 2 : new / old =  1.05
Difficult skiptable(0) : new / old =  0.42
Difficult skiptable(1) : new / old =  0.24
Difficult 2-way : new / old =  0.21
Difficult testing first 2 : new / old =  1.04
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5082a287d5)

x86: Remove __mmask intrinsics in strstr-avx512.c

The intrinsics are not available before GCC7 and using standard
operators generates code of equivalent or better quality.

Removed:
    _cvtmask64_u64
    _kshiftri_mask64
    _kand_mask64

Geometric Mean of 5 Runs of Full Benchmark Suite New / Old: 0.958

(cherry picked from commit f2698954ff)
2022-07-18 22:13:56 -07:00
H.J. Lu dbb5e61851 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>
(cherry picked from commit f8587a6189)
2022-07-18 22:13:56 -07:00
Sunil K Pandey f98a799def x86_64: Implement evex512 version of strlen, strnlen, wcslen and wcsnlen
This patch implements following evex512 version of string functions.
Perf gain for evex512 version is up to 50% as compared to evex,
depending on length and alignment.

Placeholder function, not used by any processor at the moment.

- String length function using 512 bit vectors.
- String N length using 512 bit vectors.
- Wide string length using 512 bit vectors.
- Wide string N length using 512 bit vectors.

Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 9c66efb86f)
2022-07-18 22:13:56 -07:00
Adhemerval Zanella 2ce3c218c2 x86_64: Remove bzero optimization
Both symbols are marked as legacy in POSIX.1-2001 and removed on
POSIX.1-2008, although the prototypes are defined for _GNU_SOURCE
or _DEFAULT_SOURCE.

GCC also replaces bcopy with a memmove and bzero with memset on default
configuration (to actually get a bzero libc call the code requires
to omit string.h inclusion and built with -fno-builtin), so it is
highly unlikely programs are actually calling libc bzero symbol.

On a recent Linux distro (Ubuntu 22.04), there is no bzero calls
by the installed binaries.

  $ cat count_bstring.sh
  #!/bin/bash

  files=`IFS=':';for i in $PATH; do test -d "$i" && find "$i" -maxdepth 1 -executable -type f; done`
  total=0
  for file in $files; do
    symbols=`objdump -R $file 2>&1`
    if [ $? -eq 0 ]; then
      ncalls=`echo $symbols | grep -w $1 | wc -l`
      ((total=total+ncalls))
      if [ $ncalls -gt 0 ]; then
        echo "$file: $ncalls"
      fi
    fi
  done
  echo "TOTAL=$total"
  $ ./count_bstring.sh bzero
  TOTAL=0

Checked on x86_64-linux-gnu.

(cherry picked from commit 9403b71ae9)
2022-07-18 22:13:56 -07:00
Sunil K Pandey 344a7f6da7 x86_64: Remove end of line trailing spaces
This commit remove trailing space introduced by following commit.

commit a775a7a3eb
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Wed Jun 23 01:56:29 2021 -0400

    x86: Fix overflow bug in wcsnlen-sse4_1 and wcsnlen-avx2 [BZ #27974]

(cherry picked from commit 8d324019e6)
2022-07-18 22:13:56 -07:00
Florian Weimer 1916c5f062 elf: Earlier missing dynamic segment check in _dl_map_object_from_fd
Separated debuginfo files have PT_DYNAMIC with p_filesz == 0.  We
need to check for that before the _dl_map_segments call because
that could attempt to write to mappings that extend beyond the end
of the file, resulting in SIGBUS.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit ea32ec354c)
2022-07-09 10:45:39 +02:00
Adhemerval Zanella d44e1a0740 linux: Fix mq_timereceive check for 32 bit fallback code (BZ 29304)
On  success,  mq_receive() and mq_timedreceive() return the number of
bytes in the received message, so it requires to check if the value
is larger than 0.

Checked on i686-linux-gnu.

(cherry picked from commit 71d87d85bf)
2022-06-30 10:46:47 -03:00
Matheus Castanho 82c7441f04 powerpc: Fix VSX register number on __strncpy_power9 [BZ #29197]
__strncpy_power9 initializes VR 18 with zeroes to be used throughout the
code, including when zero-padding the destination string. However, the
v18 reference was mistakenly being used for stxv and stxvl, which take a
VSX vector as operand. The code ended up using the uninitialized VSR 18
register by mistake.

Both occurrences have been changed to use the proper VSX number for VR 18
(i.e. VSR 50).

Tested on powerpc, powerpc64 and powerpc64le.

Signed-off-by: Kewen Lin <linkw@gcc.gnu.org>
(cherry picked from commit 0218463dd8)
2022-06-07 15:42:14 -03:00
Noah Goldstein 69f16619e7 x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ #29127]
Re-cherry-pick commit c627209832 for strcmp-avx2.S change which was
omitted in intial cherry pick because at the time this bug was not
present on release branch.

Fixes BZ #29127.

In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
not checks around vzeroupper and would trigger spurious
aborts. This commit fixes that.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
AVX2 machines with and without RTM.

Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c627209832)
2022-05-25 15:07:28 -07:00
Noah Goldstein 7da0b8522b x86: Optimize {str|wcs}rchr-evex
The new code unrolls the main loop slightly without adding too much
overhead and minimizes the comparisons for the search CHAR.

Geometric Mean of all benchmarks New / Old: 0.755
See email for all results.

Full xcheck passes on x86_64 with and without multiarch enabled.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit c966099cdc)
2022-05-16 20:46:48 -07:00
Noah Goldstein d02f73af99 x86: Optimize {str|wcs}rchr-avx2
The new code unrolls the main loop slightly without adding too much
overhead and minimizes the comparisons for the search CHAR.

Geometric Mean of all benchmarks New / Old: 0.832
See email for all results.

Full xcheck passes on x86_64 with and without multiarch enabled.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit df7e295d18)
2022-05-16 20:46:36 -07:00
Noah Goldstein 1c9f410f11 x86: Optimize {str|wcs}rchr-sse2
The new code unrolls the main loop slightly without adding too much
overhead and minimizes the comparisons for the search CHAR.

Geometric Mean of all benchmarks New / Old: 0.741
See email for all results.

Full xcheck passes on x86_64 with and without multiarch enabled.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5307aa9c18)
2022-05-16 20:46:27 -07:00
Noah Goldstein 505a5f15fb x86: Cleanup page cross code in memcmp-avx2-movbe.S
Old code was both inefficient and wasted code size. New code (-62
bytes) and comparable or better performance in the page cross case.

geometric_mean(N=20) of page cross cases New / Original: 0.960

size, align0, align1, ret, New Time/Old Time
   1,   4095,      0,   0,             1.001
   1,   4095,      0,   1,             0.999
   1,   4095,      0,  -1,               1.0
   2,   4094,      0,   0,               1.0
   2,   4094,      0,   1,               1.0
   2,   4094,      0,  -1,               1.0
   3,   4093,      0,   0,               1.0
   3,   4093,      0,   1,               1.0
   3,   4093,      0,  -1,               1.0
   4,   4092,      0,   0,             0.987
   4,   4092,      0,   1,               1.0
   4,   4092,      0,  -1,               1.0
   5,   4091,      0,   0,             0.984
   5,   4091,      0,   1,             1.002
   5,   4091,      0,  -1,             1.005
   6,   4090,      0,   0,             0.993
   6,   4090,      0,   1,             1.001
   6,   4090,      0,  -1,             1.003
   7,   4089,      0,   0,             0.991
   7,   4089,      0,   1,               1.0
   7,   4089,      0,  -1,             1.001
   8,   4088,      0,   0,             0.875
   8,   4088,      0,   1,             0.881
   8,   4088,      0,  -1,             0.888
   9,   4087,      0,   0,             0.872
   9,   4087,      0,   1,             0.879
   9,   4087,      0,  -1,             0.883
  10,   4086,      0,   0,             0.878
  10,   4086,      0,   1,             0.886
  10,   4086,      0,  -1,             0.873
  11,   4085,      0,   0,             0.878
  11,   4085,      0,   1,             0.881
  11,   4085,      0,  -1,             0.879
  12,   4084,      0,   0,             0.873
  12,   4084,      0,   1,             0.889
  12,   4084,      0,  -1,             0.875
  13,   4083,      0,   0,             0.873
  13,   4083,      0,   1,             0.863
  13,   4083,      0,  -1,             0.863
  14,   4082,      0,   0,             0.838
  14,   4082,      0,   1,             0.869
  14,   4082,      0,  -1,             0.877
  15,   4081,      0,   0,             0.841
  15,   4081,      0,   1,             0.869
  15,   4081,      0,  -1,             0.876
  16,   4080,      0,   0,             0.988
  16,   4080,      0,   1,              0.99
  16,   4080,      0,  -1,             0.989
  17,   4079,      0,   0,             0.978
  17,   4079,      0,   1,             0.981
  17,   4079,      0,  -1,              0.98
  18,   4078,      0,   0,             0.981
  18,   4078,      0,   1,              0.98
  18,   4078,      0,  -1,             0.985
  19,   4077,      0,   0,             0.977
  19,   4077,      0,   1,             0.979
  19,   4077,      0,  -1,             0.986
  20,   4076,      0,   0,             0.977
  20,   4076,      0,   1,             0.986
  20,   4076,      0,  -1,             0.984
  21,   4075,      0,   0,             0.977
  21,   4075,      0,   1,             0.983
  21,   4075,      0,  -1,             0.988
  22,   4074,      0,   0,             0.983
  22,   4074,      0,   1,             0.994
  22,   4074,      0,  -1,             0.993
  23,   4073,      0,   0,              0.98
  23,   4073,      0,   1,             0.992
  23,   4073,      0,  -1,             0.995
  24,   4072,      0,   0,             0.989
  24,   4072,      0,   1,             0.989
  24,   4072,      0,  -1,             0.991
  25,   4071,      0,   0,              0.99
  25,   4071,      0,   1,             0.999
  25,   4071,      0,  -1,             0.996
  26,   4070,      0,   0,             0.993
  26,   4070,      0,   1,             0.995
  26,   4070,      0,  -1,             0.998
  27,   4069,      0,   0,             0.993
  27,   4069,      0,   1,             0.999
  27,   4069,      0,  -1,               1.0
  28,   4068,      0,   0,             0.997
  28,   4068,      0,   1,               1.0
  28,   4068,      0,  -1,             0.999
  29,   4067,      0,   0,             0.996
  29,   4067,      0,   1,             0.999
  29,   4067,      0,  -1,             0.999
  30,   4066,      0,   0,             0.991
  30,   4066,      0,   1,             1.001
  30,   4066,      0,  -1,             0.999
  31,   4065,      0,   0,             0.988
  31,   4065,      0,   1,             0.998
  31,   4065,      0,  -1,             0.998
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 23102686ec)
2022-05-16 20:46:16 -07:00
Noah Goldstein 95bbfc0351 x86: Remove memcmp-sse4.S
Code didn't actually use any sse4 instructions since `ptest` was
removed in:

commit 2f9062d717
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Wed Nov 10 16:18:56 2021 -0600

    x86: Shrink memcmp-sse4.S code size

The new memcmp-sse2 implementation is also faster.

geometric_mean(N=20) of page cross cases SSE2 / SSE4: 0.905

Note there are two regressions preferring SSE2 for Size = 1 and Size =
65.

Size = 1:
size, align0, align1, ret, New Time/Old Time
   1,      1,      1,   0,               1.2
   1,      1,      1,   1,             1.197
   1,      1,      1,  -1,               1.2

This is intentional. Size == 1 is significantly less hot based on
profiles of GCC11 and Python3 than sizes [4, 8] (which is made
hotter).

Python3 Size = 1        -> 13.64%
Python3 Size = [4, 8]   -> 60.92%

GCC11   Size = 1        ->  1.29%
GCC11   Size = [4, 8]   -> 33.86%

size, align0, align1, ret, New Time/Old Time
   4,      4,      4,   0,             0.622
   4,      4,      4,   1,             0.797
   4,      4,      4,  -1,             0.805
   5,      5,      5,   0,             0.623
   5,      5,      5,   1,             0.777
   5,      5,      5,  -1,             0.802
   6,      6,      6,   0,             0.625
   6,      6,      6,   1,             0.813
   6,      6,      6,  -1,             0.788
   7,      7,      7,   0,             0.625
   7,      7,      7,   1,             0.799
   7,      7,      7,  -1,             0.795
   8,      8,      8,   0,             0.625
   8,      8,      8,   1,             0.848
   8,      8,      8,  -1,             0.914
   9,      9,      9,   0,             0.625

Size = 65:
size, align0, align1, ret, New Time/Old Time
  65,      0,      0,   0,             1.103
  65,      0,      0,   1,             1.216
  65,      0,      0,  -1,             1.227
  65,     65,      0,   0,             1.091
  65,      0,     65,   1,              1.19
  65,     65,     65,  -1,             1.215

This is because A) the checks in range [65, 96] are now unrolled 2x
and B) because smaller values <= 16 are now given a hotter path. By
contrast the SSE4 version has a branch for Size = 80. The unrolled
version has get better performance for returns which need both
comparisons.

size, align0, align1, ret, New Time/Old Time
 128,      4,      8,   0,             0.858
 128,      4,      8,   1,             0.879
 128,      4,      8,  -1,             0.888

As well, out of microbenchmark environments that are not full
predictable the branch will have a real-cost.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 7cbc03d030)
2022-05-16 20:46:04 -07:00
Noah Goldstein aa4b53b4c0 x86: Small improvements for wcslen
Just a few QOL changes.
    1. Prefer `add` > `lea` as it has high execution units it can run
       on.
    2. Don't break macro-fusion between `test` and `jcc`
    3. Reduce code size by removing gratuitous padding bytes (-90
       bytes).

geometric_mean(N=20) of all benchmarks New / Original: 0.959

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 244b415d38)
2022-05-16 20:45:53 -07:00
Noah Goldstein b03c4ba9ef x86: Remove AVX str{n}casecmp
The rational is:

1. SSE42 has nearly identical logic so any benefit is minimal (3.4%
   regression on Tigerlake using SSE42 versus AVX across the
   benchtest suite).
2. AVX2 version covers the majority of targets that previously
   prefered it.
3. The targets where AVX would still be best (SnB and IVB) are
   becoming outdated.

All in all the saving the code size is worth it.

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 305769b2a1)
2022-05-16 20:45:43 -07:00
Noah Goldstein 3dfd48f416 x86: Add EVEX optimized str{n}casecmp
geometric_mean(N=40) of all benchmarks EVEX / SSE42: .621

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 84e7c46df4)
2022-05-16 20:45:32 -07:00
Noah Goldstein 013f063030 x86: Add AVX2 optimized str{n}casecmp
geometric_mean(N=40) of all benchmarks AVX2 / SSE42: .702

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit bbf8122234)
2022-05-16 20:45:18 -07:00
Noah Goldstein c523a2b1cc x86: Optimize str{n}casecmp TOLOWER logic in strcmp-sse42.S
Slightly faster method of doing TOLOWER that saves an
instruction.

Also replace the hard coded 5-byte no with .p2align 4. On builds with
CET enabled this misaligned entry to strcasecmp.

geometric_mean(N=40) of all benchmarks New / Original: .920

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit d154758e61)
2022-05-16 20:45:07 -07:00
Noah Goldstein 82e29f4349 x86: Optimize str{n}casecmp TOLOWER logic in strcmp.S
Slightly faster method of doing TOLOWER that saves an
instruction.

Also replace the hard coded 5-byte no with .p2align 4. On builds with
CET enabled this misaligned entry to strcasecmp.

geometric_mean(N=40) of all benchmarks New / Original: .894

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 670b54bc58)
2022-05-16 20:44:57 -07:00
Noah Goldstein c434fafeba x86: Remove strspn-sse2.S and use the generic implementation
The generic implementation is faster.

geometric_mean(N=20) of all benchmarks New / Original: .710

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 9c8a6ad620)
2022-05-16 20:44:45 -07:00
Noah Goldstein 667c1f9103 x86: Remove strpbrk-sse2.S and use the generic implementation
The generic implementation is faster (see strcspn commit).

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 6533585352)
2022-05-16 20:44:33 -07:00
Noah Goldstein 1cd4946134 x86: Remove strcspn-sse2.S and use the generic implementation
The generic implementation is faster.

geometric_mean(N=20) of all benchmarks New / Original: .678

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit fe28e7d9d9)
2022-05-16 20:44:20 -07:00
Noah Goldstein a16658ee66 x86: Optimize strspn in strspn-c.c
Use _mm_cmpeq_epi8 and _mm_movemask_epi8 to get strlen instead of
_mm_cmpistri. Also change offset to unsigned to avoid unnecessary
sign extensions.

geometric_mean(N=20) of all benchmarks that dont fallback on
sse2; New / Original: .901

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 412d103431)
2022-05-16 20:44:10 -07:00
Noah Goldstein 8cd840d526 x86: Optimize strcspn and strpbrk in strcspn-c.c
Use _mm_cmpeq_epi8 and _mm_movemask_epi8 to get strlen instead of
_mm_cmpistri. Also change offset to unsigned to avoid unnecessary
sign extensions.

geometric_mean(N=20) of all benchmarks that dont fallback on
sse2/strlen; New / Original: .928

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 30d627d477)
2022-05-16 20:43:59 -07:00
Noah Goldstein 7a40676084 x86: Code cleanup in strchr-evex and comment justifying branch
Small code cleanup for size: -81 bytes.

Add comment justifying using a branch to do NULL/non-null return.

All string/memory tests pass and no regressions in benchtests.

geometric_mean(N=20) of all benchmarks New / Original: .985
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit ec285ea904)
2022-05-16 20:43:26 -07:00
Noah Goldstein a66e66022d x86: Code cleanup in strchr-avx2 and comment justifying branch
Small code cleanup for size: -53 bytes.

Add comment justifying using a branch to do NULL/non-null return.

All string/memory tests pass and no regressions in benchtests.

geometric_mean(N=20) of all benchmarks Original / New: 1.00
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit a6fbf4d51e)
2022-05-16 20:43:15 -07:00
Adhemerval Zanella 7898ee8f3f x86_64: Remove bcopy optimizations
The symbols is not present in current POSIX specification and compiler
already generates memmove call.

(cherry picked from commit bf92893a14)
2022-05-16 20:43:01 -07:00
H.J. Lu a5cd8efcea x86-64: Remove bzero weak alias in SS2 memset
commit 3d9f171bfb
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Feb 7 05:55:15 2022 -0800

    x86-64: Optimize bzero

added the optimized bzero.  Remove bzero weak alias in SS2 memset to
avoid undefined __bzero in memset-sse2-unaligned-erms.

(cherry picked from commit 0fb8800029)
2022-05-16 20:42:51 -07:00
H.J. Lu fb4ebf9db8 x86_64/multiarch: Sort sysdep_routines and put one entry per line
(cherry picked from commit c328d0152d)
2022-05-16 20:42:40 -07:00
H.J. Lu 09774a6e14 x86: Improve L to support L(XXX_SYMBOL (YYY, ZZZ))
(cherry picked from commit 1283948f23)
2022-05-16 20:42:27 -07:00
Noah Goldstein 07b5c14c43 x86: Fix fallback for wcsncmp_avx2 in strcmp-avx2.S [BZ #28896]
Overflow case for __wcsncmp_avx2_rtm should be __wcscmp_avx2_rtm not
__wcscmp_avx2.

commit ddf0992cf5
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Sun Jan 9 16:02:21 2022 -0600

    x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]

Set the wrong fallback function for `__wcsncmp_avx2_rtm`. It was set
to fallback on to `__wcscmp_avx2` instead of `__wcscmp_avx2_rtm` which
can cause spurious aborts.

This change will need to be backported.

All string/memory tests pass.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 9fef7039a7)
2022-05-05 09:38:32 -07:00
Noah Goldstein a1b122aa90 x86: Fix bug in strncmp-evex and strncmp-avx2 [BZ #28895]
Logic can read before the start of `s1` / `s2` if both `s1` and `s2`
are near the start of a page. To avoid having the result contimated by
these comparisons the `strcmp` variants would mask off these
comparisons. This was missing in the `strncmp` variants causing
the bug. This commit adds the masking to `strncmp` so that out of
range comparisons don't affect the result.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass as
well a full xcheck on x86_64 linux.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit e108c02a5e)
2022-05-05 09:36:51 -07:00
Noah Goldstein 30058694a5 x86: Set .text section in memset-vec-unaligned-erms
commit 3d9f171bfb
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Feb 7 05:55:15 2022 -0800

    x86-64: Optimize bzero

Remove setting the .text section for the code. This commit
adds that back.

(cherry picked from commit 7912236f4a)
2022-05-05 09:36:07 -07:00
H.J. Lu 2381bb056f x86-64: Optimize bzero
memset with zero as the value to set is by far the majority value (99%+
for Python3 and GCC).

bzero can be slightly more optimized for this case by using a zero-idiom
xor for broadcasting the set value to a register (vector or GPR).

Co-developed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 3d9f171bfb)
2022-05-05 09:33:50 -07:00
Noah Goldstein f5e0ea6c0d x86: Remove SSSE3 instruction for broadcast in memset.S (SSE2 Only)
commit b62ace2740
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Sun Feb 6 00:54:18 2022 -0600

    x86: Improve vec generation in memset-vec-unaligned-erms.S

Revert usage of 'pshufb' in broadcast logic as it is an SSSE3
instruction and memset.S is restricted to only SSE2 instructions.

(cherry picked from commit 1b0c60f95b)
2022-05-05 09:20:33 -07:00
Noah Goldstein ef264d262b x86: Improve vec generation in memset-vec-unaligned-erms.S
No bug.

Split vec generation into multiple steps. This allows the
broadcast in AVX2 to use 'xmm' registers for the L(less_vec)
case. This saves an expensive lane-cross instruction and removes
the need for 'vzeroupper'.

For SSE2 replace 2x 'punpck' instructions with zero-idiom 'pxor' for
byte broadcast.

Results for memset-avx2 small (geomean of N = 20 benchset runs).

size, New Time, Old Time, New / Old
   0,    4.100,    3.831,     0.934
   1,    5.074,    4.399,     0.867
   2,    4.433,    4.411,     0.995
   4,    4.487,    4.415,     0.984
   8,    4.454,    4.396,     0.987
  16,    4.502,    4.443,     0.987

All relevant string/wcsmbs tests are passing.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit b62ace2740)
2022-05-05 09:19:16 -07:00
H.J. Lu 53f4ff9ff4 x86-64: Fix strcmp-evex.S
Change "movl %edx, %rdx" to "movl %edx, %edx" in:

commit 8418eb3ff4
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Mon Jan 10 15:35:39 2022 -0600

    x86: Optimize strcmp-evex.S

(cherry picked from commit 0e0199a9e0)
2022-05-05 09:18:26 -07:00
H.J. Lu 80f869106f x86-64: Fix strcmp-avx2.S
Change "movl %edx, %rdx" to "movl %edx, %edx" in:

commit b77b06e0e2
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Mon Jan 10 15:35:38 2022 -0600

    x86: Optimize strcmp-avx2.S

(cherry picked from commit c15efd011c)
2022-05-05 09:17:31 -07:00
Noah Goldstein 30f75f3a13 x86: Optimize strcmp-evex.S
Optimization are primarily to the loop logic and how the page cross
logic interacts with the loop.

The page cross logic is at times more expensive for short strings near
the end of a page but not crossing the page. This is done to retest
the page cross conditions with a non-faulty check and to improve the
logic for entering the loop afterwards. This is only particular cases,
however, and is general made up for by more than 10x improvements on
the transition from the page cross -> loop case.

The non-page cross cases as well are nearly universally improved.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 8418eb3ff4)
2022-05-05 09:17:22 -07:00
Noah Goldstein 63d1ff4aa0 x86: Optimize strcmp-avx2.S
Optimization are primarily to the loop logic and how the page cross
logic interacts with the loop.

The page cross logic is at times more expensive for short strings near
the end of a page but not crossing the page. This is done to retest
the page cross conditions with a non-faulty check and to improve the
logic for entering the loop afterwards. This is only particular cases,
however, and is general made up for by more than 10x improvements on
the transition from the page cross -> loop case.

The non-page cross cases are improved most for smaller sizes [0, 128]
and go about even for (128, 4096]. The loop page cross logic is
improved so some more significant speedup is seen there as well.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit b77b06e0e2)
2022-05-05 09:17:13 -07:00
Noah Goldstein b002995ea4 x86: Optimize L(less_vec) case in memcmp-evex-movbe.S
No bug.
Optimizations are twofold.

1) Replace page cross and 0/1 checks with masked load instructions in
   L(less_vec). In applications this reduces branch-misses in the
   hot [0, 32] case.
2) Change controlflow so that L(less_vec) case gets the fall through.

Change 2) helps copies in the [0, 32] size range but comes at the cost
of copies in the [33, 64] size range.  From profiles of GCC and
Python3, 94%+ and 99%+ of calls are in the [0, 32] range so this
appears to the the right tradeoff.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit abddd61de0)
2022-05-02 13:02:27 -07:00
H.J. Lu 63fd074112 x86: Don't set Prefer_No_AVX512 for processors with AVX512 and AVX-VNNI
Don't set Prefer_No_AVX512 on processors with AVX512 and AVX-VNNI since
they won't lower CPU frequency when ZMM load and store instructions are
used.

(cherry picked from commit ceeffe968c)
2022-05-02 13:02:19 -07:00
Noah Goldstein d77349767a x86-64: Use notl in EVEX strcmp [BZ #28646]
Must use notl %edi here as lower bits are for CHAR comparisons
potentially out of range thus can be 0 without indicating mismatch.
This fixes BZ #28646.

Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 4df1fa6ddc)
2022-05-02 13:02:12 -07:00
Noah Goldstein 3a8cc38d57 x86: Shrink memcmp-sse4.S code size
No bug.

This implementation refactors memcmp-sse4.S primarily with minimizing
code size in mind. It does this by removing the lookup table logic and
removing the unrolled check from (256, 512] bytes.

memcmp-sse4 code size reduction : -3487 bytes
wmemcmp-sse4 code size reduction: -1472 bytes

The current memcmp-sse4.S implementation has a large code size
cost. This has serious adverse affects on the ICache / ITLB. While
in micro-benchmarks the implementations appears fast, traces of
real-world code have shown that the speed in micro benchmarks does not
translate when the ICache/ITLB are not primed, and that the cost
of the code size has measurable negative affects on overall
application performance.

See https://research.google/pubs/pub48320/ for more details.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 2f9062d717)
2022-05-02 13:02:04 -07:00
Noah Goldstein d0fac98a30 x86: Double size of ERMS rep_movsb_threshold in dl-cacheinfo.h
No bug.

This patch doubles the rep_movsb_threshold when using ERMS. Based on
benchmarks the vector copy loop, especially now that it handles 4k
aliasing, is better for these medium ranged.

On Skylake with ERMS:

Size,   Align1, Align2, dst>src,(rep movsb) / (vec copy)
4096,   0,      0,      0,      0.975
4096,   0,      0,      1,      0.953
4096,   12,     0,      0,      0.969
4096,   12,     0,      1,      0.872
4096,   44,     0,      0,      0.979
4096,   44,     0,      1,      0.83
4096,   0,      12,     0,      1.006
4096,   0,      12,     1,      0.989
4096,   0,      44,     0,      0.739
4096,   0,      44,     1,      0.942
4096,   12,     12,     0,      1.009
4096,   12,     12,     1,      0.973
4096,   44,     44,     0,      0.791
4096,   44,     44,     1,      0.961
4096,   2048,   0,      0,      0.978
4096,   2048,   0,      1,      0.951
4096,   2060,   0,      0,      0.986
4096,   2060,   0,      1,      0.963
4096,   2048,   12,     0,      0.971
4096,   2048,   12,     1,      0.941
4096,   2060,   12,     0,      0.977
4096,   2060,   12,     1,      0.949
8192,   0,      0,      0,      0.85
8192,   0,      0,      1,      0.845
8192,   13,     0,      0,      0.937
8192,   13,     0,      1,      0.939
8192,   45,     0,      0,      0.932
8192,   45,     0,      1,      0.927
8192,   0,      13,     0,      0.621
8192,   0,      13,     1,      0.62
8192,   0,      45,     0,      0.53
8192,   0,      45,     1,      0.516
8192,   13,     13,     0,      0.664
8192,   13,     13,     1,      0.659
8192,   45,     45,     0,      0.593
8192,   45,     45,     1,      0.575
8192,   2048,   0,      0,      0.854
8192,   2048,   0,      1,      0.834
8192,   2061,   0,      0,      0.863
8192,   2061,   0,      1,      0.857
8192,   2048,   13,     0,      0.63
8192,   2048,   13,     1,      0.629
8192,   2061,   13,     0,      0.627
8192,   2061,   13,     1,      0.62

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 475b63702e)
2022-05-02 13:01:55 -07:00
Noah Goldstein 5d56ee94f2 x86: Optimize memmove-vec-unaligned-erms.S
No bug.

The optimizations are as follows:

1) Always align entry to 64 bytes. This makes behavior more
   predictable and makes other frontend optimizations easier.

2) Make the L(more_8x_vec) cases 4k aliasing aware. This can have
   significant benefits in the case that:
        0 < (dst - src) < [256, 512]

3) Align before `rep movsb`. For ERMS this is roughly a [0, 30%]
   improvement and for FSRM [-10%, 25%].

In addition to these primary changes there is general cleanup
throughout to optimize the aligning routines and control flow logic.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit a6b7502ec0)
2022-05-02 13:01:46 -07:00
Fangrui Song e36de6a3cd x86-64: Replace movzx with movzbl
Clang cannot assemble movzx in the AT&T dialect mode.

../sysdeps/x86_64/strcmp.S:2232:16: error: invalid operand for instruction
 movzx (%rsi), %ecx
               ^~~~

Change movzx to movzbl, which follows the AT&T dialect and is used
elsewhere in the file.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6720d36b66)
2022-05-02 13:01:38 -07:00
H.J. Lu ce78592170 x86-64: Remove Prefer_AVX2_STRCMP
Remove Prefer_AVX2_STRCMP to enable EVEX strcmp.  When comparing 2 32-byte
strings, EVEX strcmp has been improved to require 1 load, 1 VPTESTM, 1
VPCMP, 1 KMOVD and 1 INCL instead of 2 loads, 3 VPCMPs, 2 KORDs, 1 KMOVD
and 1 TESTL while AVX2 strcmp requires 1 load, 2 VPCMPEQs, 1 VPMINU, 1
VPMOVMSKB and 1 TESTL.  EVEX strcmp is now faster than AVX2 strcmp by up
to 40% on Tiger Lake and Ice Lake.

(cherry picked from commit 14dbbf46a0)
2022-05-02 13:01:30 -07:00
H.J. Lu 1a7af4e140 x86-64: Improve EVEX strcmp with masked load
In strcmp-evex.S, to compare 2 32-byte strings, replace

        VMOVU   (%rdi, %rdx), %YMM0
        VMOVU   (%rsi, %rdx), %YMM1
        /* Each bit in K0 represents a mismatch in YMM0 and YMM1.  */
        VPCMP   $4, %YMM0, %YMM1, %k0
        VPCMP   $0, %YMMZERO, %YMM0, %k1
        VPCMP   $0, %YMMZERO, %YMM1, %k2
        /* Each bit in K1 represents a NULL in YMM0 or YMM1.  */
        kord    %k1, %k2, %k1
        /* Each bit in K1 represents a NULL or a mismatch.  */
        kord    %k0, %k1, %k1
        kmovd   %k1, %ecx
        testl   %ecx, %ecx
        jne     L(last_vector)

with

        VMOVU   (%rdi, %rdx), %YMM0
        VPTESTM %YMM0, %YMM0, %k2
        /* Each bit cleared in K1 represents a mismatch or a null CHAR
           in YMM0 and 32 bytes at (%rsi, %rdx).  */
        VPCMP   $0, (%rsi, %rdx), %YMM0, %k1{%k2}
        kmovd   %k1, %ecx
        incl    %ecx
        jne     L(last_vector)

It makes EVEX strcmp faster than AVX2 strcmp by up to 40% on Tiger Lake
and Ice Lake.

Co-Authored-By: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit c46e9afb2d)
2022-05-02 13:01:21 -07:00
Noah Goldstein 4df7e006ec x86: Replace sse2 instructions with avx in memcmp-evex-movbe.S
This commit replaces two usages of SSE2 'movups' with AVX 'vmovdqu'.

it could potentially be dangerous to use SSE2 if this function is ever
called without using 'vzeroupper' beforehand. While compilers appear
to use 'vzeroupper' before function calls if AVX2 has been used, using
SSE2 here is more brittle. Since it is not absolutely necessary it
should be avoided.

It costs 2-extra bytes but the extra bytes should only eat into
alignment padding.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit bad852b61b)
2022-05-02 13:01:14 -07:00
Noah Goldstein a4e41f7253 x86: Optimize memset-vec-unaligned-erms.S
No bug.

Optimization are

1. change control flow for L(more_2x_vec) to fall through to loop and
   jump for L(less_4x_vec) and L(less_8x_vec). This uses less code
   size and saves jumps for length > 4x VEC_SIZE.

2. For EVEX/AVX512 move L(less_vec) closer to entry.

3. Avoid complex address mode for length > 2x VEC_SIZE

4. Slightly better aligning code for the loop from the perspective of
   code size and uops.

5. Align targets so they make full use of their fetch block and if
   possible cache line.

6. Try and reduce total number of icache lines that will need to be
   pulled in for a given length.

7. Include "local" version of stosb target. For AVX2/EVEX/AVX512
   jumping to the stosb target in the sse2 code section will almost
   certainly be to a new page. The new version does increase code size
   marginally by duplicating the target but should get better iTLB
   behavior as a result.

test-memset, test-wmemset, and test-bzero are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit e59ced2384)
2022-05-02 13:01:06 -07:00
Noah Goldstein 280fcf7f56 x86: Optimize memcmp-evex-movbe.S for frontend behavior and size
No bug.

The frontend optimizations are to:
1. Reorganize logically connected basic blocks so they are either in
   the same cache line or adjacent cache lines.
2. Avoid cases when basic blocks unnecissarily cross cache lines.
3. Try and 32 byte align any basic blocks possible without sacrificing
   code size. Smaller / Less hot basic blocks are used for this.

Overall code size shrunk by 168 bytes. This should make up for any
extra costs due to aligning to 64 bytes.

In general performance before deviated a great deal dependending on
whether entry alignment % 64 was 0, 16, 32, or 48. These changes
essentially make it so that the current implementation is at least
equal to the best alignment of the original for any arguments.

The only additional optimization is in the page cross case. Branch on
equals case was removed from the size == [4, 7] case. As well the [4,
7] and [2, 3] case where swapped as [4, 7] is likely a more hot
argument size.

test-memcmp and test-wmemcmp are both passing.

(cherry picked from commit 1bd8b8d58f)
2022-05-02 13:00:20 -07:00
Noah Goldstein e47c117d01 x86: Modify ENTRY in sysdep.h so that p2align can be specified
No bug.

This change adds a new macro ENTRY_P2ALIGN which takes a second
argument, log2 of the desired function alignment.

The old ENTRY(name) macro is just ENTRY_P2ALIGN(name, 4) so this
doesn't affect any existing functionality.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit fc5bd179ef)
2022-05-02 13:00:12 -07:00
H.J. Lu c09d92d4f6 x86-64: Optimize load of all bits set into ZMM register [BZ #28252]
Optimize loads of all bits set into ZMM register in AVX512 SVML codes
by replacing

	vpbroadcastq .L_2il0floatpacket.16(%rip), %zmmX

and

	vmovups   .L_2il0floatpacket.13(%rip), %zmmX

with
	vpternlogd $0xff, %zmmX, %zmmX, %zmmX

This fixes BZ #28252.

(cherry picked from commit 78c9ec9000)
2022-05-02 13:00:04 -07:00
Noah Goldstein 83454fe8d7 x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755]
Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to
__wcscmp_evex. For x86_64 this covers the entire address range so any
length larger could not possibly be used to bound `s1` or `s2`.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 7e08db3359)
2022-05-02 12:59:38 -07:00
H.J. Lu 91010c4cf8 x86-64: Use testl to check __x86_string_control
Use testl, instead of andl, to check __x86_string_control to avoid
updating __x86_string_control.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3c8b9879ca)
2022-05-02 11:51:31 -07:00
H.J. Lu 0834ee7398 x86-64: Add Avoid_Short_Distance_REP_MOVSB
commit 3ec5d83d2a
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat Jan 25 14:19:40 2020 -0800

    x86-64: Avoid rep movsb with short distance [BZ #27130]

introduced some regressions on Intel processors without Fast Short REP
MOV (FSRM).  Add Avoid_Short_Distance_REP_MOVSB to avoid rep movsb with
short distance only on Intel processors with FSRM.  bench-memmove-large
on Skylake server shows that cycles of __memmove_evex_unaligned_erms
improves for the following data size:

                                  before    after    Improvement
length=4127, align1=3, align2=0:  479.38    349.25      27%
length=4223, align1=9, align2=5:  405.62    333.25      18%
length=8223, align1=3, align2=0:  786.12    496.38      37%
length=8319, align1=9, align2=5:  727.50    501.38      31%
length=16415, align1=3, align2=0: 1436.88   840.00      41%
length=16511, align1=9, align2=5: 1375.50   836.38      39%
length=32799, align1=3, align2=0: 2890.00   1860.12     36%
length=32895, align1=9, align2=5: 2891.38   1931.88     33%

(cherry picked from commit 91cc803d27)
2022-05-02 11:51:24 -07:00
Noah Goldstein 853f83686a x86: Remove unnecessary overflow check from wcsnlen-sse4_1.S
No bug. The way wcsnlen will check if near the end of maxlen
is the following macro:

	mov	%r11, %rsi;	\
	subq	%rax, %rsi;	\
	andq	$-64, %rax;	\
	testq	$-64, %rsi;	\
	je	L(strnlen_ret)

Which words independently of s + maxlen overflowing. So the
second overflow check is unnecissary for correctness and
just extra overhead in the common no overflow case.

test-strlen.c, test-wcslen.c, test-strnlen.c and test-wcsnlen.c are
all passing

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 08cbcd4dbc)
2022-05-02 11:51:15 -07:00
Noah Goldstein de7fd57d75 x86: Improve memmove-vec-unaligned-erms.S
This patch changes the condition for copy 4x VEC so that if length is
exactly equal to 4 * VEC_SIZE it will use the 4x VEC case instead of
8x VEC case.

Results For Skylake memcpy-avx2-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 0   , 9.137   , 6.873   , New , 75.22
128 , 7   , 0   , 12.933  , 7.732   , New , 59.79
128 , 0   , 7   , 11.852  , 6.76    , New , 57.04
128 , 7   , 7   , 12.587  , 6.808   , New , 54.09

Results For Icelake memcpy-evex-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 0   , 9.963   , 5.416   , New , 54.36
128 , 7   , 0   , 16.467  , 8.061   , New , 48.95
128 , 0   , 7   , 14.388  , 7.644   , New , 53.13
128 , 7   , 7   , 14.546  , 7.642   , New , 52.54

Results For Tigerlake memcpy-evex-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 0   , 8.979   , 4.95    , New , 55.13
128 , 7   , 0   , 14.245  , 7.122   , New , 50.0
128 , 0   , 7   , 12.668  , 6.675   , New , 52.69
128 , 7   , 7   , 13.042  , 6.802   , New , 52.15

Results For Skylake memmove-avx2-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 32  , 6.181   , 5.691   , New , 92.07
128 , 32  , 0   , 6.165   , 5.752   , New , 93.3
128 , 0   , 7   , 13.923  , 9.37    , New , 67.3
128 , 7   , 0   , 12.049  , 10.182  , New , 84.5

Results For Icelake memmove-evex-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 32  , 5.479   , 4.889   , New , 89.23
128 , 32  , 0   , 5.127   , 4.911   , New , 95.79
128 , 0   , 7   , 18.885  , 13.547  , New , 71.73
128 , 7   , 0   , 15.565  , 14.436  , New , 92.75

Results For Tigerlake memmove-evex-erms
size, al1 , al2 , Cur T   , New T   , Win , New / Cur
128 , 0   , 32  , 5.275   , 4.815   , New , 91.28
128 , 32  , 0   , 5.376   , 4.565   , New , 84.91
128 , 0   , 7   , 19.426  , 14.273  , New , 73.47
128 , 7   , 0   , 15.924  , 14.951  , New , 93.89

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 1b992204f6)
2022-05-02 11:51:05 -07:00
Noah Goldstein 6903448d93 x86: Improve memset-vec-unaligned-erms.S
No bug. This commit makes a few small improvements to
memset-vec-unaligned-erms.S. The changes are 1) only aligning to 64
instead of 128. Either alignment will perform equally well in a loop
and 128 just increases the odds of having to do an extra iteration
which can be significant overhead for small values. 2) Align some
targets and the loop. 3) Remove an ALU from the alignment process. 4)
Reorder the last 4x VEC so that they are stored after the loop. 5)
Move the condition for leq 8x VEC to before the alignment
process. test-memset and test-wmemset are both passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6abf27980a)
2022-05-02 11:50:57 -07:00
Noah Goldstein 903190e981 x86: Optimize memcmp-evex-movbe.S
No bug. This commit optimizes memcmp-evex.S. The optimizations include
adding a new vec compare path for small sizes, reorganizing the entry
control flow, removing some unnecissary ALU instructions from the main
loop, and most importantly replacing the heavy use of vpcmp + kand
logic with vpxor + vptern. test-memcmp and test-wmemcmp are both
passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 4ad473e97a)
2022-05-02 11:50:48 -07:00
Noah Goldstein a44a43e998 x86: Optimize memcmp-avx2-movbe.S
No bug. This commit optimizes memcmp-avx2.S. The optimizations include
adding a new vec compare path for small sizes, reorganizing the entry
control flow, and removing some unnecissary ALU instructions from the
main loop. test-memcmp and test-wmemcmp are both passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 16d12015c5)
2022-05-02 11:50:40 -07:00
Noah Goldstein abb0dc2f3a x86: Add EVEX optimized memchr family not safe for RTM
No bug.

This commit adds a new implementation for EVEX memchr that is not safe
for RTM because it uses vzeroupper. The benefit is that by using
ymm0-ymm15 it can use vpcmpeq and vpternlogd in the 4x loop which is
faster than the RTM safe version which cannot use vpcmpeq because
there is no EVEX encoding for the instruction. All parts of the
implementation aside from the 4x loop are the same for the two
versions and the optimization is only relevant for large sizes.

Tigerlake:
size  , algn  , Pos   , Cur T , New T , Win     , Dif
512   , 6     , 192   , 9.2   , 9.04  , no-RTM  , 0.16
512   , 7     , 224   , 9.19  , 8.98  , no-RTM  , 0.21
2048  , 0     , 256   , 10.74 , 10.54 , no-RTM  , 0.2
2048  , 0     , 512   , 14.81 , 14.87 , RTM     , 0.06
2048  , 0     , 1024  , 22.97 , 22.57 , no-RTM  , 0.4
2048  , 0     , 2048  , 37.49 , 34.51 , no-RTM  , 2.98   <--

Icelake:
size  , algn  , Pos   , Cur T , New T , Win     , Dif
512   , 6     , 192   , 7.6   , 7.3   , no-RTM  , 0.3
512   , 7     , 224   , 7.63  , 7.27  , no-RTM  , 0.36
2048  , 0     , 256   , 8.48  , 8.38  , no-RTM  , 0.1
2048  , 0     , 512   , 11.57 , 11.42 , no-RTM  , 0.15
2048  , 0     , 1024  , 17.92 , 17.38 , no-RTM  , 0.54
2048  , 0     , 2048  , 30.37 , 27.34 , no-RTM  , 3.03   <--

test-memchr, test-wmemchr, and test-rawmemchr are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 104c7b1967)
2022-05-02 11:50:27 -07:00
H.J. Lu 6d74f1b712 x86: Set rep_movsb_threshold to 2112 on processors with FSRM
The glibc memcpy benchmark on Intel Core i7-1065G7 (Ice Lake) showed
that REP MOVSB became faster after 2112 bytes:

                                      Vector Move       REP MOVSB
length=2112, align1=0, align2=0:        24.20             24.40
length=2112, align1=1, align2=0:        26.07             23.13
length=2112, align1=0, align2=1:        27.18             28.13
length=2112, align1=1, align2=1:        26.23             25.16
length=2176, align1=0, align2=0:        23.18             22.52
length=2176, align1=2, align2=0:        25.45             22.52
length=2176, align1=0, align2=2:        27.14             27.82
length=2176, align1=2, align2=2:        22.73             25.56
length=2240, align1=0, align2=0:        24.62             24.25
length=2240, align1=3, align2=0:        29.77             27.15
length=2240, align1=0, align2=3:        35.55             29.93
length=2240, align1=3, align2=3:        34.49             25.15
length=2304, align1=0, align2=0:        34.75             26.64
length=2304, align1=4, align2=0:        32.09             22.63
length=2304, align1=0, align2=4:        28.43             31.24

Use REP MOVSB for data size > 2112 bytes in memcpy on processors with
fast short REP MOVSB (FSRM).

	* sysdeps/x86/dl-cacheinfo.h (dl_init_cacheinfo): Set
	rep_movsb_threshold to 2112 on processors with fast short REP
	MOVSB (FSRM).

(cherry picked from commit cf2c57526b)
2022-05-02 11:50:18 -07:00
Noah Goldstein 21252de9ce x86: Optimize strchr-evex.S
No bug. This commit optimizes strchr-evex.S. The optimizations are
mostly small things such as save an ALU in the alignment process,
saving a few instructions in the loop return. The one significant
change is saving 2 instructions in the 4x loop. test-strchr,
test-strchrnul, test-wcschr, and test-wcschrnul are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 7f3e7c262c)
2022-05-02 11:50:10 -07:00
Noah Goldstein 8a1e30d13c x86: Optimize strchr-avx2.S
No bug. This commit optimizes strchr-avx2.S. The optimizations are all
small things such as save an ALU in the alignment process, saving a
few instructions in the loop return, saving some bytes in the main
loop, and increasing the ILP in the return cases. test-strchr,
test-strchrnul, test-wcschr, and test-wcschrnul are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit ccabe7971f)
2022-05-02 11:50:00 -07:00
Noah Goldstein d130da85f3 x86: Optimize less_vec evex and avx512 memset-vec-unaligned-erms.S
No bug. This commit adds optimized cased for less_vec memset case that
uses the avx512vl/avx512bw mask store avoiding the excessive
branches. test-memset and test-wmemset are passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit f53790272c)
2022-05-02 11:49:50 -07:00
H.J. Lu 2763627abe x86-64: Require BMI2 for strchr-avx2.S
Since strchr-avx2.S updated by

commit 1f745ecc21
Author: noah <goldstein.w.n@gmail.com>
Date:   Wed Feb 3 00:38:59 2021 -0500

    x86-64: Refactor and improve performance of strchr-avx2.S

uses sarx:

c4 e2 72 f7 c0       	sarx   %ecx,%eax,%eax

for strchr-avx2 family functions, require BMI2 in ifunc-impl-list.c and
ifunc-avx2.h.

(cherry picked from commit 83c5b36822)
2022-05-02 11:47:40 -07:00
noah e2afbc1ed8 x86: Update large memcpy case in memmove-vec-unaligned-erms.S
No Bug. This commit updates the large memcpy case (no overlap). The
update is to perform memcpy on either 2 or 4 contiguous pages at
once. This 1) helps to alleviate the affects of false memory aliasing
when destination and source have a close 4k alignment and 2) In most
cases and for most DRAM units is a modestly more efficient access
pattern. These changes are a clear performance improvement for
VEC_SIZE =16/32, though more ambiguous for VEC_SIZE=64. test-memcpy,
test-memccpy, test-mempcpy, test-memmove, and tst-memmove-overflow all
pass.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 1a8605b6cd)
2022-05-02 11:47:29 -07:00
noah f1e050f6c4 x86-64: Refactor and improve performance of strchr-avx2.S
No bug. Just seemed the performance could be improved a bit. Observed
and expected behavior are unchanged. Optimized body of main
loop. Updated page cross logic and optimized accordingly. Made a few
minor instruction selection modifications. No regressions in test
suite. Both test-strchrnul and test-strchr passed.

(cherry picked from commit 1f745ecc21)
2022-05-02 11:46:19 -07:00
Sajan Karumanchi 374d54d0a0 x86: Adding an upper bound for Enhanced REP MOVSB.
In the process of optimizing memcpy for AMD machines, we have found the
vector move operations are outperforming enhanced REP MOVSB for data
transfers above the L2 cache size on Zen3 architectures.
To handle this use case, we are adding an upper bound parameter on
enhanced REP MOVSB:'__x86_rep_movsb_stop_threshold'.
As per large-bench results, we are configuring this parameter to the
L2 cache size for AMD machines and applicable from Zen3 architecture
supporting the ERMS feature.
For architectures other than AMD, it is the computed value of
non-temporal threshold parameter.

Reviewed-by: Premachandra Mallappa <premachandra.mallappa@amd.com>
(cherry picked from commit 6e02b3e932)
2022-05-02 11:29:31 -07:00
Stefan Liebler 5eddc29c92 S390: Add new s390 platform z16.
The new IBM z16 is added to platform string array.
The macro _DL_PLATFORMS_COUNT is incremented.

_dl_hwcaps_subdir is extended by "z16" if HWCAP_S390_VXRS_PDE2
is set. HWCAP_S390_NNPA is not tested in _dl_hwcaps_subdirs_active
as those instructions may be replaced or removed in future.

tst-glibc-hwcaps.c is extended in order to test z16 via new marker5.

A fatal glibc error is dumped if glibc was build with architecture
level set for z16, but run on an older machine. (See dl-hwcap-check.h)

(cherry picked from commit 2376944b9e)
2022-04-14 14:20:47 +02:00
John David Anglin c78ad8eb47 hppa: Use END instead of PSEUDO_END in swapcontext.S
(cherry picked from commit 7a5c440102)
2022-03-15 23:17:44 +00:00
John David Anglin 32f74d4f14 hppa: Implement swapcontext in assembler (bug 28960)
When swapcontext.c is compiled without -g, the following error occurs:
Error: CFI instruction used without previous .cfi_startproc

Fix by converting swapcontext routine to assembler.

(cherry picked from commit 738ee53f0c)
2022-03-15 23:17:44 +00:00
John David Anglin baa74e8589 hppa: Fix warnings from _dl_lookup_address
This change fixes two warnings from _dl_lookup_address.

The first warning comes from dropping the volatile keyword from
desc in the call to _dl_read_access_allowed.  We now have a full
atomic barrier between loading desc[0] and the access check, so
desc no longer needs to be declared as volatile.

The second warning comes from the implicit declaration of
_dl_fix_reloc_arg.  This is fixed by including dl-runtime.h and
declaring _dl_fix_reloc_arg in dl-runtime.h.

(cherry picked from commit 6c9c230765)
2022-03-08 13:34:06 +00:00
John David Anglin 6d9525b620 nptl: Fix cleanups for stack grows up [BZ# 28899]
_STACK_GROWS_DOWN is defined to 0 when the stack grows up.  The
code in unwind.c used `#ifdef _STACK_GROWS_DOWN' to selct the
stack grows down define for FRAME_LEFT.  As a result, the
_STACK_GROWS_DOWN define was always selected and cleanups were
incorrectly sequenced when the stack grows up.

(cherry picked from commit 2bbc694df2)
2022-03-08 13:34:06 +00:00
John David Anglin 8f56ecc19b hppa: Revise gettext trampoline design
The current getcontext return trampoline is overly complex and it
unnecessarily clobbers several registers.  By saving the context
pointer (r26) in the context, __getcontext_ret can restore any
registers not restored by setcontext.  This allows getcontext to
save and restore the entire register context present when getcontext
is entered.  We use the unused oR0 context slot for the return
from __getcontext_ret.

While this is not directly useful in C, it can be exploited in
assembly code.  Registers r20, r23, r24 and r25 are not clobbered
in the call path to getcontext.  This allows a small simplification
of swapcontext.

It also allows saving and restoring the 6-bit SAR register in the
LSB of the oSAR context slot.  The getcontext flag value can be
stored in the MSB of the oSAR slot.

(cherry picked from commit 9e7e5fda38)
2022-03-08 13:34:06 +00:00
John David Anglin ea94346dbe hppa: Fix swapcontext
This change fixes the failure of stdlib/tst-setcontext2 and
stdlib/tst-setcontext7 on hppa.  The implementation of swapcontext
in C is broken.  C saves the return pointer (rp) and any non
call-clobbered registers (in this case r3, r4 and r5) on the
stack.  However, the setcontext call in swapcontext pops the
stack and subsequent calls clobber the saved registers.  When
the context in oucp is restored, both tests fault.

Here we rewrite swapcontext in assembly code to avoid using
the stack for register values that need to be used after
restoration.  The getcontext and setcontext routines are
revised to save and restore register ret1 for normal returns.
We copy the oucp pointer to ret1.  This allows access to
the old context after calling getcontext and setcontext.

(cherry picked from commit 71b108d7eb)
2022-03-08 13:34:05 +00:00
John David Anglin aeab7584c2 Fix elf/tst-audit2 on hppa
The test elf/tst-audit2 fails on hppa with a segmentation fault in the
long branch stub used to call malloc from calloc.  This occurs because
the test is not a PIC executable and calloc is called from the dynamic
linker before the dp register is initialized in _dl_start_user.

The fix is to move the dp register initialization into
elf_machine_runtime_setup.  Since the address of $global$ can't be
loaded directly, we continue to use the DT_PLTGOT value from the
the main_map to initialize dp.  Since l_main_map is not available
in v2.34 and earlier, we use a new function, elf_machine_main_map,
to find the main map.

(cherry picked from commit 3be79b72d5)
2022-03-08 13:34:05 +00:00
H.J. Lu f341ab08fc NEWS: Add a bug fix entry for BZ #28896 2022-02-18 19:09:52 -08:00
Noah Goldstein 24e95955aa x86: Fix TEST_NAME to make it a string in tst-strncmp-rtm.c
Previously TEST_NAME was passing a function pointer. This didn't fail
because of the -Wno-error flag (to allow for overflow sizes passed
to strncmp/wcsncmp)

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit b98d0bbf74)
2022-02-18 15:40:50 -08:00
Noah Goldstein 6f8e99b567 x86: Test wcscmp RTM in the wcsncmp overflow case [BZ #28896]
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
not checks around vzeroupper and would trigger spurious
aborts. This commit fixes that.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
AVX2 machines with and without RTM.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 7835d611af)
2022-02-18 15:40:44 -08:00
Noah GoldsteinandH.J. Lu a3cd0fe201 x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ #28896]
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
not checks around vzeroupper and would trigger spurious
aborts. This commit fixes that.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
AVX2 machines with and without RTM.

Co-authored-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit c627209832)
2022-02-18 15:40:38 -08:00
H.J. Lu cb922428dc string: Add a testcase for wcsncmp with SIZE_MAX [BZ #28755]
Verify that wcsncmp (L("abc"), L("abd"), SIZE_MAX) == 0.  The new test
fails without

commit ddf0992cf5
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Sun Jan 9 16:02:21 2022 -0600

    x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]

and

commit 7e08db3359
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Sun Jan 9 16:02:28 2022 -0600

    x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755]

This is for BZ #28755.

Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>

(cherry picked from commit aa5a720056)
2022-02-17 11:22:55 -08:00
H.J. Lu 211cce703d <bits/platform/x86.h>: Correct x86_cpu_TBM
x86_cpu_TBM should be x86_cpu_index_80000001_ecx + 21.

(cherry picked from commit ba230b6387)
2022-02-16 16:09:07 -08:00
Florian Weimer 55446dd8a2 socket: Do not use AF_NETLINK in __opensock
It is not possible to use interface ioctls with netlink sockets
on all Linux kernels.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit 3d981795cd)
2022-02-03 20:04:32 +01:00
Samuel Thibault 9495d729f6 hurd if_index: Explicitly use AF_INET for if index discovery
5bf07e1b3a ("Linux: Simplify __opensock and fix race condition [BZ #28353]")
made __opensock try NETLINK then UNIX then INET. On the Hurd, only INET
knows about network interfaces, so better actually specify that in
if_index.

(cherry picked from commit 1d3decee99)
2022-02-03 20:04:31 +01:00
Florian Weimer 78d25827ae Linux: Simplify __opensock and fix race condition [BZ #28353]
AF_NETLINK support is not quite optional on modern Linux systems
anymore, so it is likely that the first attempt will always succeed.
Consequently, there is no need to cache the result.  Keep AF_UNIX
and the Internet address families as a fallback, for the rare case
that AF_NETLINK is missing.  The other address families previously
probed are totally obsolete be now, so remove them.

Use this simplified version as the generic implementation, disabling
Netlink support as needed.

(cherry picked from commit 5bf07e1b3a)
2022-02-03 20:04:27 +01:00
H.J. Lu 1956ad4930 x86-64: Test strlen and wcslen with 0 in the RSI register [BZ #28064]
commit 6f573a27b6
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Wed Jun 23 01:19:34 2021 -0400

    x86-64: Add wcslen optimize for sse4.1

added wcsnlen-sse4.1 to the wcslen ifunc implementation list.  Since the
random value in the the RSI register is larger than the wide-character
string length in the existing wcslen test, it didn't trigger the wcslen
test failure.  Add a test to force 0 into the RSI register before calling
wcslen.

(cherry picked from commit a6e7c3745d)
2022-02-01 11:53:21 -08:00
Noah Goldstein 260360e89b x86: Remove wcsnlen-sse4_1 from wcslen ifunc-impl-list [BZ #28064]
The following commit

commit 6f573a27b6
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Wed Jun 23 01:19:34 2021 -0400

    x86-64: Add wcslen optimize for sse4.1

Added wcsnlen-sse4.1 to the wcslen ifunc implementation list and did
not add wcslen-sse4.1 to wcslen ifunc implementation list. This commit
fixes that by removing wcsnlen-sse4.1 from the wcslen ifunc
implementation list and adding wcslen-sse4.1 to the ifunc
implementation list.

Testing:
test-wcslen.c, test-rsi-wcslen.c, and test-rsi-strlen.c are passing as
well as all other tests in wcsmbs and string.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 0679442def)
2022-02-01 11:43:59 -08:00
H.J. Lu 1b8f2456b9 x86: Use CHECK_FEATURE_PRESENT to check HLE [BZ #27398]
HLE is disabled on blacklisted CPUs.  Use CHECK_FEATURE_PRESENT, instead
of CHECK_FEATURE_ACTIVE, to check HLE.

(cherry picked from commit 501246c5e2)
2022-02-01 06:07:32 -08:00
H.J. Lu 54fdfa2b33 x86: Black list more Intel CPUs for TSX [BZ #27398]
Disable TSX and enable RTM_ALWAYS_ABORT for Intel CPUs listed in:

https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html

This fixes BZ #27398.

Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 1e000d3d33)
2022-02-01 06:05:23 -08:00
H.J. Lu 0a5f5e2dc1 x86: Check RTM_ALWAYS_ABORT for RTM [BZ #28033]
From

https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html

* Intel TSX will be disabled by default.
* The processor will force abort all Restricted Transactional Memory (RTM)
  transactions by default.
* A new CPUID bit CPUID.07H.0H.EDX[11](RTM_ALWAYS_ABORT) will be enumerated,
  which is set to indicate to updated software that the loaded microcode is
  forcing RTM abort.
* On processors that enumerate support for RTM, the CPUID enumeration bits
  for Intel TSX (CPUID.07H.0H.EBX[11] and CPUID.07H.0H.EBX[4]) continue to
  be set by default after microcode update.
* Workloads that were benefited from Intel TSX might experience a change
  in performance.
* System software may use a new bit in Model-Specific Register (MSR) 0x10F
  TSX_FORCE_ABORT[TSX_CPUID_CLEAR] functionality to clear the Hardware Lock
  Elision (HLE) and RTM bits to indicate to software that Intel TSX is
  disabled.

1. Add RTM_ALWAYS_ABORT to CPUID features.
2. Set RTM usable only if RTM_ALWAYS_ABORT isn't set.  This skips the
string/tst-memchr-rtm etc. testcases on the affected processors, which
always fail after a microcde update.
3. Check RTM feature, instead of usability, against /proc/cpuinfo.

This fixes BZ #28033.

(cherry picked from commit ea8e465a6b)
2022-02-01 06:04:09 -08:00
H.J. Lu 5cb6edb6cd x86: Copy IBT and SHSTK usable only if CET is enabled
IBT and SHSTK usable bits are copied from CPUID feature bits and later
cleared if kernel doesn't support CET.  Copy IBT and SHSTK usable only
if CET is enabled so that they aren't set on CET capable processors
with non-CET enabled glibc.

(cherry picked from commit ea26ff0322)
2022-02-01 05:59:12 -08:00
H.J. Lu 3e2a15c666 x86-64: Require BMI2 for __strlen_evex and __strnlen_evex
Since __strlen_evex and __strnlen_evex added by

commit 1fd8c163a8
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Mar 5 06:24:52 2021 -0800

    x86-64: Add ifunc-avx2.h functions with 256-bit EVEX

use sarx:

c4 e2 6a f7 c0       	sarx   %edx,%eax,%eax

require BMI2 for __strlen_evex and __strnlen_evex in ifunc-impl-list.c.
ifunc-avx2.h already requires BMI2 for EVEX implementation.

(cherry picked from commit 55bf411b45)
2022-01-27 15:28:42 -08:00
H.J. Lu 25941de34e NEWS: Add a bug fix entry for BZ #27974 2022-01-27 14:13:35 -08:00
Noah Goldstein 2b00ee820a String: Add overflow tests for strnlen, memchr, and strncat [BZ #27974]
This commit adds tests for a bug in the wide char variant of the
functions where the implementation may assume that maxlen for wcsnlen
or n for wmemchr/strncat will not overflow when multiplied by
sizeof(wchar_t).

These tests show the following implementations failing on x86_64:

wcsnlen-sse4_1
wcsnlen-avx2

wmemchr-sse2
wmemchr-avx2

strncat would fail as well if it where on a system that prefered
either of the wcsnlen implementations that failed as it relies on
wcsnlen.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit da5a6fba0f)
2022-01-27 14:13:35 -08:00
Noah Goldstein 8a3a0177c7 x86: Optimize strlen-evex.S
No bug. This commit optimizes strlen-evex.S. The
optimizations are mostly small things but they add up to roughly
10-30% performance improvement for strlen. The results for strnlen are
bit more ambiguous. test-strlen, test-strnlen, test-wcslen, and
test-wcsnlen are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit 4ba6558684)
2022-01-27 14:09:24 -08:00
Noah Goldstein cef3bffade x86: Fix overflow bug in wcsnlen-sse4_1 and wcsnlen-avx2 [BZ #27974]
This commit fixes the bug mentioned in the previous commit.

The previous implementations of wmemchr in these files relied
on maxlen * sizeof(wchar_t) which was not guranteed by the standard.

The new overflow tests added in the previous commit now
pass (As well as all the other tests).

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit a775a7a3eb)
2022-01-27 14:09:24 -08:00
Noah Goldstein 3ac5a7fe8b x86-64: Add wcslen optimize for sse4.1
No bug. This comment adds the ifunc / build infrastructure
necessary for wcslen to prefer the sse4.1 implementation
in strlen-vec.S. test-wcslen.c is passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6f573a27b6)
2022-01-27 14:09:24 -08:00
H.J. Lu 5697e2dda8 x86-64: Move strlen.S to multiarch/strlen-vec.S
Since strlen.S contains SSE2 version of strlen/strnlen and SSE4.1
version of wcslen/wcsnlen, move strlen.S to multiarch/strlen-vec.S
and include multiarch/strlen-vec.S from SSE2 and SSE4.1 variants.
This also removes the unused symbols, __GI___strlen_sse2 and
__GI___wcsnlen_sse4_1.

(cherry picked from commit a0db678071)
2022-01-27 14:09:24 -08:00
Alice Xu 3dea108f60 x86-64: Fix an unknown vector operation in memchr-evex.S
An unknown vector operation occurred in commit 2a76821c30. Fixed it
by using "ymm{k1}{z}" but not "ymm {k1} {z}".

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 6ea916adfa)
2022-01-27 14:09:24 -08:00
Noah Goldstein 355afae940 x86: Optimize memchr-evex.S
No bug. This commit optimizes memchr-evex.S. The optimizations include
replacing some branches with cmovcc, avoiding some branches entirely
in the less_4x_vec case, making the page cross logic less strict,
saving some ALU in the alignment process, and most importantly
increasing ILP in the 4x loop. test-memchr, test-rawmemchr, and
test-wmemchr are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 2a76821c30)
2022-01-27 14:09:24 -08:00
Noah Goldstein b72b89705e x86: Optimize strlen-avx2.S
No bug. This commit optimizes strlen-avx2.S. The optimizations are
mostly small things but they add up to roughly 10-30% performance
improvement for strlen. The results for strnlen are bit more
ambiguous. test-strlen, test-strnlen, test-wcslen, and test-wcsnlen
are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit aaa23c3507)
2022-01-27 12:55:28 -08:00
Noah Goldstein 453ed0a0f2 x86: Fix overflow bug with wmemchr-sse2 and wmemchr-avx2 [BZ #27974]
This commit fixes the bug mentioned in the previous commit.

The previous implementations of wmemchr in these files relied
on n * sizeof(wchar_t) which was not guranteed by the standard.

The new overflow tests added in the previous commit now
pass (As well as all the other tests).

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 645a158978)
2022-01-27 12:54:16 -08:00
Noah Goldstein e09c377806 x86: Optimize memchr-avx2.S
No bug. This commit optimizes memchr-avx2.S. The optimizations include
replacing some branches with cmovcc, avoiding some branches entirely
in the less_4x_vec case, making the page cross logic less strict,
asaving a few instructions the in loop return loop. test-memchr,
test-rawmemchr, and test-wmemchr are all passing.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit acfd088a19)
2022-01-27 12:54:05 -08:00
H.J. Lu 902af2f5ee NEWS: Add a bug fix entry for BZ #27457 2022-01-27 12:20:21 -08:00
Sunil K Pandey 31dd3e3cb3 x86-64: Fix ifdef indentation in strlen-evex.S
Fix some indentations of ifdef in file strlen-evex.S which are off by 1
and confusing to read.

(cherry picked from commit 595c22ecd8)
2022-01-27 10:36:43 -08:00
H.J. Lu d49105cc7a x86-64: Use ZMM16-ZMM31 in AVX512 memmove family functions
Update ifunc-memmove.h to select the function optimized with AVX512
instructions using ZMM16-ZMM31 registers to avoid RTM abort with usable
AVX512VL since VZEROUPPER isn't needed at function exit.

(cherry picked from commit e4fda46310)
2022-01-27 10:36:43 -08:00
H.J. Lu 763cea698b x86-64: Use ZMM16-ZMM31 in AVX512 memset family functions
Update ifunc-memset.h/ifunc-wmemset.h to select the function optimized
with AVX512 instructions using ZMM16-ZMM31 registers to avoid RTM abort
with usable AVX512VL and AVX512BW since VZEROUPPER isn't needed at
function exit.

(cherry picked from commit 4e2d8f3527)
2022-01-27 10:36:43 -08:00
H.J. Lu 82f1ba9af7 x86: Add string/memory function tests in RTM region
At function exit, AVX optimized string/memory functions have VZEROUPPER
which triggers RTM abort.   When such functions are called inside a
transactionally executing RTM region, RTM abort causes severe performance
degradation.  Add tests to verify that string/memory functions won't
cause RTM abort in RTM region.

(cherry picked from commit 4bd660be40)
2022-01-27 10:36:43 -08:00
H.J. Lu 0598a25cbe x86-64: Add AVX optimized string/memory functions for RTM
Since VZEROUPPER triggers RTM abort while VZEROALL won't, select AVX
optimized string/memory functions with

	xtest
	jz	1f
	vzeroall
	ret
1:
	vzeroupper
	ret

at function exit on processors with usable RTM, but without 256-bit EVEX
instructions to avoid VZEROUPPER inside a transactionally executing RTM
region.

(cherry picked from commit 7ebba91361)
2022-01-27 10:36:43 -08:00
H.J. Lu 15bae38c8b x86-64: Add memcmp family functions with 256-bit EVEX
Update ifunc-memcmp.h to select the function optimized with 256-bit EVEX
instructions using YMM16-YMM31 registers to avoid RTM abort with usable
AVX512VL, AVX512BW and MOVBE since VZEROUPPER isn't needed at function
exit.

(cherry picked from commit 91264fe357)
2022-01-27 10:36:43 -08:00
H.J. Lu 47bf9f38bb x86-64: Add memset family functions with 256-bit EVEX
Update ifunc-memset.h/ifunc-wmemset.h to select the function optimized
with 256-bit EVEX instructions using YMM16-YMM31 registers to avoid RTM
abort with usable AVX512VL and AVX512BW since VZEROUPPER isn't needed at
function exit.

(cherry picked from commit 1b968b6b9b)
2022-01-27 10:36:43 -08:00
H.J. Lu 1697e739ef x86-64: Add memmove family functions with 256-bit EVEX
Update ifunc-memmove.h to select the function optimized with 256-bit EVEX
instructions using YMM16-YMM31 registers to avoid RTM abort with usable
AVX512VL since VZEROUPPER isn't needed at function exit.

(cherry picked from commit 63ad43566f)
2022-01-27 10:36:43 -08:00
H.J. Lu 06d1aed51b x86-64: Add strcpy family functions with 256-bit EVEX
Update ifunc-strcpy.h to select the function optimized with 256-bit EVEX
instructions using YMM16-YMM31 registers to avoid RTM abort with usable
AVX512VL and AVX512BW since VZEROUPPER isn't needed at function exit.

(cherry picked from commit 525bc2a32c)
2022-01-27 10:36:43 -08:00
H.J. Lu 9cee072f8f x86-64: Add ifunc-avx2.h functions with 256-bit EVEX
Update ifunc-avx2.h, strchr.c, strcmp.c, strncmp.c and wcsnlen.c to
select the function optimized with 256-bit EVEX instructions using
YMM16-YMM31 registers to avoid RTM abort with usable AVX512VL, AVX512BW
and BMI2 since VZEROUPPER isn't needed at function exit.

For strcmp/strncmp, prefer AVX2 strcmp/strncmp if Prefer_AVX2_STRCMP
is set.

(cherry picked from commit 1fd8c163a8)
2022-01-27 10:36:43 -08:00
H.J. Lu f0a2b67147 x86: Set Prefer_No_VZEROUPPER and add Prefer_AVX2_STRCMP
1. Set Prefer_No_VZEROUPPER if RTM is usable to avoid RTM abort triggered
by VZEROUPPER inside a transactionally executing RTM region.
2. Since to compare 2 32-byte strings, 256-bit EVEX strcmp requires 2
loads, 3 VPCMPs and 2 KORDs while AVX2 strcmp requires 1 load, 2 VPCMPEQs,
1 VPMINU and 1 VPMOVMSKB, AVX2 strcmp is faster than EVEX strcmp.  Add
Prefer_AVX2_STRCMP to prefer AVX2 strcmp family functions.

(cherry picked from commit 1da50d4bda)
2022-01-27 10:36:43 -08:00
H.J. Lu a744a0a3fe test-strnlen.c: Check that strnlen won't go beyond the maximum length
Place strings ending at page boundary without the null byte.  If an
implementation goes beyond EXP_LEN, it will trigger the segfault.

(cherry picked from commit cb882b21b6)
2022-01-27 09:09:26 -08:00
H.J. Lu 6b7b6c7514 test-strnlen.c: Initialize wchar_t string with wmemset [BZ #27655]
Use wmemset to initialize wchar_t string.

(cherry picked from commit 86859b7e58)
2022-01-27 09:06:19 -08:00
H.J. Lu 86c153d092 NEWS: Add a bug fix entry for BZ #28755 2022-01-26 20:28:51 -08:00
Noah Goldstein 3d52239b30 x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]
Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to
__wcscmp_avx2. For x86_64 this covers the entire address range so any
length larger could not possibly be used to bound `s1` or `s2`.

test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit ddf0992cf5)
(cherry picked from commit b50d5b746c)
2022-01-26 20:26:15 -08:00
Szabolcs Nagy d251ad533e aarch64: align stack in clone [BZ #27939]
The AArch64 PCS requires 16 byte aligned stack.  Previously if the
caller passed an unaligned stack to clone then the child crashed.

Fixes bug 27939.

(cherry picked from commit 3842ba4949)
2022-01-26 22:51:14 +01:00
Florian Weimer 06ce5fbd6d support: Fix xclone build failures on ia64 and hppa
(cherry picked from commit 97ed4749be)
2022-01-26 18:50:39 +01:00
Florian Weimer 48d9161e02 Linux: Detect user namespace support in io/tst-getcwd-smallbuff
Otherwise the test fails with certain container runtimes.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 5b8e7980c5)
2022-01-24 22:00:59 +01:00
Siddhesh Poyarekar 41980af2d7 realpath: Avoid overwriting preexisting error (CVE-2021-3998)
Set errno and failure for paths that are too long only if no other error
occurred earlier.

Related: BZ #28770

Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 84d2d0fe20)
2022-01-24 17:30:16 +01:00
Siddhesh Poyarekar bcdde07537 getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)
No valid path returned by getcwd would fit into 1 byte, so reject the
size early and return NULL with errno set to ERANGE.  This change is
prompted by CVE-2021-3999, which describes a single byte buffer
underflow and overflow when all of the following conditions are met:

- The buffer size (i.e. the second argument of getcwd) is 1 byte
- The current working directory is too long
- '/' is also mounted on the current working directory

Sequence of events:

- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG
  because the linux kernel checks for name length before it checks
  buffer size

- The code falls back to the generic getcwd in sysdeps/posix

- In the generic func, the buf[0] is set to '\0' on line 250

- this while loop on line 262 is bypassed:

    while (!(thisdev == rootdev && thisino == rootino))

  since the rootfs (/) is bind mounted onto the directory and the flow
  goes on to line 449, where it puts a '/' in the byte before the
  buffer.

- Finally on line 458, it moves 2 bytes (the underflowed byte and the
  '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow.

- buf is returned on line 469 and errno is not set.

This resolves BZ #28769.

Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Signed-off-by: Qualys Security Advisory <qsa@qualys.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 23e0e8f5f1)
2022-01-24 16:46:06 +01:00
Adhemerval Zanella 46a70c49ba support: Add xclone
It is a wrapper for Linux clone syscall, to simplify the call to the
use only the most common arguments and remove architecture specific
handling (such as ia64 different name and signature).

(cherry picked from commit de8995a2a0)
2022-01-24 16:46:06 +01:00
Siddhesh Poyarekar f63cb3cf72 tst-realpath-toolong: Fix hurd build
Define PATH_MAX to a constant if it isn't already defined, like in hurd.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 976db046bc)
2022-01-24 10:30:01 +01:00
Siddhesh Poyarekar e41e5b97e3 realpath: Set errno to ENAMETOOLONG for result larger than PATH_MAX [BZ #28770]
realpath returns an allocated string when the result exceeds PATH_MAX,
which is unexpected when its second argument is not NULL.  This results
in the second argument (resolved) being uninitialized and also results
in a memory leak since the caller expects resolved to be the same as the
returned value.

Return NULL and set errno to ENAMETOOLONG if the result exceeds
PATH_MAX.  This fixes [BZ #28770], which is CVE-2021-3998.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit ee8d5e33ad)
2022-01-24 10:29:17 +01:00
Siddhesh Poyarekar e081bafcb1 support: Add helpers to create paths longer than PATH_MAX
Add new helpers support_create_and_chdir_toolong_temp_directory and
support_chdir_toolong_temp_directory to create and descend into
directory trees longer than PATH_MAX.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit fb7bff12e8)
2022-01-24 09:25:27 +01:00
Florian Weimer ac148bdd88 elf: Fix glibc-hwcaps priorities with cache flags mismatches [BZ #27046]
If lib->flags (in the cache) did not match GLRO (dl_correct_cache_id),
searching for further glibc-hwcaps entries did not happen, and it
was possible that the best glibc-hwcaps was not found.  By accident,
this causes a test failure for elf/tst-glibc-hwcaps-prepend-cache
on armv7l.

This commit changes the cache lookup logic to continue searching
if (a) no match has been found, (b) a named glibc-hwcaps match
has been found(), or (c) non-glibc-hwcaps match has been found
and the entry flags and cache default flags do not match.

_DL_CACHE_DEFAULT_ID is used instead of GLRO (dl_correct_cache_id)
because the latter is only written once on i386 if loading
of libc.so.5 libraries is selected, so GLRO (dl_correct_cache_id)
should probably removed in a future change.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 66db95b6e8)
2022-01-18 23:10:25 +01:00
Paul A. Clarke 5cab4e3f3a powerpc: Fix unrecognized instruction errors with recent binutils
Recent versions of binutils (with commit
b25f942e18d6ecd7ec3e2d2e9930eb4f996c258a) stopped preserving "sticky"
options across a base `.machine` directive, nullifying the use of
passing "-many" through GCC to the assembler.  As a result, some
instructions which were recognized even under older, more stringent
`.machine` directives become unrecognized instructions in that
context.

In `sysdeps/powerpc/tst-set_ppr.c`, the use of the `mfppr32` extended
mnemonic became unrecognized, as the default compilation with GCC for
32bit powerpc adds a `.machine ppc` in the resulting assembly, so the
command line option `-Wa,-many` is essentially ignored, and the ISA 2.06
instructions and mnemonics, like `mfppr32`, are unrecognized.

The compilation of `sysdeps/powerpc/tst-set_ppr.c` fails with:
Error: unrecognized opcode: `mfppr32'

Add appropriate `.machine` directives in the assembly to bracket the
`mfppr32` instruction.

Part of a 2019 fix (commit 9250e6610f) to
the above test's Makefile to add `-many` to the compilation when GCC
itself stopped passing `-many` to the assember no longer has any effect,
so remove that.

Reported-by: Joseph Myers <joseph@codesourcery.com>
(cherry picked from commit ee874f44fd)
2022-01-18 23:07:17 +01:00
Florian Weimer 0f70b829f8 CVE-2022-23218: Buffer overflow in sunrpc svcunix_create (bug 28768)
The sunrpc function svcunix_create suffers from a stack-based buffer
overflow with overlong pathname arguments.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit f545ad4928)
2022-01-18 10:17:11 +01:00
Florian Weimer 4f4452721d <shlib-compat.h>: Support compat_symbol_reference for _ISOMAC
This is helpful for testing compat symbols in cases where _ISOMAC
is activated implicitly due to -DMODULE_NAME=testsuite and cannot
be disabled easily.

(cherry picked from commit 36f6e40884)
2022-01-18 10:16:55 +01:00
Martin Sebor dae9a8e7f6 sunrpc: Test case for clnt_create "unix" buffer overflow (bug 22542)
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit ef972a4c50)
2022-01-18 07:46:03 +01:00
Florian Weimer 4653cd9e36 CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" (bug 22542)
Processing an overlong pathname in the sunrpc clnt_create function
results in a stack-based buffer overflow.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 226b46770c)
2022-01-18 07:46:02 +01:00
Florian Weimer f10e992e8d socket: Add the __sockaddr_un_set function
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit e368b12f6c)
2022-01-18 07:46:02 +01:00
Aurelien Jarno a51b76b71e x86: use default cache size if it cannot be determined [BZ #28784]
In some cases (e.g QEMU, non-Intel/AMD CPU) the cache information can
not be retrieved and the corresponding values are set to 0.

Commit 2d651eb926 ("x86: Move x86 processor cache info to
cpu_features") changed the behaviour in such case by defining the
__x86_shared_cache_size and __x86_data_cache_size variables to 0 instead
of using the default values. This cause an issue with the i686 SSE2
optimized bzero/routine which assumes that the cache size is at least
128 bytes, and otherwise tries to zero/set the whole address space minus
128 bytes.

Fix that by restoring the original code to only update
__x86_shared_cache_size and __x86_data_cache_size variables if the
corresponding cache sizes are not zero.

Fixes bug 28784
Fixes commit 2d651eb926

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c242fcce06)
2022-01-17 19:49:44 +01:00
Paul A. Clarke 55b99e9ed0 powerpc: Fix unrecognized instruction errors with recent GCC
Recent binutils commit b25f942e18d6ecd7ec3e2d2e9930eb4f996c258a
changes the behavior of `.machine` directives to override, rather
than augment, the base CPU. This can result in _reduced_ functionality
when, for example, compiling for default machine "power8", but explicitly
asking for ".machine power5", which loses Altivec instructions.

In tst-ucontext-ppc64-vscr.c, while the instructions provoking the new
error messages are bracketed by ".machine power5", which is ostensibly
Power ISA 2.03 (POWER5), the POWER5 processor did not support the
VSX subset, so these instructions are not recognized as "power5".

Error: unrecognized opcode: `vspltisb'
Error: unrecognized opcode: `vpkuwus'
Error: unrecognized opcode: `mfvscr'
Error: unrecognized opcode: `stvx'

Manually adding the VSX subset via ".machine altivec" is sufficient.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
(cherry picked from commit 064b475a2e)
2022-01-10 22:50:05 +01:00
Matheus Castanho c493f6a0e4 powerpc64[le]: Allocate extra stack frame on syscall.S
The syscall function does not allocate the extra stack frame for scv like other
assembly syscalls using DO_CALL_SCV. So after commit d120fb9941 changed the
offset that is used to save LR, syscall ended up using an invalid offset,
causing regressions on powerpc64. So make sure the extra stack frame is
allocated in syscall.S as well to make it consistent with other uses of
DO_CALL_SCV and avoid similar issues in the future.

Tested on powerpc, powerpc64, and powerpc64le (with and without scv)

Reviewed-by: Raphael M Zinsly <rzinsly@linux.ibm.com>

(cherry picked from commit ae91d3df24)
2021-12-17 15:57:16 -03:00
Nikita Popov c76a0ba878 gconv: Do not emit spurious NUL character in ISO-2022-JP-3 (bug 28524)
Bugfix 27256 has introduced another issue:
In conversion from ISO-2022-JP-3 encoding, it is possible
to force iconv to emit extra NUL character on internal state reset.
To do this, it is sufficient to feed iconv with escape sequence
which switches active character set.
The simplified check 'data->__statep->__count != ASCII_set'
introduced by the aforementioned bugfix picks that case and
behaves as if '\0' character has been queued thus emitting it.

To eliminate this issue, these steps are taken:
* Restore original condition
'(data->__statep->__count & ~7) != ASCII_set'.
It is necessary since bits 0-2 may contain
number of buffered input characters.
* Check that queued character is not NUL.
Similar step is taken for main conversion loop.

Bundled test case follows following logic:
* Try to convert ISO-2022-JP-3 escape sequence
switching active character set
* Reset internal state by providing NULL as input buffer
* Ensure that nothing has been converted.

Signed-off-by: Nikita Popov <npv1310@gmail.com>
(cherry picked from commit ff012870b2)
2021-12-04 23:04:44 +01:00
Matheus Castanho 1cc490adca powerpc64[le]: Fix CFI and LR save address for asm syscalls [BZ #28532]
Syscalls based on the assembly templates are missing CFI for r31, which gets
clobbered when scv is used, and info for LR is inaccurate, placed in the wrong
LOC and not using the proper offset. LR was also being saved to the callee's
frame, while the ABI mandates it to be saved to the caller's frame. These are
fixed by this commit.

After this change:

$ readelf -wF libc.so.6 | grep 0004b9d4.. -A 7 && objdump --disassemble=kill libc.so.6
00004a48 0000000000000020 00004a4c FDE cie=00000000 pc=000000000004b9d4..000000000004ba3c
   LOC           CFA      r31   ra
000000000004b9d4 r1+0     u     u
000000000004b9e4 r1+48    u     u
000000000004b9e8 r1+48    c-16  u
000000000004b9fc r1+48    c-16  c+16
000000000004ba08 r1+48    c-16
000000000004ba18 r1+48    u
000000000004ba1c r1+0     u

libc.so.6:     file format elf64-powerpcle

Disassembly of section .text:

000000000004b9d4 <kill>:
   4b9d4:       1f 00 4c 3c     addis   r2,r12,31
   4b9d8:       2c c3 42 38     addi    r2,r2,-15572
   4b9dc:       25 00 00 38     li      r0,37
   4b9e0:       d1 ff 21 f8     stdu    r1,-48(r1)
   4b9e4:       20 00 e1 fb     std     r31,32(r1)
   4b9e8:       98 8f ed eb     ld      r31,-28776(r13)
   4b9ec:       10 00 ff 77     andis.  r31,r31,16
   4b9f0:       1c 00 82 41     beq     4ba0c <kill+0x38>
   4b9f4:       a6 02 28 7d     mflr    r9
   4b9f8:       40 00 21 f9     std     r9,64(r1)
   4b9fc:       01 00 00 44     scv     0
   4ba00:       40 00 21 e9     ld      r9,64(r1)
   4ba04:       a6 03 28 7d     mtlr    r9
   4ba08:       08 00 00 48     b       4ba10 <kill+0x3c>
   4ba0c:       02 00 00 44     sc
   4ba10:       00 00 bf 2e     cmpdi   cr5,r31,0
   4ba14:       20 00 e1 eb     ld      r31,32(r1)
   4ba18:       30 00 21 38     addi    r1,r1,48
   4ba1c:       18 00 96 41     beq     cr5,4ba34 <kill+0x60>
   4ba20:       01 f0 20 39     li      r9,-4095
   4ba24:       40 48 23 7c     cmpld   r3,r9
   4ba28:       20 00 e0 4d     bltlr+
   4ba2c:       d0 00 63 7c     neg     r3,r3
   4ba30:       08 00 00 48     b       4ba38 <kill+0x64>
   4ba34:       20 00 e3 4c     bnslr+
   4ba38:       c8 32 fe 4b     b       2ed00 <__syscall_error>
        ...
   4ba44:       40 20 0c 00     .long 0xc2040
   4ba48:       68 00 00 00     .long 0x68
   4ba4c:       06 00 5f 5f     rlwnm   r31,r26,r0,0,3
   4ba50:       6b 69 6c 6c     xoris   r12,r3,26987

(cherry picked from commit d120fb9941)
2021-11-30 15:33:02 -03:00
Florian Weimer f9592d65f2 nptl: Do not set signal mask on second setjmp return [BZ #28607]
__libc_signal_restore_set was in the wrong place: It also ran
when setjmp returned the second time (after pthread_exit or
pthread_cancel).  This is observable with blocked pending
signals during thread exit.

Fixes commit b3cae39dcb
("nptl: Start new threads with all signals blocked [BZ #25098]").

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit e186fc5a31)
2021-11-24 10:01:01 +01:00
Adhemerval Zanella 94c91ce231 support: Add xpthread_kill
Checked on x86_64-linux-gnu.

(cherry picked from commit 0280b390fb)
2021-11-24 10:01:01 +01:00
Florian Weimer 9edf29fd72 s390: Use long branches across object boundaries (jgh instead of jh)
Depending on the layout chosen by the linker, the 16-bit displacement
of the jh instruction is insufficient to reach the target label.

Analysis of the linker failure was carried out by Nick Clifton.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Stefan Liebler <stli@linux.ibm.com>
(cherry picked from commit 98966749f2)
2021-11-10 15:22:51 +01:00
H.J. Lu 6090cf1330 elf: Replace nsid with args.nsid [BZ #27609]
commit ec935dea63
Author: Florian Weimer <fweimer@redhat.com>
Date:   Fri Apr 24 22:31:15 2020 +0200

    elf: Implement __libc_early_init

has

@@ -856,6 +876,11 @@ no more namespaces available for dlmopen()"));
   /* See if an error occurred during loading.  */
   if (__glibc_unlikely (exception.errstring != NULL))
     {
+      /* Avoid keeping around a dangling reference to the libc.so link
+   map in case it has been cached in libc_map.  */
+      if (!args.libc_already_loaded)
+  GL(dl_ns)[nsid].libc_map = NULL;
+

do_dlopen calls _dl_open with nsid == __LM_ID_CALLER (-2), which calls
dl_open_worker with args.nsid = nsid.  dl_open_worker updates args.nsid
if it is __LM_ID_CALLER.  After dl_open_worker returns, it is wrong to
use nsid.

Replace nsid with args.nsid after dl_open_worker returns.  This fixes
BZ #27609.

(cherry picked from commit 1e1ecea62e)
2021-10-13 05:29:59 -07:00
Stefan Liebler 4b95183785 S390: Add PCI_MIO and SIE HWCAPs
Both new HWCAPs were introduced in these kernel commits:
- 7e8403ecaf884f307b627f3c371475913dd29292
  "s390: add HWCAP_S390_PCI_MIO to ELF hwcaps"
- 7e82523f2583e9813e4109df3656707162541297
  "s390/hwcaps: make sie capability regular hwcap"

Also note that the kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e
"s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros
from "HWCAP_S390_" to "HWCAP_".  For compatibility reasons, we do not
change the prefix in public glibc header file.

(cherry picked from commit f2e06656d0)
2021-10-07 06:58:08 +02:00
Aurelien Jarno d27d1e4d13 posix: Fix attribute access mode on getcwd [BZ #27476]
There is a GNU extension that allows to call getcwd(NULL, >0). It is
described in the documentation, but also directly in the unistd.h
header, just above the declaration.

Therefore the attribute access mode added in commit 06febd8c67
is not correct. Drop it.

(cherry picked from commit 63a788f48a)
2021-09-19 18:47:28 +02:00
Aurelien Jarno 14f2867b57 Fix failing nss/tst-nss-files-hosts-long with local resolver
When a local resolver like unbound is listening on the IPv4 loopback
address 127.0.0.1, the nss/tst-nss-files-hosts-long test fails. This is
due to:
- the default resolver in the absence of resolv.conf being 127.0.0.1
- the default DNS NSS database configuration in the absence of
  nsswitch.conf being 'hosts: dns [!UNAVAIL=return] file'

This causes the requests for 'test4' and 'test6' to first be sent to the
local resolver, which responds with NXDOMAIN in the likely case those
records do no exist. In turn that causes the access to /etc/hosts to be
skipped, which is the purpose of that test.

Fix that by providing a simple nsswitch.conf file forcing access to
/etc/hosts for that test. I have tested that the only changed result in
the testsuite is that test.

(cherry picked from commit 2738480a4b)
2021-09-14 21:03:05 +02:00
Jiaxun Yang 9b01145592 MIPS: Setup errno for {f,l,}xstat
{f,l,}xstat stub for MIPS is using INTERNAL_SYSCALL
to do xstat syscall for glibc ver, However it leaves
errno untouched and thus giving bad errno output.

Setup errno properly when syscall returns non-zero.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

(cherry picked from commit 66016ec8ae)
2021-09-07 10:22:18 -03:00
Aurelien Jarno 9c676ef514 RISC-V: Update rv64 ULPs
Generated on both a Microsemi Polarfire Icicle Kit and a BeagleV
Starlight, resulting in identical ULPs.
2021-09-01 23:52:37 +02:00
Adhemerval Zanella c6cadbf83a linux: Remove shmmax check from tst-sysvshm-linux
The shmmax expected value is tricky to check because kernel clamps it
to INT_MAX in two cases:

  1. Compat symbols with IPC_64, i.e, 32-bit binaries running on 64-bit
     kernels.

  2. Default symbol without IPC_64 (defined as IPC_OLD within Linux) and
     glibc always use IPC_64 for 32-bit ABIs (to support 64-bit time_t).
     It means that 32-bit binaries running on 32-bit kernels will not see
     shmmax being clamped.

And finding out whether the compat symbol is used would require checking
the underlying kernel against the current ABI.  The shmall and shmmni
already provided enough coverage.

Checked on x86_64-linux-gnu and i686-linux-gnu.  It should fix the
tst-sysvshm-linux failures on 32-bit kernels.

(cherry picked from commit 9132010785)
2021-08-22 15:52:53 +02:00
Nikita Popov 22d37364ae librt: add test (bug 28213)
This test implements following logic:
1) Create POSIX message queue.
   Register a notification with mq_notify (using NULL attributes).
   Then immediately unregister the notification with mq_notify.
   Helper thread in a vulnerable version of glibc
   should cause NULL pointer dereference after these steps.
2) Once again, register the same notification.
   Try to send a dummy message.
   Test is considered successfulif the dummy message
   is successfully received by the callback function.

Signed-off-by: Nikita Popov <npv1310@gmail.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 4cc79c2177)
2021-08-17 18:47:03 +05:30
Nikita Popov 27a78fd712 librt: fix NULL pointer dereference (bug 28213)
Helper thread frees copied attribute on NOTIFY_REMOVED message
received from the OS kernel.  Unfortunately, it fails to check whether
copied attribute actually exists (data.attr != NULL).  This worked
earlier because free() checks passed pointer before actually
attempting to release corresponding memory.  But
__pthread_attr_destroy assumes pointer is not NULL.

So passing NULL pointer to __pthread_attr_destroy will result in
segmentation fault.  This scenario is possible if
notification->sigev_notify_attributes == NULL (which means default
thread attributes should be used).

Signed-off-by: Nikita Popov <npv1310@gmail.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit b805aebd42)
2021-08-17 18:46:54 +05:30
Fangrui Song b5711025bc x86_64: Remove unneeded static PIE check for undefined weak diagnostic
https://sourceware.org/bugzilla/show_bug.cgi?id=21782 dropped an ld
diagnostic for R_X86_64_PC32 referencing an undefined weak symbol in
-pie links.  Arguably keeping the diagnostic like other ports is more
correct, since statically resolving movl foo(%rip), %eax to the
link-time zero address produces a corrupted output.

It turns out that --enable-static-pie builds do not depend on the ld
behavior. GCC generates GOT indirection for weak declarations for
-fPIE/-fPIC, so what ld does with the PC-relative relocation doesn't
really matter.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 115d242456)
2021-07-08 21:37:32 -07:00
Andreas Schwab edfd11197e wordexp: handle overflow in positional parameter number (bug 28011)
Use strtoul instead of atoi so that overflow can be detected.

(cherry picked from commit 5adda61f62)
2021-07-06 21:04:00 +02:00
Florian Weimer 58b90461ae elf: Use _dl_catch_error from base namespace in dl-libc.c [BZ #27646]
dlerrror_run in elf/dl-libc.c needs to call GLRO (dl_catch_error)
from the base namespace, just like the exported dlerror
implementation.

Fixes commit b2964eb1d9 ("dlfcn:
Failures after dlmopen should not terminate process [BZ #24772]").

Backport notes: GLRO (dl_catch_error) is replaced with
_dl_catch_error_ptr to preserve _rtld_global_ro layout.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c2059edce2)
2021-06-18 11:42:47 +02:00
Florian Weimer 8c06748c51 Fix use of __pthread_attr_copy in mq_notify (bug 27896)
__pthread_attr_copy can fail and does not initialize the attribute
structure in that case.

If __pthread_attr_copy is never called and there is no allocated
attribute, pthread_attr_destroy should not be called, otherwise
there is a null pointer dereference in rt/tst-mqueue6.

Fixes commit 42d3593505
("Use __pthread_attr_copy in mq_notify (bug 27896)").

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 217b6dc298)
2021-06-10 11:46:59 +02:00
Andreas Schwab 4b6be914bd Use __pthread_attr_copy in mq_notify (bug 27896)
Make a deep copy of the pthread attribute object to remove a potential
use-after-free issue.

(cherry picked from commit 42d3593505)
2021-06-10 11:46:45 +02:00
Florian Weimer f4cba6ca1e dlfcn: Failures after dlmopen should not terminate process [BZ #15271]
Commit 9e78f6f6e7 ("Implement
_dl_catch_error, _dl_signal_error in libc.so [BZ #16628]") has the
side effect that distinct namespaces, as created by dlmopen, now have
separate implementations of the rtld exception mechanism.  This means
that the call to _dl_catch_error from libdl in a secondary namespace
does not actually install an exception handler because the
thread-local variable catch_hook in the libc.so copy in the secondary
namespace is distinct from that of the base namepace.  As a result, a
dlsym/dlopen/... failure in a secondary namespace terminates the process
with a dynamic linker error because it looks to the exception handler
mechanism as if no handler has been installed.

Backport notes: GLRO (dl_catch_error) is replaced with
_dl_catch_error_ptr to preserve _rtld_global_ro layout.

(cherry picked from commit b2964eb1d9)
2021-06-09 17:15:00 +02:00
Nicholas Piggin 0ef0e6de7f powerpc: Fix handling of scv return error codes [BZ #27892]
When using scv for templated ASM syscalls, current code interprets any
negative return value as error, but the only valid error codes are in
the range -4095..-1 according to the ABI.

This commit also fixes 'signal.gen.test' strace test, where the issue
was first identified.

Reviewed-by: Matheus Castanho <msc@linux.ibm.com>
(cherry picked from commit 7de36744ee)
2021-05-24 17:05:07 -03:00
Florian Weimer 3f5080aedd nptl: Do not build nptl/tst-pthread-gdb-attach as PIE
(cherry picked from commit 6f3e54d404)
2021-04-30 08:34:46 +02:00
Florian Weimer 36783141cf nptl: Check for compatible GDB in nptl/tst-pthread-gdb-attach
Also do not clear the subprocess environment, in case running
GDB needs certain environment variables.

(cherry picked from commit f553dc0660)
2021-04-30 08:32:21 +02:00
Florian Weimer ea299b62e8 nptl_db: Support different libpthread/ld.so load orders (bug 27744)
libthread_db is loaded once GDB encounters libpthread, and at this
point, ld.so may not have been processed by GDB yet. As a result,
_rtld_global cannot be accessed by regular means from libthread_db.
To make this work until GDB can be fixed, acess _rtld_global through
a pointer stored in libpthread.

The new test does not reproduce bug 27744 with
--disable-hardcoded-path-in-tests, but is still a valid smoke test.
With --enable-hardcoded-path-in-tests, it is necessary to avoid
add-symbol-file because this can tickle a GDB bug.

Fixes commit 1daccf403b ("nptl: Move
stack list variables into _rtld_global").

Tested-by: Emil Velikov <emil.velikov@collabora.com>
(cherry picked from commit a64afc2252)
2021-04-30 08:32:03 +02:00
H.J. Lu 162df872f0 x86: tst-cpu-features-supports.c: Update AMX check
Pass "amx-bf16", "amx-int8" and "amx-tile", instead of "amx_bf16",
"amx_int8" and "amx_tile", to __builtin_cpu_supports for GCC 11.

(cherry picked from commit 7fc9152e83)
2021-04-22 10:10:37 -07:00
Szabolcs Nagy 12ff80b312 Remove PR_TAGGED_ADDR_ENABLE from sys/prctl.h
The value of PR_TAGGED_ADDR_ENABLE was incorrect in the installed
headers and the prctl command macros were missing that are needed
for it to be useful (PR_SET_TAGGED_ADDR_CTRL).  Linux headers have
the definitions since 5.4 so it's widely available, we don't need
to repeat these definitions.  The remaining definitions are from
Linux 5.10.

To build glibc with --enable-memory-tagging, Linux 5.4 headers and
binutils 2.33.1 or newer is needed.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit f4596d9540)
2021-04-14 09:22:26 +01:00
Siddhesh Poyarekar 1bf38e7260 Fix SXID_ERASE behavior in setuid programs (BZ #27471)
When parse_tunables tries to erase a tunable marked as SXID_ERASE for
setuid programs, it ends up setting the envvar string iterator
incorrectly, because of which it may parse the next tunable
incorrectly.  Given that currently the implementation allows malformed
and unrecognized tunables pass through, it may even allow SXID_ERASE
tunables to go through.

This change revamps the SXID_ERASE implementation so that:

- Only valid tunables are written back to the tunestr string, because
  of which children of SXID programs will only inherit a clean list of
  identified tunables that are not SXID_ERASE.

- Unrecognized tunables get scrubbed off from the environment and
  subsequently from the child environment.

- This has the side-effect that a tunable that is not identified by
  the setxid binary, will not be passed on to a non-setxid child even
  if the child could have identified that tunable.  This may break
  applications that expect this behaviour but expecting such tunables
  to cross the SXID boundary is wrong.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 2ed18c5b53)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar a7b8e8ec9b Enhance setuid-tunables test
Instead of passing GLIBC_TUNABLES via the environment, pass the
environment variable from parent to child.  This allows us to test
multiple variables to ensure better coverage.

The test list currently only includes the case that's already being
tested.  More tests will be added later.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 061fe3f8ad)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar ee16c81063 tst-env-setuid: Use support_capture_subprogram_self_sgid
Use the support_capture_subprogram_self_sgid to spawn an sgid child.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit ca33528106)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar 267e174f19 support: Add capability to fork an sgid child
Add a new function support_capture_subprogram_self_sgid that spawns an
sgid child of the running program with its own image and returns the
exit code of the child process.  This functionality is used by at
least three tests in the testsuite at the moment, so it makes sense to
consolidate.

There is also a new function support_subprogram_wait which should
provide simple system() like functionality that does not set up file
actions.  This is useful in cases where only the return code of the
spawned subprocess is interesting.

This patch also ports tst-secure-getenv to this new function.  A
subsequent patch will port other tests.  This also brings an important
change to tst-secure-getenv behaviour.  Now instead of succeeding, the
test fails as UNSUPPORTED if it is unable to spawn a setgid child,
which is how it should have been in the first place.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 716a3bdc41)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar 249c486ce8 support: Pass environ to child process
Pass environ to posix_spawn so that the child process can inherit
environment of the test.

(cherry picked from commit e958490f8c)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar 45b2c57d34 support: Typo and formatting fixes
- Add a newline to the end of error messages in transfer().
- Fixed the name of support_subprocess_init().

(cherry picked from commit 95c68080a3)
2021-04-14 10:29:52 +05:30
Siddhesh Poyarekar e07abf59b2 tunables: Fix comparison of tunable values
The simplification of tunable_set interfaces took care of
signed/unsigned conversions while setting values, but comparison with
bounds ended up being incorrect; comparing TUNABLE_SIZE_T values for
example will fail because SIZE_MAX is seen as -1.

Add comparison helpers that take tunable types into account and use
them to do comparison instead.

(cherry picked from commit d1a3dcabf2)
2021-04-14 10:29:52 +05:30
Adhemerval Zanella 3e9ca60a58 linux: always update select timeout (BZ #27706)
The timeout should be updated even on failure for time64 support.

Checked on i686-linux-gnu.

(cherry-pick from commit cedbf6d5f3)
2021-04-13 10:15:35 -03:00
Adhemerval Zanella 8380ca5833 linux: Normalize and return timeout on select (BZ #27651)
The commit 2433d39b69, which added time64 support to select, changed
the function to use __NR_pselect6 (or __NR_pelect6_time64) on all
architectures.  However, on architectures where the symbol was
implemented with __NR_select the kernel normalizes the passed timeout
instead of return EINVAL.  For instance, the input timeval
{ 0, 5000000 } is interpreted as { 5, 0 }.

And as indicated by BZ #27651, this semantic seems to be expected
and changing it results in some performance issues (most likely
the program does not check the return code and keeps issuing
select with unormalized tv_usec argument).

To avoid a different semantic depending whether which syscall the
architecture used to issue, select now always normalize the timeout
input.  This is a slight change for some ABIs (for instance aarch64).

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

(cherry picked from commit 9d7c5cc38e)
2021-04-13 10:15:09 -03:00
Adhemerval Zanella 85e4dc415a libsupport: Add support_select_normalizes_timeout
It will be used on a select() test.

(cherry-pick from commit 49a40ba18e)
2021-04-13 10:14:42 -03:00
Adhemerval Zanella b5b4aa62c1 libsupport: Add support_select_modifies_timeout
It will be used on a select() test.

(cherry picked from commit 5628f103f5)
2021-04-13 10:14:42 -03:00
Adhemerval Zanella 3d525dd639 misc: Fix tst-select timeout handling (BZ#27648)
Instead of polling the stderr, create two pipes and fork to check
if child timeout as expected similar to tst-pselect.c.  Also lower
the timeout value.

Checked on x86_64-linux-gnu.

(cherry picked from commit 1b53b5d970)
2021-04-13 10:14:41 -03:00
Lukasz Majewski 830674605f tst: Provide test for select
This change adds new test to assess select()'s timeout related
functionality (the rdfs set provides valid fd - stderr - but during
normal program operation there is no data to be read, so one just
waits for timeout).

To be more specific - two use cases are checked:
- if select() times out immediately when passed struct timeval has
  zero values of tv_usec and tv_sec.
- if select() times out after timeout specified in passed argument

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

(cherry picked from commit bff3019afc)
2021-04-13 10:06:19 -03:00
Joseph Myers e78ea9bd26 Update Nios II libm-test-ulps.
This has a subset of the changes in the version applied to master
(only those that actually appear in a regeneration on 2.33 branch).
2021-04-01 20:14:50 +00:00
Szabolcs Nagy 98bb18f52a malloc: Fix a realloc crash with heap tagging [BZ 27468]
_int_free must be called with a chunk that has its tag reset. This was
missing in a rare case that could crash when heap tagging is enabled:
when in a multi-threaded process the current arena runs out of memory
during realloc, but another arena still has space to finish the realloc
then _int_free was called without clearing the user allocation tags.

Fixes bug 27468.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 42cc96066b)
2021-03-29 09:45:10 +01:00
Stefan Liebler fc4ecce85b S390: Also check vector support in memmove ifunc-selector [BZ #27511]
The arch13 memmove variant is currently selected by the ifunc selector
if the Miscellaneous-Instruction-Extensions Facility 3 facility bit
is present, but the function is also using vector instructions.
If the vector support is not present, one is receiving an operation
exception.

Therefore this patch also checks for vector support in the ifunc
selector and in ifunc-impl-list.c.

Just to be sure, the configure check is now also testing an arch13
vector instruction and an arch13 Miscellaneous-Instruction-Extensions
Facility 3 instruction.

(cherry picked from commit 7759be2593)
2021-03-26 10:58:56 +01:00
DJ Delorie db32fc27e7 test-container: Always copy test-specific support files [BZ #27537]
There's a small chance that a fresh checkout will result in some of
the test-specific container files will have the same timestamp and
size, which breaks the rsync logic in test-container, resulting in
tests running with the wrong support files.

This patch changes the rsync logic to always copy the test-specific
files, which normally would always be copied anyway.  The rsync logic
for the testroot itself is unchanged.

(cherry picked from commit 20bee71348)
2021-03-16 10:50:37 +01:00
Florian Weimer 79c6be6a0a nptl: Remove private futex optimization [BZ #27304]
It is effectively used, unexcept for pthread_cond_destroy, where we do
not want it; see bug 27304.  The internal locks do not support a
process-shared mode.

This fixes commit dc6cfdc934 ("nptl:
Move pthread_cond_destroy implementation into libc").

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit c4ad832276)
2021-03-16 10:30:41 +01:00
Jakub Jelinek f90d6b0484 pthread_once hangs when init routine throws an exception [BZ #18435]
This is another attempt at making pthread_once handle throwing exceptions
from the init routine callback.  As the new testcases show, just switching
to the cleanup attribute based cleanup does fix the tst-once5 test, but
breaks the new tst-oncey3 test.  That is because when throwing exceptions,
only the unwind info registered cleanups (i.e. C++ destructors or cleanup
attribute), when cancelling threads and there has been unwind info from the
cancellation point up to whatever needs cleanup both unwind info registered
cleanups and THREAD_SETMEM (self, cleanup, ...) registered cleanups are
invoked, but once we hit some frame with no unwind info, only the
THREAD_SETMEM (self, cleanup, ...) registered cleanups are invoked.
So, to stay fully backwards compatible (allow init routines without
unwind info which encounter cancellation points) and handle exception throwing
we actually need to register the pthread_once cleanups in both unwind info
and in the THREAD_SETMEM (self, cleanup, ...) way.
If an exception is thrown, only the former will happen and we in that case
need to also unregister the THREAD_SETMEM (self, cleanup, ...) registered
handler, because otherwise after catching the exception the user code could
call deeper into the stack some cancellation point, get cancelled and then
a stale cleanup handler would clobber stack and probably crash.
If a thread calling init routine is cancelled and unwind info ends before
the pthread_once frame, it will be cleaned up through self->cleanup as
before.  And if unwind info is present, unwind_stop first calls the
self->cleanup registered handler for the frame, then it will call the
unwind info registered handler but that will already see __do_it == 0
and do nothing.

(cherry picked from commit f0419e6a10)
2021-03-16 10:28:58 +01:00
Florian Weimer dd8023c2ac elf: ld.so --help calls _dl_init_paths without a main map [BZ #27577]
In this case, use the link map of the dynamic loader itself as
a replacement.  This is more than just a hack: if we ever support
DT_RUNPATH/DT_RPATH for the dynamic loader, reporting it for
ld.so --help (without further command line arguments) would be the
right thing to do.

Fixes commit 3324213125 ("elf: Always
set l in _dl_init_paths (bug 23462)").

(cherry picked from commit 4e6db99c66)
2021-03-16 10:27:53 +01:00
Carlos O'Donell ea5a537e87 elf: Always set l in _dl_init_paths (bug 23462)
After d1d5471579 ("Remove dead
DL_DST_REQ_STATIC code.") we always setup the link map l to make the
static and shared cases the same.  The bug is that in elf/dl-load.c
(_dl_init_paths) we conditionally set l only in the #ifdef SHARED
case, but unconditionally use it later.  The simple solution is to
remove the #ifdef SHARED conditional, because it's no longer needed,
and unconditionally setup l for both the static and shared cases. A
regression test is added to run a static binary with
LD_LIBRARY_PATH='$ORIGIN' which crashes before the fix and runs after
the fix.

Co-Authored-By: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 3324213125)
2021-03-16 10:27:00 +01:00
H.J. Lu 64f6c287ad x86: Handle _SC_LEVEL1_ICACHE_LINESIZE [BZ #27444]
commit 2d651eb926
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Sep 18 07:55:14 2020 -0700

    x86: Move x86 processor cache info to cpu_features

missed _SC_LEVEL1_ICACHE_LINESIZE.

1. Add level1_icache_linesize to struct cpu_features.
2. Initialize level1_icache_linesize by calling handle_intel,
handle_zhaoxin and handle_amd with _SC_LEVEL1_ICACHE_LINESIZE.
3. Return level1_icache_linesize for _SC_LEVEL1_ICACHE_LINESIZE.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit f53ffc9b90)
2021-03-15 05:53:41 -07:00
Adhemerval Zanella 32b9280f1d io: Return EBAFD for negative file descriptor on fstat (BZ #27559)
Now that fstat is implemented on top fstatat we need to handle negative
inputs.  The implementation now rejects AT_FDCWD, which would otherwise
be accepted by the kernel.

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

(cherry picked from commit 94caafa040)
2021-03-11 10:53:50 -03:00
DJ Delorie a151f2e05a nscd: Fix double free in netgroupcache [BZ #27462]
In commit 745664bd79 a use-after-free
was fixed, but this led to an occasional double-free.  This patch
tracks the "live" allocation better.

Tested manually by a third party.

Related: RHBZ 1927877

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit dca565886b)
2021-03-08 15:14:51 +05:30
H.J. Lu ee9f98d9ca x86: Set minimum x86-64 level marker [BZ #27318]
Since the full ISA set used in an ELF binary is unknown to compiler,
an x86-64 ISA level marker indicates the minimum, not maximum, ISA set
required to run such an ELF binary.  We never guarantee a library with
an x86-64 ISA level v3 marker doesn't contain other ISAs beyond x86-64
ISA level v3, like AVX VNNI.  We check the x86-64 ISA level marker for
the minimum ISA set.  Since -march=sandybridge enables only some ISAs
in x86-64 ISA level v3, we should set the needed ISA marker to v2.
Otherwise, libc is compiled with -march=sandybridge will fail to run on
Sandy Bridge:

$ ./elf/ld.so ./libc.so
./libc.so: (p) CPU ISA level is lower than required: needed: 7; got: 3

Set the minimum, instead of maximum, x86-64 ISA level marker should have
no impact on the glibc-hwcaps directory assignment logic in ldconfig nor
ld.so.

(cherry picked from commit 339bf918ea)
2021-03-06 07:54:09 -08:00
DJ Delorie 3e880d7337 nss: Re-enable NSS module loading after chroot [BZ #27389]
The glibc 2.33 release enabled /etc/nsswitch.conf reloading,
and to prevent potential security issues like CVE-2019-14271
the re-loading of nsswitch.conf and all mdoules was disabled
when the root filesystem changes (see bug 27077).

Unfortunately php-lpfm and openldap both require the ability
to continue to load NSS modules after chroot. The packages
do not exec after the chroot, and so do not cause the
protections to be reset. The only solution is to re-enable
only NSS module loading (not nsswitch.conf reloading) and so
get back the previous glibc behaviour.

In the future we may introduce a way to harden applications
so they do not reload NSS modules once the root filesystem
changes, or that only files/dns are available pre-loaded
(or builtin).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 58673149f3)
2021-03-04 10:51:27 +01:00
Florian Weimer 71b2463f61 x86: Add CPU-specific diagnostics to ld.so --list-diagnostics
(cherry picked from commit 01a5746b6c)

Adjusted to not print the rep_movsb_stop_threshold field, which
does not exist in glibc 2.33.
2021-03-02 16:47:03 +01:00
Florian Weimer a1eb3915e7 x86: Automate generation of PREFERRED_FEATURE_INDEX_1 bitfield
Use a .def file to define the bitfield layout, so that it is possible
to iterate over field members using the preprocessor.

(cherry picked from commit e4933c8a92)
2021-03-02 15:48:51 +01:00
Florian Weimer 33dc1dd602 ld.so: Implement the --list-diagnostics option
(cherry picked from commit 851f32cf7b)
2021-03-02 15:46:42 +01:00
Florian Weimer 8d4241b897 string: Work around GCC PR 98512 in rawmemchr
(cherry picked from commit 044e603b69)
2021-02-19 16:10:27 +01:00
Stefan Liebler 6efa2d44c8 S390: Add new hwcap values.
The new hwcap values indicate support for arch14 architecture.

(cherry picked from commit 25251c0707)
2021-02-17 13:42:30 +01:00
Siddhesh Poyarekar c5e3545897 tunables: Disallow negative values for some tunables
The glibc.malloc.mmap_max tunable as well as al of the INT_32 tunables
don't have use for negative values, so pin the hardcoded limits in the
non-negative range of INT.  There's no real benefit in any of those
use cases for the extended range of unsigned, so I have avoided added
a new type to keep things simple.

(cherry picked from commit 228f30ab47)
2021-02-10 19:14:06 +05:30
Siddhesh Poyarekar 905fdc7071 x86: Use SIZE_MAX instead of (long int)-1 for tunable range value
The tunable types are SIZE_T, so set the ranges to the correct maximum
value, i.e. SIZE_MAX.

(cherry picked from commit a1b8b06a55)
2021-02-10 19:14:05 +05:30
Siddhesh Poyarekar 15afd6b8d8 tunables: Simplify TUNABLE_SET interface
The TUNABLE_SET interface took a primitive C type argument, which
resulted in inconsistent type conversions internally due to incorrect
dereferencing of types, especialy on 32-bit architectures.  This
change simplifies the TUNABLE setting logic along with the interfaces.

Now all numeric tunable values are stored as signed numbers in
tunable_num_t, which is intmax_t.  All calls to set tunables cast the
input value to its primitive type and then to tunable_num_t for
storage.  This relies on gcc-specific (although I suspect other
compilers woul also do the same) unsigned to signed integer conversion
semantics, i.e. the bit pattern is conserved.  The reverse conversion
is guaranteed by the standard.

(cherry picked from commit 61117bfa1b)
2021-02-10 19:14:03 +05:30
Sergei Trofimovich 17f0ff0978 nsswitch: return result when nss database is locked [BZ #27343]
Before the change nss_database_check_reload_and_get() did not populate
the '*result' value when it returned success in a case of chroot
detection. This caused initgroups() to use garage pointer in the
following test (extracted from unbound):

```

int main() {
    // load some NSS modules
    struct passwd * pw = getpwnam("root");

    chdir("/tmp");
    chroot("/tmp");
    chdir("/");
    // access nsswitch.conf in a chroot
    initgroups("root", 0);
}
```

Reviewed-by: DJ Delorie <dj@redhat.com>
2021-02-05 22:35:25 -05:00
399 changed files with 20022 additions and 8847 deletions
+5 -2
View File
@@ -557,9 +557,12 @@ link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
# before the expansion of LDLIBS-* variables).
# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
# build-hardcoded-path-in-tests.
# build-hardcoded-path-in-tests. Add -Wl,--disable-new-dtags to force
# DT_RPATH instead of DT_RUNPATH which only applies to DT_NEEDED entries
# in the executable and doesn't applies to DT_NEEDED entries in shared
# libraries which are loaded via DT_NEEDED entries in the executable.
ifeq (yes,$(build-hardcoded-path-in-tests))
link-libc-tests-rpath-link = $(link-libc-rpath)
link-libc-tests-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
else
link-libc-tests-rpath-link = $(link-libc-rpath-link)
endif # build-hardcoded-path-in-tests
+69
View File
@@ -5,6 +5,74 @@ 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.33.1
Major new features:
* The dynamic linker implements the --list-diagnostics option, printing
a dump of information related to IFUNC resolver operation and
glibc-hwcaps subdirectory selection.
Security related changes:
CVE-2021-33574: The mq_notify function has a potential use-after-free
issue when using a notification type of SIGEV_THREAD and a thread
attribute with a non-default affinity mask.
CVE-2022-23219: Passing an overlong file name to the clnt_create
legacy function could result in a stack-based buffer overflow when
using the "unix" protocol. Reported by Martin Sebor.
CVE-2022-23218: Passing an overlong file name to the svcunix_create
legacy function could result in a stack-based buffer overflow.
CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath
function could result in a memory leak and potential access of
uninitialized memory. Reported by Qualys.
CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd
function may result in an off-by-one buffer underflow and overflow
when the current working directory is longer than PATH_MAX and also
corresponds to the / directory through an unprivileged mount
namespace. Reported by Qualys.
GLIBC-SA-2026-0003: wordexp with WRDE_REUSE and WRDE_APPEND may return
uninitialized memory (CVE-2025-15281).
The following bugs are resolved with this release:
[15271] dlfcn function failure after dlmopen terminates process
[18435] pthread_once hangs when init routine throws an exception
[20975] Deferred cancellation triggers in __check_pf and looses lock leading to deadlock
[22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
[23462] Static binary with dynamic string tokens ($LIB, $PLATFORM, $ORIGIN)
crashes
[27304] pthread_cond_destroy does not pass private flag to futex system calls
[27457] vzeroupper use in AVX2 multiarch string functions cause HTM aborts
[27537] test-container: Always copy test-specific support files
[27577] elf/ld.so --help doesn't work
[27646] gethostbyname and NSS crashes after dlmopen
[27648] FAIL: misc/tst-select
[27651] Performance regression after updating to 2.33
[27706] select fails to update timeout on error
[27744] Support different libpthread/ld.so load orders for gdb -p
[27892] powerpc: scv ABI error handling fails to check IS_ERR_VALUE
[27974] Overflow bug in some implementation of wcsnlen, wmemchr, and wcsncat
[28353] Race condition in __opensock
[28607] Masked signals are delivered on thread exit
[28524] Conversion from ISO-2022-JP-3 with iconv may emit spurious NULs
[28532] powerpc64[le]: CFI for assembly templated syscalls is incorrect
[28755] overflow bug in wcsncmp_avx2 and wcsncmp_evex
[28768] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create
[28769] CVE-2021-3999: Off-by-one buffer overflow/underflow in getcwd()
[28770] CVE-2021-3998: Unexpected return value from realpath() for too long results
[28896] strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on non-rtm
variants when avoiding overflow
[29528] elf: Call __libc_early_init for reused namespaces
[33185] Fix double-free after allocation failure in regcomp
[33814] glob: wordexp with WRDE_REUSE and WRDE_APPEND may return
uninitialized memory
Version 2.33
Major new features:
@@ -238,6 +306,7 @@ The following bugs are resolved with this release:
[27237] malloc: deadlock in malloc/tst-malloc-stats-cancellation
[27256] locale: Assertion failure in ISO-2022-JP-3 gconv module
related to combining characters (CVE-2021-3326)
[28784] x86: crash in 32bit memset-sse2.s when the cache size can not be determined
Version 2.32
+6
View File
@@ -275,4 +275,10 @@
/* Define if x86 ISA level should be included in shared libraries. */
#undef INCLUDE_X86_ISA_LEVEL
/* Define if -msahf is enabled by default on x86. */
#undef HAVE_X86_LAHF_SAHF
/* Define if -mmovbe is enabled by default on x86. */
#undef HAVE_X86_MOVBE
#endif
+2
View File
@@ -168,6 +168,8 @@ extra-libs-others = $(extra-libs)
libSegFault-routines = segfault
libSegFault-inhibit-o = $(filter-out .os,$(object-suffixes))
# libSegFault.so installs a signal handler in its ELF constructor.
LDFLAGS-SegFault.so = -Wl,--enable-new-dtags,-z,nodelete
libpcprofile-routines = pcprofile
libpcprofile-inhibit-o = $(filter-out .os,$(object-suffixes))
+11 -2
View File
@@ -167,8 +167,17 @@ _dlerror_run (void (*operate) (void *), void *args)
result->errstring = NULL;
}
result->errcode = _dl_catch_error (&result->objname, &result->errstring,
&result->malloced, operate, args);
#ifdef SHARED
result->errcode = _dl_catch_error_ptr (&result->objname,
&result->errstring,
&result->malloced,
operate, args);
#else
result->errcode = _dl_catch_error (&result->objname,
&result->errstring,
&result->malloced,
operate, args);
#endif
/* If no error we mark that no error string is available. */
result->returned = result->errstring == NULL;
+45 -7
View File
@@ -66,7 +66,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
# interpreter and operating independent of libc.
rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \
dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \
dl-usage
dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
@@ -164,7 +164,8 @@ tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
tst-dl-iter-static \
tst-tlsalign-static tst-tlsalign-extern-static \
tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
tst-single_threaded-static tst-single_threaded-pthread-static
tst-single_threaded-static tst-single_threaded-pthread-static \
tst-dst-static
tests-static-internal := tst-tls1-static tst-tls2-static \
tst-ptrguard1-static tst-stackguard1-static \
@@ -225,7 +226,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit14 tst-audit15 tst-audit16 \
tst-single_threaded tst-single_threaded-pthread \
tst-tls-ie tst-tls-ie-dlmopen argv0test \
tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask
tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
tst-dlmopen-dlerror tst-dlmopen-gethostbyname tst-dlmopen-twice
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -244,7 +246,7 @@ tests += $(tests-execstack-$(have-z-execstack))
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-leaks1-mem.out \
$(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
$(objpfx)tst-ldconfig-X.out
$(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out
endif
tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@@ -347,6 +349,10 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
libmarkermod2-1 libmarkermod2-2 \
libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
libmarkermod5-1 libmarkermod5-2 libmarkermod5-3 libmarkermod5-4 \
libmarkermod5-5 \
tst-dlmopen-dlerror-mod tst-dlmopen-gethostbyname-mod \
tst-dlmopen-twice-mod1 tst-dlmopen-twice-mod2 \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -432,7 +438,8 @@ endif
ifeq (yes,$(build-shared))
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
$(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out
$(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \
$(objpfx)tst-rtld-help.out
endif
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
$(objpfx)check-wx-segment.out \
@@ -678,6 +685,9 @@ CFLAGS-cache.c += $(SYSCONF-FLAGS)
CFLAGS-rtld.c += $(SYSCONF-FLAGS)
CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) \
-D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
CFLAGS-dl-diagnostics.c += $(SYSCONF-FLAGS) \
-D'PREFIX="$(prefix)"' \
-D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
cpp-srcs-left := $(all-rtld-routines:=.os)
lib := rtld
@@ -1578,6 +1588,10 @@ $(objpfx)tst-sonamemove-dlopen.out: \
$(objpfx)tst-sonamemove-runmod1.so \
$(objpfx)tst-sonamemove-runmod2.so
$(objpfx)tst-dlmopen-dlerror: $(libdl)
$(objpfx)tst-dlmopen-dlerror-mod.so: $(libdl) $(libsupport)
$(objpfx)tst-dlmopen-dlerror.out: $(objpfx)tst-dlmopen-dlerror-mod.so
# Override -z defs, so that we can reference an undefined symbol.
# Force lazy binding for the same reason.
LDFLAGS-tst-latepthreadmod.so = \
@@ -1653,8 +1667,6 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
LD_HWCAP_MASK=0x1
tst-env-setuid-tunables-ENV = \
GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
$(objpfx)tst-debug1: $(libdl)
$(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so
@@ -1840,6 +1852,7 @@ LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so
LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so
LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so
LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so
LDFLAGS-libmarkermod5-1.so += -Wl,-soname,libmarkermod5.so
$(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c
$(compile-command.c) \
-DMARKER=marker$(firstword $(subst -, ,$*)) \
@@ -1852,6 +1865,8 @@ $(objpfx)libmarkermod3.so: $(objpfx)libmarkermod3-1.so
cp $< $@
$(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so
cp $< $@
$(objpfx)libmarkermod5.so: $(objpfx)libmarkermod5-1.so
cp $< $@
# tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is
# preferred over auto-detected subdirectories.
@@ -1902,3 +1917,26 @@ $(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
cmp tst-rtld-list-tunables.exp \
$(objpfx)/tst-rtld-list-tunables.out > $@; \
$(evaluate-test)
tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'
$(objpfx)tst-rtld-help.out: $(objpfx)ld.so
$(test-wrapper) $(rtld-prefix) --help > $@; \
status=$$?; \
echo "info: ld.so exit status: $$status" >> $@; \
if ! grep -q 'Legacy HWCAP subdirectories under library search path directories' $@; then \
echo "error: missing subdirectory pattern" >> $@; \
if test $$status -eq 0; then \
status=1; \
fi; \
fi; \
(exit $$status); \
$(evaluate-test)
$(objpfx)tst-dlmopen-gethostbyname: $(libdl)
$(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so
$(objpfx)tst-dlmopen-twice: $(libdl)
$(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \
$(objpfx)tst-dlmopen-twice-mod2.so
+1 -1
View File
@@ -72,7 +72,7 @@ ld {
# Internal error handling support. Interposed by libc.so.
_dl_signal_exception; _dl_catch_exception;
_dl_signal_error; _dl_catch_error;
_dl_signal_error; _dl_catch_error; _dl_catch_error_ptr;
# Set value of a tunable.
__tunable_get_val;
+61 -65
View File
@@ -269,81 +269,77 @@ search_cache (const char *string_table, uint32_t string_table_size,
if (_dl_cache_check_flags (flags)
&& _dl_cache_verify_ptr (lib->value, string_table_size))
{
if (best == NULL || flags == GLRO (dl_correct_cache_id))
{
/* Named/extension hwcaps get slightly different
treatment: We keep searching for a better
match. */
bool named_hwcap = false;
/* Named/extension hwcaps get slightly different
treatment: We keep searching for a better
match. */
bool named_hwcap = false;
if (entry_size >= sizeof (struct file_entry_new))
{
/* The entry is large enough to include
HWCAP data. Check it. */
struct file_entry_new *libnew
= (struct file_entry_new *) lib;
if (entry_size >= sizeof (struct file_entry_new))
{
/* The entry is large enough to include
HWCAP data. Check it. */
struct file_entry_new *libnew
= (struct file_entry_new *) lib;
#ifdef SHARED
named_hwcap = dl_cache_hwcap_extension (libnew);
if (named_hwcap
&& !dl_cache_hwcap_isa_level_compatible (libnew))
continue;
named_hwcap = dl_cache_hwcap_extension (libnew);
if (named_hwcap
&& !dl_cache_hwcap_isa_level_compatible (libnew))
continue;
#endif
/* The entries with named/extension hwcaps
have been exhausted. Return the best
match encountered so far if there is
one. */
if (!named_hwcap && best != NULL)
break;
/* The entries with named/extension hwcaps have
been exhausted (they are listed before all
other entries). Return the best match
encountered so far if there is one. */
if (!named_hwcap && best != NULL)
break;
if ((libnew->hwcap & hwcap_exclude) && !named_hwcap)
continue;
if (GLRO (dl_osversion)
&& libnew->osversion > GLRO (dl_osversion))
continue;
if (_DL_PLATFORMS_COUNT
&& (libnew->hwcap & _DL_HWCAP_PLATFORM) != 0
&& ((libnew->hwcap & _DL_HWCAP_PLATFORM)
!= platform))
continue;
if ((libnew->hwcap & hwcap_exclude) && !named_hwcap)
continue;
if (GLRO (dl_osversion)
&& libnew->osversion > GLRO (dl_osversion))
continue;
if (_DL_PLATFORMS_COUNT
&& (libnew->hwcap & _DL_HWCAP_PLATFORM) != 0
&& ((libnew->hwcap & _DL_HWCAP_PLATFORM)
!= platform))
continue;
#ifdef SHARED
/* For named hwcaps, determine the priority
and see if beats what has been found so
far. */
if (named_hwcap)
{
uint32_t entry_priority
= glibc_hwcaps_priority (libnew->hwcap);
if (entry_priority == 0)
/* Not usable at all. Skip. */
continue;
else if (best == NULL
|| entry_priority < best_priority)
/* This entry is of higher priority
than the previous one, or it is the
first entry. */
best_priority = entry_priority;
else
/* An entry has already been found,
but it is a better match. */
continue;
}
#endif /* SHARED */
/* For named hwcaps, determine the priority and
see if beats what has been found so far. */
if (named_hwcap)
{
uint32_t entry_priority
= glibc_hwcaps_priority (libnew->hwcap);
if (entry_priority == 0)
/* Not usable at all. Skip. */
continue;
else if (best == NULL
|| entry_priority < best_priority)
/* This entry is of higher priority
than the previous one, or it is the
first entry. */
best_priority = entry_priority;
else
/* An entry has already been found,
but it is a better match. */
continue;
}
best = string_table + lib->value;
if (flags == GLRO (dl_correct_cache_id)
&& !named_hwcap)
/* We've found an exact match for the shared
object and no general `ELF' release. Stop
searching, but not if a named (extension)
hwcap is used. In this case, an entry with
a higher priority may come up later. */
break;
#endif /* SHARED */
}
best = string_table + lib->value;
if (!named_hwcap && flags == _DL_CACHE_DEFAULT_ID)
/* With named hwcaps, we need to keep searching to
see if we find a better match. A better match
is also possible if the flags of the current
entry do not match the expected cache flags.
But if the flags match, no better entry will be
found. */
break;
}
}
while (++middle <= right);
@@ -1,5 +1,5 @@
/* strncasecmp_l optimized with AVX.
Copyright (C) 2017-2021 Free Software Foundation, Inc.
/* Print CPU diagnostics data in ld.so. Stub version.
Copyright (C) 2021 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,7 +16,9 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define STRCMP_SSE42 __strncasecmp_l_avx
#define USE_AVX 1
#define USE_AS_STRNCASECMP_L
#include "strcmp-sse42.S"
#include <dl-diagnostics.h>
void
_dl_diagnostics_cpu (void)
{
}
+24
View File
@@ -0,0 +1,24 @@
/* Print kernel diagnostics data in ld.so. Stub version.
Copyright (C) 2021 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 <dl-diagnostics.h>
void
_dl_diagnostics_kernel (void)
{
}
+265
View File
@@ -0,0 +1,265 @@
/* Print diagnostics data in ld.so.
Copyright (C) 2021 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 <stdbool.h>
#include <stddef.h>
#include <unistd.h>
#include <dl-diagnostics.h>
#include <dl-hwcaps.h>
#include <dl-main.h>
#include <dl-procinfo.h>
#include <dl-sysdep.h>
#include <ldsodefs.h>
#include "trusted-dirs.h"
#include "version.h"
/* Write CH to standard output. */
static void
_dl_putc (char ch)
{
_dl_write (STDOUT_FILENO, &ch, 1);
}
/* Print CH to standard output, quoting it if necessary. */
static void
print_quoted_char (char ch)
{
if (ch < ' ' || ch > '~')
{
char buf[4];
buf[0] = '\\';
buf[1] = '0' + ((ch >> 6) & 7);
buf[2] = '0' + ((ch >> 6) & 7);
buf[3] = '0' + (ch & 7);
_dl_write (STDOUT_FILENO, buf, 4);
}
else
{
if (ch == '\\' || ch == '"')
_dl_putc ('\\');
_dl_putc (ch);
}
}
/* Print S of LEN bytes to standard output, quoting characters as
needed. */
static void
print_string_length (const char *s, size_t len)
{
_dl_putc ('"');
for (size_t i = 0; i < len; ++i)
print_quoted_char (s[i]);
_dl_putc ('"');
}
void
_dl_diagnostics_print_string (const char *s)
{
if (s == NULL)
{
_dl_printf ("0x0");
return;
}
_dl_putc ('"');
while (*s != '\0')
{
print_quoted_char (*s);
++s;
}
_dl_putc ('"');
}
void
_dl_diagnostics_print_labeled_string (const char *label, const char *s)
{
_dl_printf ("%s=", label);
_dl_diagnostics_print_string (s);
_dl_putc ('\n');
}
void
_dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
{
if (sizeof (value) == sizeof (unsigned long int))
/* _dl_printf can print 64-bit values directly. */
_dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
else
{
uint32_t high = value >> 32;
uint32_t low = value;
if (high == 0)
_dl_printf ("%s=0x%x\n", label, low);
else
_dl_printf ("%s=0x%x%08x\n", label, high, low);
}
}
/* Return true if ENV is an unfiltered environment variable. */
static bool
unfiltered_envvar (const char *env, size_t *name_length)
{
char *env_equal = strchr (env, '=');
if (env_equal == NULL)
{
/* Always dump malformed entries. */
*name_length = strlen (env);
return true;
}
size_t envname_length = env_equal - env;
*name_length = envname_length;
/* LC_ and LD_ variables. */
if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
&& env[2] == '_')
return true;
/* MALLOC_ variables. */
if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
return true;
static const char unfiltered[] =
"DATEMSK\0"
"GCONV_PATH\0"
"GETCONF_DIR\0"
"GETCONF_DIR\0"
"GLIBC_TUNABLES\0"
"GMON_OUTPUT_PREFIX\0"
"HESIOD_CONFIG\0"
"HES_DOMAIN\0"
"HOSTALIASES\0"
"I18NPATH\0"
"IFS\0"
"LANG\0"
"LOCALDOMAIN\0"
"LOCPATH\0"
"MSGVERB\0"
"NIS_DEFAULTS\0"
"NIS_GROUP\0"
"NIS_PATH\0"
"NLSPATH\0"
"PATH\0"
"POSIXLY_CORRECT\0"
"RESOLV_HOST_CONF\0"
"RES_OPTIONS\0"
"SEV_LEVEL\0"
"TMPDIR\0"
"TZ\0"
"TZDIR\0"
/* Two null bytes at the end to mark the end of the list via an
empty substring. */
;
for (const char *candidate = unfiltered; *candidate != '\0'; )
{
size_t candidate_length = strlen (candidate);
if (candidate_length == envname_length
&& memcmp (candidate, env, candidate_length) == 0)
return true;
candidate += candidate_length + 1;
}
return false;
}
/* Dump the process environment. */
static void
print_environ (char **environ)
{
unsigned int index = 0;
for (char **envp = environ; *envp != NULL; ++envp)
{
char *env = *envp;
size_t name_length;
bool unfiltered = unfiltered_envvar (env, &name_length);
_dl_printf ("env%s[0x%x]=",
unfiltered ? "" : "_filtered", index);
if (unfiltered)
_dl_diagnostics_print_string (env);
else
print_string_length (env, name_length);
_dl_putc ('\n');
++index;
}
}
/* Print configured paths and the built-in search path. */
static void
print_paths (void)
{
_dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
_dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
_dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
unsigned int index = 0;
static const char *system_dirs = SYSTEM_DIRS "\0";
for (const char *e = system_dirs; *e != '\0'; )
{
size_t len = strlen (e);
_dl_printf ("path.system_dirs[0x%x]=", index);
print_string_length (e, len);
_dl_putc ('\n');
++index;
e += len + 1;
}
}
/* Print information about the glibc version. */
static void
print_version (void)
{
_dl_diagnostics_print_labeled_string ("version.release", RELEASE);
_dl_diagnostics_print_labeled_string ("version.version", VERSION);
}
void
_dl_print_diagnostics (char **environ)
{
#ifdef HAVE_DL_DISCOVER_OSVERSION
_dl_diagnostics_print_labeled_value
("dl_discover_osversion", _dl_discover_osversion ());
#endif
_dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
_dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
_dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
_dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
_dl_diagnostics_print_labeled_string
("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
_dl_diagnostics_print_labeled_value
("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
_dl_diagnostics_print_labeled_value ("dl_osversion", GLRO (dl_osversion));
_dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
_dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
_dl_diagnostics_print_labeled_string
("dl_profile_output", GLRO (dl_profile_output));
_dl_diagnostics_print_labeled_value
("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
_dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
_dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
print_environ (environ);
print_paths ();
print_version ();
_dl_diagnostics_kernel ();
_dl_diagnostics_cpu ();
_exit (EXIT_SUCCESS);
}
+46
View File
@@ -0,0 +1,46 @@
/* Interfaces for printing diagnostics in ld.so.
Copyright (C) 2021 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/>. */
#ifndef _DL_DIAGNOSTICS_H
#define _DL_DIAGNOSTICS_H
#include <stdint.h>
/* Write the null-terminated string to standard output, surrounded in
quotation marks. */
void _dl_diagnostics_print_string (const char *s) attribute_hidden;
/* Like _dl_diagnostics_print_string, but add a LABEL= prefix, and a
newline character as a suffix. */
void _dl_diagnostics_print_labeled_string (const char *label, const char *s)
attribute_hidden;
/* Print LABEL=VALUE to standard output, followed by a newline
character. */
void _dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
attribute_hidden;
/* Print diagnostics data for the kernel. Called from
_dl_print_diagnostics. */
void _dl_diagnostics_kernel (void) attribute_hidden;
/* Print diagnostics data for the CPU(s). Called from
_dl_print_diagnostics. */
void _dl_diagnostics_cpu (void) attribute_hidden;
#endif /* _DL_DIAGNOSTICS_H */
+15
View File
@@ -248,4 +248,19 @@ _dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
catch_hook = old_catch;
receiver = old_receiver;
}
/* Forwarder used for initializing _dl_catch_error_ptr. */
int
_rtld_catch_error (const char **objname, const char **errstring,
bool *mallocedp, void (*operate) (void *),
void *args)
{
/* The reference to _dl_catch_error will eventually be relocated to
point to the implementation in libc.so. */
return _dl_catch_error (objname, errstring, mallocedp, operate, args);
}
__typeof (_dl_catch_error) *_dl_catch_error_ptr = _rtld_catch_error;
rtld_hidden_data_def (_dl_catch_error_ptr);
#endif /* DL_ERROR_BOOTSTRAP */
+8 -2
View File
@@ -43,9 +43,15 @@ dlerror_run (void (*operate) (void *), void *args)
const char *last_errstring = NULL;
bool malloced;
int result = (_dl_catch_error (&objname, &last_errstring, &malloced,
operate, args)
#ifdef SHARED
int result = (_dl_catch_error_ptr (&objname, &last_errstring, &malloced,
operate, args)
?: last_errstring != NULL);
#else
int result = (_dl_catch_error (&objname, &last_errstring, &malloced,
operate, args)
?: last_errstring != NULL);
#endif
if (result && malloced)
free ((char *) last_errstring);
+49 -46
View File
@@ -758,50 +758,51 @@ _dl_init_paths (const char *llp, const char *source,
max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
*aelem = NULL;
#ifdef SHARED
/* This points to the map of the main object. */
/* This points to the map of the main object. If there is no main
object (e.g., under --help, use the dynamic loader itself as a
stand-in. */
l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (l != NULL)
{
assert (l->l_type != lt_loaded);
#ifdef SHARED
if (l == NULL)
l = &GL (dl_rtld_map);
#endif
assert (l->l_type != lt_loaded);
if (l->l_info[DT_RUNPATH])
if (l->l_info[DT_RUNPATH])
{
/* Allocate room for the search path and fill in information
from RUNPATH. */
decompose_rpath (&l->l_runpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RUNPATH]->d_un.d_val),
l, "RUNPATH");
/* During rtld init the memory is allocated by the stub malloc,
prevent any attempt to free it by the normal malloc. */
l->l_runpath_dirs.malloced = 0;
/* The RPATH is ignored. */
l->l_rpath_dirs.dirs = (void *) -1;
}
else
{
l->l_runpath_dirs.dirs = (void *) -1;
if (l->l_info[DT_RPATH])
{
/* Allocate room for the search path and fill in information
from RUNPATH. */
decompose_rpath (&l->l_runpath_dirs,
from RPATH. */
decompose_rpath (&l->l_rpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RUNPATH]->d_un.d_val),
l, "RUNPATH");
/* During rtld init the memory is allocated by the stub malloc,
prevent any attempt to free it by the normal malloc. */
l->l_runpath_dirs.malloced = 0;
/* The RPATH is ignored. */
l->l_rpath_dirs.dirs = (void *) -1;
+ l->l_info[DT_RPATH]->d_un.d_val),
l, "RPATH");
/* During rtld init the memory is allocated by the stub
malloc, prevent any attempt to free it by the normal
malloc. */
l->l_rpath_dirs.malloced = 0;
}
else
{
l->l_runpath_dirs.dirs = (void *) -1;
if (l->l_info[DT_RPATH])
{
/* Allocate room for the search path and fill in information
from RPATH. */
decompose_rpath (&l->l_rpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RPATH]->d_un.d_val),
l, "RPATH");
/* During rtld init the memory is allocated by the stub
malloc, prevent any attempt to free it by the normal
malloc. */
l->l_rpath_dirs.malloced = 0;
}
else
l->l_rpath_dirs.dirs = (void *) -1;
}
l->l_rpath_dirs.dirs = (void *) -1;
}
#endif /* SHARED */
if (llp != NULL && *llp != '\0')
{
@@ -1113,6 +1114,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
struct loadcmd loadcmds[l->l_phnum];
size_t nloadcmds = 0;
bool has_holes = false;
bool empty_dynamic = false;
/* The struct is initialized to zero so this is not necessary:
l->l_ld = 0;
@@ -1125,7 +1127,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
segments are mapped in. We record the addresses it says
verbatim, and later correct for the run-time load address. */
case PT_DYNAMIC:
if (ph->p_filesz)
if (ph->p_filesz == 0)
empty_dynamic = true; /* Usually separate debuginfo. */
else
{
/* Debuginfo only files from "objcopy --only-keep-debug"
contain a PT_DYNAMIC segment with p_filesz == 0. Skip
@@ -1247,6 +1251,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
goto lose;
}
/* This check recognizes most separate debuginfo files. */
if (__glibc_unlikely ((l->l_ld == 0 && type == ET_DYN) || empty_dynamic))
{
errstring = N_("object file has no dynamic section");
goto lose;
}
/* Length of the sections to be loaded. */
maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
@@ -1264,15 +1275,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
}
}
if (l->l_ld == 0)
{
if (__glibc_unlikely (type == ET_DYN))
{
errstring = N_("object file has no dynamic section");
goto lose;
}
}
else
if (l->l_ld != 0)
l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
elf_get_dynamic_info (l, NULL);
+4 -1
View File
@@ -63,7 +63,7 @@ struct audit_list
enum rtld_mode
{
rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace,
rtld_mode_list_tunables, rtld_mode_help,
rtld_mode_list_tunables, rtld_mode_list_diagnostics, rtld_mode_help,
};
/* Aggregated state information extracted from environment variables
@@ -121,4 +121,7 @@ _Noreturn void _dl_version (void) attribute_hidden;
_Noreturn void _dl_help (const char *argv0, struct dl_main_state *state)
attribute_hidden;
/* Print a diagnostics dump. */
_Noreturn void _dl_print_diagnostics (char **environ) attribute_hidden;
#endif /* _DL_MAIN */
+9 -6
View File
@@ -819,11 +819,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
_dl_signal_error (EINVAL, file, NULL, N_("\
no more namespaces available for dlmopen()"));
}
else if (nsid == GL(dl_nns))
{
__rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
++GL(dl_nns);
}
if (nsid == GL(dl_nns))
++GL(dl_nns);
/* Initialize the new namespace. Most members are
zero-initialized, only the lock needs special treatment. */
memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
__rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
}
@@ -881,7 +884,7 @@ no more namespaces available for dlmopen()"));
/* Avoid keeping around a dangling reference to the libc.so link
map in case it has been cached in libc_map. */
if (!args.libc_already_loaded)
GL(dl_ns)[nsid].libc_map = NULL;
GL(dl_ns)[args.nsid].libc_map = NULL;
/* Remove the object from memory. It may be in an inconsistent
state if relocation failed, for example. */
+19 -2
View File
@@ -38,8 +38,8 @@ typedef enum
typedef struct
{
tunable_type_code_t type_code;
int64_t min;
int64_t max;
tunable_num_t min;
tunable_num_t max;
} tunable_type_t;
/* Security level for tunables. This decides what to do with individual
@@ -81,4 +81,21 @@ struct _tunable
typedef struct _tunable tunable_t;
static __always_inline bool
unsigned_tunable_type (tunable_type_code_t t)
{
switch (t)
{
case TUNABLE_TYPE_INT_32:
return false;
case TUNABLE_TYPE_UINT_64:
case TUNABLE_TYPE_SIZE_T:
return true;
case TUNABLE_TYPE_STRING:
default:
break;
}
__builtin_unreachable ();
}
#endif
+70 -119
View File
@@ -93,88 +93,49 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val,
return NULL;
}
#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type) \
({ \
__type min = (__cur)->type.min; \
__type max = (__cur)->type.max; \
\
if ((__type) (__val) >= min && (__type) (__val) <= max) \
{ \
(__cur)->val.numval = (__val); \
(__cur)->initialized = true; \
} \
})
#define TUNABLE_SET_BOUNDS_IF_VALID(__cur, __minp, __maxp, __type) \
({ \
if (__minp != NULL) \
{ \
/* MIN is specified. */ \
__type min = *((__type *) __minp); \
if (__maxp != NULL) \
{ \
/* Both MIN and MAX are specified. */ \
__type max = *((__type *) __maxp); \
if (max >= min \
&& max <= (__cur)->type.max \
&& min >= (__cur)->type.min) \
{ \
(__cur)->type.min = min; \
(__cur)->type.max = max; \
} \
} \
else if (min > (__cur)->type.min && min <= (__cur)->type.max) \
{ \
/* Only MIN is specified. */ \
(__cur)->type.min = min; \
} \
} \
else if (__maxp != NULL) \
{ \
/* Only MAX is specified. */ \
__type max = *((__type *) __maxp); \
if (max < (__cur)->type.max && max >= (__cur)->type.min) \
(__cur)->type.max = max; \
} \
})
static void
do_tunable_update_val (tunable_t *cur, const void *valp,
const void *minp, const void *maxp)
do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
const tunable_num_t *minp,
const tunable_num_t *maxp)
{
uint64_t val;
tunable_num_t val, min, max;
if (cur->type.type_code != TUNABLE_TYPE_STRING)
val = *((int64_t *) valp);
switch (cur->type.type_code)
if (cur->type.type_code == TUNABLE_TYPE_STRING)
{
case TUNABLE_TYPE_INT_32:
{
TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, int64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t);
break;
}
case TUNABLE_TYPE_UINT_64:
{
TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t);
break;
}
case TUNABLE_TYPE_SIZE_T:
{
TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t);
break;
}
case TUNABLE_TYPE_STRING:
{
cur->val.strval = valp;
break;
}
default:
__builtin_unreachable ();
cur->val.strval = valp->strval;
cur->initialized = true;
return;
}
bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
val = valp->numval;
min = minp != NULL ? *minp : cur->type.min;
max = maxp != NULL ? *maxp : cur->type.max;
/* We allow only increasingly restrictive bounds. */
if (tunable_val_lt (min, cur->type.min, unsigned_cmp))
min = cur->type.min;
if (tunable_val_gt (max, cur->type.max, unsigned_cmp))
max = cur->type.max;
/* Skip both bounds if they're inconsistent. */
if (tunable_val_gt (min, max, unsigned_cmp))
{
min = cur->type.min;
max = cur->type.max;
}
/* Bail out if the bounds are not valid. */
if (tunable_val_lt (val, min, unsigned_cmp)
|| tunable_val_lt (max, val, unsigned_cmp))
return;
cur->val.numval = val;
cur->type.min = min;
cur->type.max = max;
cur->initialized = true;
}
/* Validate range of the input value and initialize the tunable CUR if it looks
@@ -182,24 +143,18 @@ do_tunable_update_val (tunable_t *cur, const void *valp,
static void
tunable_initialize (tunable_t *cur, const char *strval)
{
uint64_t val;
const void *valp;
tunable_val_t val;
if (cur->type.type_code != TUNABLE_TYPE_STRING)
{
val = _dl_strtoul (strval, NULL);
valp = &val;
}
val.numval = (tunable_num_t) _dl_strtoul (strval, NULL);
else
{
cur->initialized = true;
valp = strval;
}
do_tunable_update_val (cur, valp, NULL, NULL);
val.strval = strval;
do_tunable_update_val (cur, &val, NULL, NULL);
}
void
__tunable_set_val (tunable_id_t id, void *valp, void *minp, void *maxp)
__tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
tunable_num_t *maxp)
{
tunable_t *cur = &tunable_list[id];
@@ -219,6 +174,7 @@ parse_tunables (char *tunestr, char *valstring)
return;
char *p = tunestr;
size_t off = 0;
while (true)
{
@@ -232,7 +188,11 @@ parse_tunables (char *tunestr, char *valstring)
/* If we reach the end of the string before getting a valid name-value
pair, bail out. */
if (p[len] == '\0')
return;
{
if (__libc_enable_secure)
tunestr[off] = '\0';
return;
}
/* We did not find a valid name-value pair before encountering the
colon. */
@@ -258,35 +218,28 @@ parse_tunables (char *tunestr, char *valstring)
if (tunable_is_name (cur->name, name))
{
/* If we are in a secure context (AT_SECURE) then ignore the tunable
unless it is explicitly marked as secure. Tunable values take
precedence over their envvar aliases. */
/* If we are in a secure context (AT_SECURE) then ignore the
tunable unless it is explicitly marked as secure. Tunable
values take precedence over their envvar aliases. We write
the tunables that are not SXID_ERASE back to TUNESTR, thus
dropping all SXID_ERASE tunables and any invalid or
unrecognized tunables. */
if (__libc_enable_secure)
{
if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
{
if (p[len] == '\0')
{
/* Last tunable in the valstring. Null-terminate and
return. */
*name = '\0';
return;
}
else
{
/* Remove the current tunable from the string. We do
this by overwriting the string starting from NAME
(which is where the current tunable begins) with
the remainder of the string. We then have P point
to NAME so that we continue in the correct
position in the valstring. */
char *q = &p[len + 1];
p = name;
while (*q != '\0')
*name++ = *q++;
name[0] = '\0';
len = 0;
}
if (off > 0)
tunestr[off++] = ':';
const char *n = cur->name;
while (*n != '\0')
tunestr[off++] = *n++;
tunestr[off++] = '=';
for (size_t j = 0; j < len; j++)
tunestr[off++] = value[j];
}
if (cur->security_level != TUNABLE_SECLEVEL_NONE)
@@ -299,9 +252,7 @@ parse_tunables (char *tunestr, char *valstring)
}
}
if (p[len] == '\0')
return;
else
if (p[len] != '\0')
p += len + 1;
}
}
+37 -18
View File
@@ -33,9 +33,11 @@ __tunables_init (char **unused __attribute__ ((unused)))
# include <stddef.h>
# include <stdint.h>
typedef intmax_t tunable_num_t;
typedef union
{
int64_t numval;
tunable_num_t numval;
const char *strval;
} tunable_val_t;
@@ -52,7 +54,8 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
extern void __tunables_init (char **);
extern void __tunables_print (void);
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
extern void __tunable_set_val (tunable_id_t, void *, void *, void *);
extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
tunable_num_t *);
rtld_hidden_proto (__tunables_init)
rtld_hidden_proto (__tunables_print)
rtld_hidden_proto (__tunable_get_val)
@@ -64,20 +67,18 @@ rtld_hidden_proto (__tunable_set_val)
#if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE
# define TUNABLE_GET(__id, __type, __cb) \
TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
# define TUNABLE_SET(__id, __type, __val) \
TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __val)
# define TUNABLE_SET_WITH_BOUNDS(__id, __type, __val, __min, __max) \
# define TUNABLE_SET(__id, __val) \
TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __val)
# define TUNABLE_SET_WITH_BOUNDS(__id, __val, __min, __max) \
TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \
__type, __val, __min, __max)
__val, __min, __max)
#else
# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
# define TUNABLE_SET(__top, __ns, __id, __type, __val) \
TUNABLE_SET_FULL (__top, __ns, __id, __type, __val)
# define TUNABLE_SET_WITH_BOUNDS(__top, __ns, __id, __type, __val, \
__min, __max) \
TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __type, __val, \
__min, __max)
# define TUNABLE_SET(__top, __ns, __id, __val) \
TUNABLE_SET_FULL (__top, __ns, __id, __val)
# define TUNABLE_SET_WITH_BOUNDS(__top, __ns, __id, __val, __min, __max) \
TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max)
#endif
/* Get and return a tunable value. If the tunable was set externally and __CB
@@ -91,19 +92,19 @@ rtld_hidden_proto (__tunable_set_val)
})
/* Set a tunable value. */
# define TUNABLE_SET_FULL(__top, __ns, __id, __type, __val) \
# define TUNABLE_SET_FULL(__top, __ns, __id, __val) \
({ \
__tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \
& (__type) {__val}, NULL, NULL); \
& (tunable_val_t) {.numval = __val}, NULL, NULL); \
})
/* Set a tunable value together with min/max values. */
# define TUNABLE_SET_WITH_BOUNDS_FULL(__top, __ns, __id, __type, __val, \
__min, __max) \
# define TUNABLE_SET_WITH_BOUNDS_FULL(__top, __ns, __id,__val, __min, __max) \
({ \
__tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \
& (__type) {__val}, & (__type) {__min}, \
& (__type) {__max}); \
& (tunable_val_t) {.numval = __val}, \
& (tunable_num_t) {__min}, \
& (tunable_num_t) {__max}); \
})
/* Namespace sanity for callback functions. Use this macro to keep the
@@ -114,6 +115,24 @@ rtld_hidden_proto (__tunable_set_val)
/* The default value for TUNABLES_FRONTEND. */
# define TUNABLES_FRONTEND_yes TUNABLES_FRONTEND_valstring
static __always_inline bool
tunable_val_lt (tunable_num_t lhs, tunable_num_t rhs, bool unsigned_cmp)
{
if (unsigned_cmp)
return (uintmax_t) lhs < (uintmax_t) rhs;
else
return lhs < rhs;
}
static __always_inline bool
tunable_val_gt (tunable_num_t lhs, tunable_num_t rhs, bool unsigned_cmp)
{
if (unsigned_cmp)
return (uintmax_t) lhs > (uintmax_t) rhs;
else
return lhs > rhs;
}
/* Compare two name strings, bounded by the name hardcoded in glibc. */
static __always_inline bool
tunable_is_name (const char *orig, const char *envname)
+6
View File
@@ -64,6 +64,7 @@ glibc {
type: INT_32
env_alias: MALLOC_MMAP_MAX_
security_level: SXID_IGNORE
minval: 0
}
arena_max {
type: SIZE_T
@@ -109,22 +110,27 @@ glibc {
skip_lock_busy {
type: INT_32
default: 3
minval: 0
}
skip_lock_internal_abort {
type: INT_32
default: 3
minval: 0
}
skip_lock_after_retries {
type: INT_32
default: 3
minval: 0
}
tries {
type: INT_32
default: 3
minval: 0
}
skip_trylock_internal_abort {
type: INT_32
default: 3
minval: 0
}
}
+1
View File
@@ -261,6 +261,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
--list-tunables list all tunables with minimum and maximum values\n"
#endif
"\
--list-diagnostics list diagnostics information\n\
--help display this help and exit\n\
--version output version information and exit\n\
\n\
+13
View File
@@ -19,7 +19,14 @@ typedef int (*foo_p) (void);
#endif
foo_p foo_ptr = foo;
/* Address-significant access to protected symbols is not supported in
position-dependent mode on several architectures because GCC
generates relocations that assume that the address is local to the
main program. */
#ifdef __PIE__
foo_p foo_procted_ptr = foo_protected;
#endif
extern foo_p get_foo_p (void);
extern foo_p get_foo_hidden_p (void);
@@ -37,12 +44,16 @@ main (void)
if ((*foo_ptr) () != -1)
abort ();
#ifdef __PIE__
if (foo_procted_ptr != foo_protected)
abort ();
#endif
if (foo_protected () != 0)
abort ();
#ifdef __PIE__
if ((*foo_procted_ptr) () != 0)
abort ();
#endif
p = get_foo_p ();
if (p != foo)
@@ -55,8 +66,10 @@ main (void)
abort ();
p = get_foo_protected_p ();
#ifdef __PIE__
if (p != foo_protected)
abort ();
#endif
if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
abort ();
+9
View File
@@ -14,12 +14,19 @@ get_foo (void)
return foo;
}
/* Address-significant access to protected symbols is not supported in
position-dependent mode on several architectures because GCC
generates relocations that assume that the address is local to the
main program. */
#ifdef __PIE__
foo_p
__attribute__ ((noinline))
get_foo_protected (void)
{
return foo_protected;
}
#endif
int
main (void)
@@ -30,9 +37,11 @@ main (void)
if ((*p) () != -1)
abort ();
#ifdef __PIE__
p = get_foo_protected ();
if ((*p) () != 0)
abort ();
#endif
return 0;
}
+12 -7
View File
@@ -141,6 +141,7 @@ static void dl_main_state_init (struct dl_main_state *state);
/* Process all environments variables the dynamic linker must recognize.
Since all of them start with `LD_' we are a bit smarter while finding
all the entries. */
extern char **_environ attribute_hidden;
static void process_envvars (struct dl_main_state *state);
#ifdef DL_ARGV_NOT_RELRO
@@ -379,7 +380,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
extern struct rtld_global_ro _rtld_local_ro
__attribute__ ((alias ("_rtld_global_ro"), visibility ("hidden")));
static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv);
@@ -1287,6 +1287,14 @@ dl_main (const ElfW(Phdr) *phdr,
++_dl_argv;
}
#endif
else if (! strcmp (_dl_argv[1], "--list-diagnostics"))
{
state.mode = rtld_mode_list_diagnostics;
++_dl_skip_args;
--_dl_argc;
++_dl_argv;
}
else if (strcmp (_dl_argv[1], "--help") == 0)
{
state.mode = rtld_mode_help;
@@ -1315,6 +1323,9 @@ dl_main (const ElfW(Phdr) *phdr,
}
#endif
if (state.mode == rtld_mode_list_diagnostics)
_dl_print_diagnostics (_environ);
/* If we have no further argument the program was called incorrectly.
Grant the user some education. */
if (_dl_argc < 2)
@@ -2649,12 +2660,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
}
}
/* Process all environments variables the dynamic linker must recognize.
Since all of them start with `LD_' we are a bit smarter while finding
all the entries. */
extern char **_environ attribute_hidden;
static void
process_envvars (struct dl_main_state *state)
{
+41
View File
@@ -0,0 +1,41 @@
/* Check that dlfcn errors are reported properly after dlmopen. Test module.
Copyright (C) 2021 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 <dlfcn.h>
#include <stddef.h>
#include <support/check.h>
/* Note: This object is not linked into the main program, so we cannot
use delayed test failure reporting via TEST_VERIFY etc., and have
to use FAIL_EXIT1 (or something else that calls exit). */
void
call_dlsym (void)
{
void *ptr = dlsym (NULL, "does not exist");
if (ptr != NULL)
FAIL_EXIT1 ("dlsym did not fail as expected");
}
void
call_dlopen (void)
{
void *handle = dlopen ("tst-dlmopen-dlerror does not exist", RTLD_NOW);
if (handle != NULL)
FAIL_EXIT1 ("dlopen did not fail as expected");
}
+37
View File
@@ -0,0 +1,37 @@
/* Check that dlfcn errors are reported properly after dlmopen.
Copyright (C) 2021 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 <stddef.h>
#include <support/check.h>
#include <support/xdlfcn.h>
static int
do_test (void)
{
void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-dlerror-mod.so",
RTLD_NOW);
void (*call_dlsym) (void) = xdlsym (handle, "call_dlsym");
void (*call_dlopen) (void) = xdlsym (handle, "call_dlopen");
call_dlsym ();
call_dlopen ();
return 0;
}
#include <support/test-driver.c>
+29
View File
@@ -0,0 +1,29 @@
/* Exercise dlerror_run in elf/dl-libc.c after dlmopen, via NSS. Helper module.
Copyright (C) 2021 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 <netdb.h>
#include <nss.h>
void
call_gethostbyname (void)
{
__nss_configure_lookup ("hosts", "files");
/* This should not terminate the process due to a missing
_nss_files_getcanonname_r symbol. */
gethostbyname ("localhost");
}
+31
View File
@@ -0,0 +1,31 @@
/* Exercise dlerror_run in elf/dl-libc.c after dlmopen, via NSS (bug 27646).
Copyright (C) 2021 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>
static int
do_test (void)
{
void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-gethostbyname-mod.so",
RTLD_NOW);
void (*call_gethostbyname) (void) = xdlsym (handle, "call_gethostbyname");
call_gethostbyname ();
return 0;
}
#include <support/test-driver.c>
+37
View File
@@ -0,0 +1,37 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlmopen-twice-mod1.so loaded");
fflush (stdout);
}
static void __attribute__ ((destructor))
fini (void)
{
puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
fflush (stdout);
}
/* Large allocation. The second module does not have this, so it
should load libc at a different address. */
char large_allocate[16 * 1024 * 1024];
+50
View File
@@ -0,0 +1,50 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ctype.h>
#include <stdio.h>
static void __attribute__ ((constructor))
init (void)
{
puts ("info: tst-dlmopen-twice-mod2.so loaded");
fflush (stdout);
}
static void __attribute__ ((destructor))
fini (void)
{
puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
fflush (stdout);
}
int
run_check (void)
{
puts ("info: about to call isalpha");
fflush (stdout);
volatile char ch = 'a';
if (!isalpha (ch))
{
puts ("error: isalpha ('a') is not true");
fflush (stdout);
return 1;
}
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <support/xdlfcn.h>
#include <support/check.h>
static int
do_test (void)
{
void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
xdlclose (handle);
handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
int (*run_check) (void) = xdlsym (handle, "run_check");
TEST_COMPARE (run_check (), 0);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>
+32
View File
@@ -0,0 +1,32 @@
/* Test DST expansion for static binaries doesn't carsh. Bug 23462.
Copyright (C) 2021 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/>. */
/* The purpose of this test is to exercise the code in elf/dl-loac.c
(_dl_init_paths) or thereabout and ensure that static binaries
don't crash when expanding DSTs.
If the dynamic loader code linked into the static binary cannot
handle expanding the DSTs e.g. null-deref on an incomplete link
map, then it will crash before reaching main, so the test harness
is unnecessary. */
int
main (void)
{
return 0;
}
+93 -19
View File
@@ -25,35 +25,76 @@
#include "config.h"
#undef _LIBC
#define test_parent test_parent_tunables
#define test_child test_child_tunables
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <intprops.h>
#include <array_length.h>
static int test_child_tunables (void);
static int test_parent_tunables (void);
#include <support/check.h>
#include <support/support.h>
#include <support/test-driver.h>
#include <support/capture_subprocess.h>
#include "tst-env-setuid.c"
const char *teststrings[] =
{
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.check=2:glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096:glibc.malloc.check=2",
"glibc.malloc.perturb=0x800",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
"not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
"glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
":glibc.malloc.garbage=2:glibc.malloc.check=1",
"glibc.malloc.check=1:glibc.malloc.check=2",
"not_valid.malloc.check=2",
"glibc.not_valid.check=2",
};
#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096"
#define PARENT_VALSTRING_VALUE \
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096"
const char *resultstrings[] =
{
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"",
"",
"",
"",
"",
"",
};
static int
test_child_tunables (void)
test_child (int off)
{
const char *val = getenv ("GLIBC_TUNABLES");
#if HAVE_TUNABLES
if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0)
if (val != NULL && strcmp (val, resultstrings[off]) == 0)
return 0;
if (val != NULL)
printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
return 1;
#else
if (val != NULL)
{
printf ("GLIBC_TUNABLES not cleared\n");
printf ("[%d] GLIBC_TUNABLES not cleared\n", off);
return 1;
}
return 0;
@@ -61,15 +102,48 @@ test_child_tunables (void)
}
static int
test_parent_tunables (void)
do_test (int argc, char **argv)
{
const char *val = getenv ("GLIBC_TUNABLES");
/* Setgid child process. */
if (argc == 2)
{
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 ());
if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0)
return 0;
int ret = test_child (atoi (argv[1]));
if (val != NULL)
printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
if (ret != 0)
exit (1);
return 1;
exit (EXIT_SUCCESS);
}
else
{
int ret = 0;
/* Spawn tests. */
for (int i = 0; i < array_length (teststrings); i++)
{
char buf[INT_BUFSIZE_BOUND (int)];
printf ("Spawned test for %s (%d)\n", teststrings[i], i);
snprintf (buf, sizeof (buf), "%d\n", i);
if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
exit (1);
int status = support_capture_subprogram_self_sgid (buf);
/* Bail out early if unsupported. */
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
ret |= status;
}
return ret;
}
}
#define TEST_FUNCTION_ARGV do_test
#include <support/test-driver.c>
+14 -183
View File
@@ -29,173 +29,12 @@
#include <sys/wait.h>
#include <unistd.h>
#include <support/check.h>
#include <support/support.h>
#include <support/test-driver.h>
#include <support/capture_subprocess.h>
static char SETGID_CHILD[] = "setgid-child";
#define CHILD_STATUS 42
/* Return a GID which is not our current GID, but is present in the
supplementary group list. */
static gid_t
choose_gid (void)
{
const int count = 64;
gid_t groups[count];
int ret = getgroups (count, groups);
if (ret < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t current = getgid ();
for (int i = 0; i < ret; ++i)
{
if (groups[i] != current)
return groups[i];
}
return 0;
}
/* Spawn and execute a program and verify that it returns the CHILD_STATUS. */
static pid_t
do_execve (char **args)
{
pid_t kid = vfork ();
if (kid < 0)
{
printf ("vfork: %m\n");
return -1;
}
if (kid == 0)
{
/* Child process. */
execve (args[0], args, environ);
_exit (-errno);
}
if (kid < 0)
return 1;
int status;
if (waitpid (kid, &status, 0) < 0)
{
printf ("waitpid: %m\n");
return 1;
}
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS)
{
printf ("Unexpected exit status %d from child process\n",
WEXITSTATUS (status));
return 1;
}
return 0;
}
/* Copies the executable into a restricted directory, so that we can
safely make it SGID with the TARGET group ID. Then runs the
executable. */
static int
run_executable_sgid (gid_t target)
{
char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd",
test_dir, (intmax_t) getpid ());
char *execname = xasprintf ("%s/bin", dirname);
int infd = -1;
int outfd = -1;
int ret = 0;
if (mkdir (dirname, 0700) < 0)
{
printf ("mkdir: %m\n");
goto err;
}
infd = open ("/proc/self/exe", O_RDONLY);
if (infd < 0)
{
printf ("open (/proc/self/exe): %m\n");
goto err;
}
outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
if (outfd < 0)
{
printf ("open (%s): %m\n", execname);
goto err;
}
char buf[4096];
for (;;)
{
ssize_t rdcount = read (infd, buf, sizeof (buf));
if (rdcount < 0)
{
printf ("read: %m\n");
goto err;
}
if (rdcount == 0)
break;
char *p = buf;
char *end = buf + rdcount;
while (p != end)
{
ssize_t wrcount = write (outfd, buf, end - p);
if (wrcount == 0)
errno = ENOSPC;
if (wrcount <= 0)
{
printf ("write: %m\n");
goto err;
}
p += wrcount;
}
}
if (fchown (outfd, getuid (), target) < 0)
{
printf ("fchown (%s): %m\n", execname);
goto err;
}
if (fchmod (outfd, 02750) < 0)
{
printf ("fchmod (%s): %m\n", execname);
goto err;
}
if (close (outfd) < 0)
{
printf ("close (outfd): %m\n");
goto err;
}
if (close (infd) < 0)
{
printf ("close (infd): %m\n");
goto err;
}
char *args[] = {execname, SETGID_CHILD, NULL};
ret = do_execve (args);
err:
if (outfd >= 0)
close (outfd);
if (infd >= 0)
close (infd);
if (execname)
{
unlink (execname);
free (execname);
}
if (dirname)
{
rmdir (dirname);
free (dirname);
}
return ret;
}
#ifndef test_child
static int
@@ -256,40 +95,32 @@ do_test (int argc, char **argv)
if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
{
if (getgid () == getegid ())
{
/* This can happen if the file system is mounted nosuid. */
fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
exit (EXIT_UNSUPPORTED);
}
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
int ret = test_child ();
if (ret != 0)
exit (1);
exit (CHILD_STATUS);
exit (EXIT_SUCCESS);
}
else
{
if (test_parent () != 0)
exit (1);
/* Try running a setgid program. */
gid_t target = choose_gid ();
if (target == 0)
{
fprintf (stderr,
"Could not find a suitable GID for user %jd, skipping test\n",
(intmax_t) getuid ());
exit (0);
}
int status = support_capture_subprogram_self_sgid (SETGID_CHILD);
return run_executable_sgid (target);
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status))
FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
return 0;
}
/* Something went wrong and our argv was corrupted. */
_exit (1);
}
#define TEST_FUNCTION_ARGV do_test
+6
View File
@@ -4,6 +4,7 @@
cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
cp $B/elf/libmarkermod5-1.so $L/libmarkermod5.so
mkdirp 0770 $L/glibc-hwcaps/power9
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so
@@ -20,6 +21,11 @@ mkdirp 0770 $L/glibc-hwcaps/z15
cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/z13/libmarkermod4.so
cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/z14/libmarkermod4.so
cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/z15/libmarkermod4.so
mkdirp 0770 $L/glibc-hwcaps/z16
cp $B/elf/libmarkermod5-2.so $L/glibc-hwcaps/z13/libmarkermod5.so
cp $B/elf/libmarkermod5-3.so $L/glibc-hwcaps/z14/libmarkermod5.so
cp $B/elf/libmarkermod5-4.so $L/glibc-hwcaps/z15/libmarkermod5.so
cp $B/elf/libmarkermod5-5.so $L/glibc-hwcaps/z16/libmarkermod5.so
mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
+1 -1
View File
@@ -1,7 +1,7 @@
glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+)
glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+)
glibc.malloc.check: 0 (min: 0, max: 3)
glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647)
glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.perturb: 0 (min: 0, max: 255)
+7 -1
View File
@@ -1,4 +1,5 @@
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
# Copyright (C) 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
@@ -74,7 +75,8 @@ ifeq (yes,$(build-shared))
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-iconv13 bug-iconv14 bug-iconv15 \
tst-iconv-iso-2022-cn-ext
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -324,6 +326,10 @@ $(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(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)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so)) \
+60
View File
@@ -0,0 +1,60 @@
/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv
may emit spurious NUL character on state reset.
Copyright (C) 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 <stddef.h>
#include <iconv.h>
#include <support/check.h>
static int
do_test (void)
{
char in[] = "\x1b(I";
char *inbuf = in;
size_t inleft = sizeof (in) - 1;
char out[1];
char *outbuf = out;
size_t outleft = sizeof (out);
iconv_t cd;
cd = iconv_open ("UTF8", "ISO-2022-JP-3");
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
/* First call to iconv should alter internal state.
Now, JISX0201_Kana_set is selected and
state value != ASCII_set. */
TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1);
/* No bytes should have been added to
the output buffer at this point. */
TEST_VERIFY (outbuf == out);
TEST_VERIFY (outleft == sizeof (out));
/* Second call shall emit spurious NUL character in unpatched glibc. */
TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1);
/* No characters are expected to be produced. */
TEST_VERIFY (outbuf == out);
TEST_VERIFY (outleft == sizeof (out));
TEST_VERIFY_EXIT (iconv_close (cd) != -1);
return 0;
}
#include <support/test-driver.c>
+12
View File
@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
if (outptr + 4 > outend) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
assert (used == CNS11643_2_set); /* XXX */ \
escseq = "*H"; \
*outptr++ = ESC; \
@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
if (outptr + 4 > outend) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
*outptr++ = ESC; \
+20 -8
View File
@@ -1,5 +1,6 @@
/* Conversion module for ISO-2022-JP-3.
Copyright (C) 1998-2021 Free Software Foundation, Inc.
Copyright (C) The GNU Toolchain Authors.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
and Bruno Haible <bruno@clisp.org>, 2002.
@@ -81,20 +82,31 @@ enum
the output state to the initial state. This has to be done during the
flushing. */
#define EMIT_SHIFT_TO_INIT \
if (data->__statep->__count != ASCII_set) \
if ((data->__statep->__count & ~7) != ASCII_set) \
{ \
if (FROM_DIRECTION) \
{ \
if (__glibc_likely (outbuf + 4 <= outend)) \
uint32_t ch = data->__statep->__count >> 6; \
\
if (__glibc_unlikely (ch != 0)) \
{ \
/* Write out the last character. */ \
*((uint32_t *) outbuf) = data->__statep->__count >> 6; \
outbuf += sizeof (uint32_t); \
data->__statep->__count = ASCII_set; \
if (__glibc_likely (outbuf + 4 <= outend)) \
{ \
/* Write out the last character. */ \
put32u (outbuf, ch); \
outbuf += 4; \
data->__statep->__count &= 7; \
data->__statep->__count |= ASCII_set; \
} \
else \
/* We don't have enough room in the output buffer. */ \
status = __GCONV_FULL_OUTPUT; \
} \
else \
/* We don't have enough room in the output buffer. */ \
status = __GCONV_FULL_OUTPUT; \
{ \
data->__statep->__count &= 7; \
data->__statep->__count |= ASCII_set; \
} \
} \
else \
{ \
+128
View File
@@ -0,0 +1,128 @@
/* Verify ISO-2022-CN-EXT does not write out of the bounds.
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 <string.h>
#include <errno.h>
#include <iconv.h>
#include <sys/mman.h>
#include <support/xunistd.h>
#include <support/check.h>
#include <support/support.h>
/* The test sets up a two memory page buffer with the second page marked
PROT_NONE to trigger a fault if the conversion writes beyond the exact
expected amount. Then we carry out various conversions and precisely
place the start of the output buffer in order to trigger a SIGSEGV if the
process writes anywhere between 1 and page sized bytes more (only one
PROT_NONE page is setup as a canary) than expected. These tests exercise
all three of the cases in ISO-2022-CN-EXT where the converter must switch
character sets and may run out of buffer space while doing the
operation. */
static int
do_test (void)
{
iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
char *ntf;
size_t ntfsize;
char *outbufbase;
{
int pgz = getpagesize ();
TEST_VERIFY_EXIT (pgz > 0);
ntfsize = 2 * pgz;
ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
| MAP_ANONYMOUS, -1);
xmprotect (ntf + pgz, pgz, PROT_NONE);
outbufbase = ntf + pgz;
}
/* Check if SOdesignation escape sequence does not trigger an OOB write. */
{
char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
for (int i = 0; i < 9; i++)
{
char *inp = inbuf;
size_t inleft = sizeof (inbuf) - 1;
char *outp = outbufbase - i;
size_t outleft = i;
TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
== (size_t) -1);
TEST_COMPARE (errno, E2BIG);
TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
}
}
/* Same as before for SS2designation. */
{
char inbuf[] = "\xe3\xb4\xbd";
for (int i = 0; i < 14; i++)
{
char *inp = inbuf;
size_t inleft = sizeof (inbuf) - 1;
char *outp = outbufbase - i;
size_t outleft = i;
TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
== (size_t) -1);
TEST_COMPARE (errno, E2BIG);
TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
}
}
/* Same as before for SS3designation. */
{
char inbuf[] = "\xe5\x8a\x84";
for (int i = 0; i < 14; i++)
{
char *inp = inbuf;
size_t inleft = sizeof (inbuf) - 1;
char *outp = outbufbase - i;
size_t outleft = i;
TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
== (size_t) -1);
TEST_COMPARE (errno, E2BIG);
TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
}
}
TEST_VERIFY_EXIT (iconv_close (cd) != -1);
xmunmap (ntf, ntfsize);
return 0;
}
#include <support/test-driver.c>
+13 -13
View File
@@ -59,6 +59,19 @@
# define IN_MODULE (-1)
#endif
/* Use symbol_version_reference to specify the version a symbol
reference should link to. Use symbol_version or
default_symbol_version for the definition of a versioned symbol.
The difference is that the latter is a no-op in non-shared
builds. */
#ifdef __ASSEMBLER__
# define symbol_version_reference(real, name, version) \
.symver real, name##@##version
#else /* !__ASSEMBLER__ */
# define symbol_version_reference(real, name, version) \
__asm__ (".symver " #real "," #name "@" #version)
#endif
#ifndef _ISOMAC
/* This is defined for the compilation of all C library code. features.h
@@ -396,19 +409,6 @@ for linking")
past the last element in SET. */
#define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set)
/* Use symbol_version_reference to specify the version a symbol
reference should link to. Use symbol_version or
default_symbol_version for the definition of a versioned symbol.
The difference is that the latter is a no-op in non-shared
builds. */
#ifdef __ASSEMBLER__
# define symbol_version_reference(real, name, version) \
.symver real, name##@##version
#else /* !__ASSEMBLER__ */
# define symbol_version_reference(real, name, version) \
__asm__ (".symver " #real "," #name "@" #version)
#endif
#ifdef SHARED
# define symbol_version(real, name, version) \
symbol_version_reference(real, name, version)
+12
View File
@@ -1 +1,13 @@
#include <socket/sys/un.h>
#ifndef _ISOMAC
/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME.
Return 0 on success or -1 on failure (due to overlong PATHNAME).
The caller should always use sizeof (struct sockaddr_un) as the
socket address length, disregaring the length of PATHNAME.
Only concrete (non-abstract) pathnames are supported. */
int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
attribute_hidden;
#endif /* _ISOMAC */
+5
View File
@@ -502,6 +502,11 @@ time_now (void)
__clock_gettime (TIME_CLOCK_GETTIME_CLOCKID, &ts);
return ts.tv_sec;
}
#define NSEC_PER_SEC 1000000000L /* Nanoseconds per second. */
#define USEC_PER_SEC 1000000L /* Microseconds per second. */
#define NSEC_PER_USEC 1000L /* Nanoseconds per microsecond. */
#endif
#endif
+1 -1
View File
@@ -68,7 +68,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
tst-fts tst-fts-lfs tst-open-tmpfile \
tst-copy_file_range tst-getcwd-abspath tst-lockf \
tst-ftw-lnk tst-file_change_detection tst-lchmod \
tst-ftw-bz26353
tst-ftw-bz26353 tst-stat tst-stat-lfs
# Likewise for statx, but we do not need static linking here.
tests-internal += tst-statx
+6
View File
@@ -16,10 +16,16 @@
<https://www.gnu.org/licenses/>. */
#include <sys/stat.h>
#include <errno.h>
int
__fstat (int fd, struct stat *buf)
{
if (fd < 0)
{
__set_errno (EBADF);
return -1;
}
return __fstatat (fd, "", buf, AT_EMPTY_PATH);
}
+6
View File
@@ -16,10 +16,16 @@
<https://www.gnu.org/licenses/>. */
#include <sys/stat.h>
#include <errno.h>
int
__fstat64 (int fd, struct stat64 *buf)
{
if (fd < 0)
{
__set_errno (EBADF);
return -1;
}
return __fstatat64 (fd, "", buf, AT_EMPTY_PATH);
}
hidden_def (__fstat64)
+2
View File
@@ -0,0 +1,2 @@
#define _FILE_OFFSET_BITS 64
#include "tst-stat.c"
+102
View File
@@ -0,0 +1,102 @@
/* Basic tests for stat, lstat, fstat, and fstatat.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
#include <errno.h>
#include <fcntl.h>
#include <support/check.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/xunistd.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
static void
stat_check (int fd, const char *path, struct stat *st)
{
TEST_COMPARE (stat (path, st), 0);
}
static void
lstat_check (int fd, const char *path, struct stat *st)
{
TEST_COMPARE (lstat (path, st), 0);
}
static void
fstat_check (int fd, const char *path, struct stat *st)
{
/* Test for invalid fstat input (BZ #27559). */
TEST_COMPARE (fstat (AT_FDCWD, st), -1);
TEST_COMPARE (errno, EBADF);
TEST_COMPARE (fstat (fd, st), 0);
}
static void
fstatat_check (int fd, const char *path, struct stat *st)
{
TEST_COMPARE (fstatat (fd, "", st, 0), -1);
TEST_COMPARE (errno, ENOENT);
TEST_COMPARE (fstatat (fd, path, st, 0), 0);
}
typedef void (*test_t)(int, const char *path, struct stat *);
static int
do_test (void)
{
char *path;
int fd = create_temp_file ("tst-fstat.", &path);
TEST_VERIFY_EXIT (fd >= 0);
support_write_file_string (path, "abc");
struct statx stx;
TEST_COMPARE (statx (fd, path, 0, STATX_BASIC_STATS, &stx), 0);
test_t tests[] = { stat_check, lstat_check, fstat_check, fstatat_check };
for (int i = 0; i < array_length (tests); i++)
{
struct stat st;
tests[i](fd, path, &st);
TEST_COMPARE (stx.stx_dev_major, major (st.st_dev));
TEST_COMPARE (stx.stx_dev_minor, minor (st.st_dev));
TEST_COMPARE (stx.stx_ino, st.st_ino);
TEST_COMPARE (stx.stx_mode, st.st_mode);
TEST_COMPARE (stx.stx_nlink, st.st_nlink);
TEST_COMPARE (stx.stx_uid, st.st_uid);
TEST_COMPARE (stx.stx_gid, st.st_gid);
TEST_COMPARE (stx.stx_rdev_major, major (st.st_rdev));
TEST_COMPARE (stx.stx_rdev_minor, minor (st.st_rdev));
TEST_COMPARE (stx.stx_blksize, st.st_blksize);
TEST_COMPARE (stx.stx_blocks, st.st_blocks);
TEST_COMPARE (stx.stx_ctime.tv_sec, st.st_ctim.tv_sec);
TEST_COMPARE (stx.stx_ctime.tv_nsec, st.st_ctim.tv_nsec);
TEST_COMPARE (stx.stx_mtime.tv_sec, st.st_mtim.tv_sec);
TEST_COMPARE (stx.stx_mtime.tv_nsec, st.st_mtim.tv_nsec);
}
return 0;
}
#include <support/test-driver.c>
+8 -4
View File
@@ -3446,7 +3446,9 @@ __libc_realloc (void *oldmem, size_t bytes)
newp = __libc_malloc (bytes);
if (newp != NULL)
{
memcpy (newp, oldmem, oldsize - SIZE_SZ);
size_t sz = CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ;
memcpy (newp, oldmem, sz);
(void) TAG_REGION (chunk2rawmem (oldp), sz);
_int_free (ar_ptr, oldp, 0);
}
}
@@ -4909,7 +4911,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
if (!checked_request2size (bytes, &nb))
if (!checked_request2size (bytes, &nb) || alignment > PTRDIFF_MAX)
{
__set_errno (ENOMEM);
return NULL;
@@ -4920,8 +4922,10 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
request, and then possibly free the leading and trailing space.
*/
/* Call malloc with worst case padding to hit alignment. */
/* Call malloc with worst case padding to hit alignment. ALIGNMENT is a
power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of
space to add MINSIZE and whatever checked_request2size adds to BYTES to
get NB. Consequently, total below also does not overflow. */
m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
if (m == 0)
+2 -8
View File
@@ -127,7 +127,6 @@ test_large_allocations (size_t size)
}
static long pagesize;
/* This function tests the following aligned memory allocation functions
using several valid alignments and precedes each allocation test with a
@@ -146,8 +145,8 @@ test_large_aligned_allocations (size_t size)
/* All aligned memory allocation functions expect an alignment that is a
power of 2. Given this, we test each of them with every valid
alignment from 1 thru PAGESIZE. */
for (align = 1; align <= pagesize; align *= 2)
alignment for the type of ALIGN, i.e. until it wraps to 0. */
for (align = 1; align > 0; align <<= 1)
{
test_setup ();
#if __GNUC_PREREQ (7, 0)
@@ -240,11 +239,6 @@ do_test (void)
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
#endif
/* Aligned memory allocation functions need to be tested up to alignment
size equivalent to page size, which should be a power of 2. */
pagesize = sysconf (_SC_PAGESIZE);
TEST_VERIFY_EXIT (powerof2 (pagesize));
/* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
+7 -9
View File
@@ -98,17 +98,16 @@ where it can expect the tunable value to be passed in VALP.
Tunables in the module can be updated using:
TUNABLE_SET (check, int32_t, val)
TUNABLE_SET (check, val)
where 'check' is the tunable name, 'int32_t' is the C type of the tunable and
'val' is a value of same type.
where 'check' is the tunable name and 'val' is a value of same type.
To get and set tunables in a different namespace from that module, use the full
form of the macros as follows:
val = TUNABLE_GET_FULL (glibc, cpu, hwcap_mask, uint64_t, NULL)
TUNABLE_SET_FULL (glibc, cpu, hwcap_mask, uint64_t, val)
TUNABLE_SET_FULL (glibc, cpu, hwcap_mask, val)
where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the
remaining arguments are the same as the short form macros.
@@ -116,18 +115,17 @@ remaining arguments are the same as the short form macros.
The minimum and maximum values can updated together with the tunable value
using:
TUNABLE_SET_WITH_BOUNDS (check, int32_t, val, min, max)
TUNABLE_SET_WITH_BOUNDS (check, val, min, max)
where 'check' is the tunable name, 'int32_t' is the C type of the tunable,
'val' is a value of same type, 'min' and 'max' are the minimum and maximum
values of the tunable.
where 'check' is the tunable name, 'val' is a value of same type, 'min' and
'max' are the minimum and maximum values of the tunable.
To set the minimum and maximum values of tunables in a different namespace
from that module, use the full form of the macros as follows:
val = TUNABLE_GET_FULL (glibc, cpu, hwcap_mask, uint64_t, NULL)
TUNABLE_SET_WITH_BOUNDS_FULL (glibc, cpu, hwcap_mask, uint64_t, val, min, max)
TUNABLE_SET_WITH_BOUNDS_FULL (glibc, cpu, hwcap_mask, val, min, max)
where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the
remaining arguments are the same as the short form macros.
+3
View File
@@ -510,6 +510,9 @@ capability.
@item
@code{RTM} -- RTM instruction extensions.
@item
@code{RTM_ALWAYS_ABORT} -- Transactions always abort, making RTM unusable.
@item
@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug.
+1 -1
View File
@@ -46,7 +46,7 @@ glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff)
glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647)
glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff)
glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0x0fffffffffffffff)
glibc.cpu.x86_shstk:
glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff)
glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
+1 -1
View File
@@ -88,7 +88,7 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
tst-mntent-autofs tst-syscalls tst-mntent-escape
tst-mntent-autofs tst-syscalls tst-mntent-escape tst-select
# Tests which need libdl.
ifeq (yes,$(build-shared))
+143
View File
@@ -0,0 +1,143 @@
/* Test for select timeout.
Copyright (C) 2021 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 <errno.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/support.h>
#include <support/timespec.h>
#include <support/xunistd.h>
#include <support/xtime.h>
#include <support/xsignal.h>
struct child_args
{
int fds[2][2];
struct timeval tmo;
};
static void
alarm_handler (int signum)
{
/* Do nothing. */
}
static void
do_test_child (void *clousure)
{
struct child_args *args = (struct child_args *) clousure;
close (args->fds[0][1]);
close (args->fds[1][0]);
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (args->fds[0][0], &rfds);
struct timespec ts = xclock_now (CLOCK_REALTIME);
ts = timespec_add (ts, (struct timespec) { args->tmo.tv_sec, 0 });
int r = select (args->fds[0][0] + 1, &rfds, NULL, NULL, &args->tmo);
TEST_COMPARE (r, 0);
if (support_select_modifies_timeout ())
{
TEST_COMPARE (args->tmo.tv_sec, 0);
TEST_COMPARE (args->tmo.tv_usec, 0);
}
TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
xwrite (args->fds[1][1], "foo", 3);
}
static void
do_test_child_alarm (void *clousure)
{
struct sigaction act = { .sa_handler = alarm_handler };
xsigaction (SIGALRM, &act, NULL);
alarm (1);
struct timeval tv = { .tv_sec = 10, .tv_usec = 0 };
int r = select (0, NULL, NULL, NULL, &tv);
TEST_COMPARE (r, -1);
TEST_COMPARE (errno, EINTR);
if (support_select_modifies_timeout ())
TEST_VERIFY (tv.tv_sec < 10);
}
static int
do_test (void)
{
struct child_args args;
xpipe (args.fds[0]);
xpipe (args.fds[1]);
/* The child select should timeout and write on its pipe end. */
args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 250000 };
{
struct support_capture_subprocess result;
result = support_capture_subprocess (do_test_child, &args);
support_capture_subprocess_check (&result, "tst-select-child", 0,
sc_allow_none);
}
if (support_select_normalizes_timeout ())
{
/* This is handled as 1 second instead of failing with EINVAL. */
args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 1000000 };
struct support_capture_subprocess result;
result = support_capture_subprocess (do_test_child, &args);
support_capture_subprocess_check (&result, "tst-select-child", 0,
sc_allow_none);
}
/* Same as before, but simulating polling. */
args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
{
struct support_capture_subprocess result;
result = support_capture_subprocess (do_test_child, &args);
support_capture_subprocess_check (&result, "tst-select-child", 0,
sc_allow_none);
}
xclose (args.fds[0][0]);
xclose (args.fds[1][1]);
{
struct support_capture_subprocess result;
result = support_capture_subprocess (do_test_child_alarm, NULL);
support_capture_subprocess_check (&result, "tst-select-child", 0,
sc_allow_none);
}
{
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (args.fds[1][0], &rfds);
int r = select (args.fds[1][0] + 1, &rfds, NULL, NULL, &args.tmo);
TEST_COMPARE (r, 1);
}
return 0;
}
#include <support/test-driver.c>
+20 -6
View File
@@ -294,7 +294,8 @@ tests = tst-attr2 tst-attr3 tst-default-attr \
tst-thread-affinity-sched \
tst-pthread-defaultattr-free \
tst-pthread-attr-sigmask \
tst-pthread-timedlock-lockloop
tst-pthread-timedlock-lockloop \
tst-pthread-gdb-attach tst-pthread-gdb-attach-static
tests-container = tst-pthread-getattr
@@ -314,10 +315,6 @@ xtests += tst-eintr1
test-srcs = tst-oddstacklimit
# Test expected to fail on most targets (except x86_64) due to bug
# 18435 - pthread_once hangs when init routine throws an exception.
test-xfail-tst-once5 = yes
gen-as-const-headers = unwindbuf.sym \
pthread-pi-defines.sym
@@ -344,6 +341,22 @@ CPPFLAGS-test-cond-printers.c := $(CFLAGS-printers-tests)
CPPFLAGS-test-rwlockattr-printers.c := $(CFLAGS-printers-tests)
CPPFLAGS-test-rwlock-printers.c := $(CFLAGS-printers-tests)
# Reuse the CFLAGS setting for the GDB attaching test. It needs
# debugging information.
CFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests)
CPPFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests)
ifeq ($(build-shared)$(build-hardcoded-path-in-tests),yesno)
CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=1
else
CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=0
endif
CFLAGS-tst-pthread-gdb-attach-static.c := $(CFLAGS-printers-tests)
CPPFLAGS-tst-pthread-gdb-attach-static.c := \
$(CFLAGS-printers-tests) -DDO_ADD_SYMBOL_FILE=0
# As of version 9.2, GDB cannot attach properly to PIE programs that
# were launched with an explicit ld.so invocation.
tst-pthread-gdb-attach-no-pie = yes
ifeq ($(build-shared),yes)
tests-printers-libs := $(shared-thread-library)
else
@@ -415,7 +428,8 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
tests-static += tst-stackguard1-static \
tst-cancel24-static \
tst-mutex8-static tst-mutexpi8-static tst-sem11-static \
tst-sem12-static tst-cond11-static
tst-sem12-static tst-cond11-static \
tst-pthread-gdb-attach-static
tests += tst-cancel24-static
+62
View File
@@ -35,6 +35,7 @@
#include <kernel-features.h>
#include <errno.h>
#include <internal-signals.h>
#include <pthread_mutex_backoff.h>
#include "pthread_mutex_conf.h"
@@ -602,6 +603,67 @@ extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
# undef pthread_cleanup_pop
# define pthread_cleanup_pop(execute) \
__pthread_cleanup_pop (&_buffer, (execute)); }
# if defined __EXCEPTIONS && !defined __cplusplus
/* Structure to hold the cleanup handler information. */
struct __pthread_cleanup_combined_frame
{
void (*__cancel_routine) (void *);
void *__cancel_arg;
int __do_it;
struct _pthread_cleanup_buffer __buffer;
};
/* Special cleanup macros which register cleanup both using
__pthread_cleanup_{push,pop} and using cleanup attribute. This is needed
for pthread_once, so that it supports both throwing exceptions from the
pthread_once callback (only cleanup attribute works there) and cancellation
of the thread running the callback if the callback or some routines it
calls don't have unwind information. */
static __always_inline void
__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame
*__frame)
{
if (__frame->__do_it)
{
__frame->__cancel_routine (__frame->__cancel_arg);
__frame->__do_it = 0;
__pthread_cleanup_pop (&__frame->__buffer, 0);
}
}
static inline void
__pthread_cleanup_combined_routine_voidptr (void *__arg)
{
struct __pthread_cleanup_combined_frame *__frame
= (struct __pthread_cleanup_combined_frame *) __arg;
if (__frame->__do_it)
{
__frame->__cancel_routine (__frame->__cancel_arg);
__frame->__do_it = 0;
}
}
# define pthread_cleanup_combined_push(routine, arg) \
do { \
void (*__cancel_routine) (void *) = (routine); \
struct __pthread_cleanup_combined_frame __clframe \
__attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \
= { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \
.__do_it = 1 }; \
__pthread_cleanup_push (&__clframe.__buffer, \
__pthread_cleanup_combined_routine_voidptr, \
&__clframe);
# define pthread_cleanup_combined_pop(execute) \
__pthread_cleanup_pop (&__clframe.__buffer, 0); \
__clframe.__do_it = 0; \
if (execute) \
__cancel_routine (__clframe.__cancel_arg); \
} while (0)
# endif
#endif
extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
+10 -2
View File
@@ -51,6 +51,14 @@ static td_thr_events_t __nptl_threads_events __attribute_used__;
/* Pointer to descriptor with the last event. */
static struct pthread *__nptl_last_event __attribute_used__;
#ifdef SHARED
/* This variable is used to access _rtld_global from libthread_db. If
GDB loads libpthread before ld.so, it is not possible to resolve
_rtld_global directly during libpthread initialization. */
static struct rtld_global *__nptl_rtld_global __attribute_used__
= &_rtld_global;
#endif
/* Number of threads running. */
unsigned int __nptl_nthreads = 1;
@@ -426,8 +434,6 @@ START_THREAD_DEFN
unwind_buf.priv.data.prev = NULL;
unwind_buf.priv.data.cleanup = NULL;
__libc_signal_restore_set (&pd->sigmask);
/* Allow setxid from now onwards. */
if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
@@ -437,6 +443,8 @@ START_THREAD_DEFN
/* Store the new cleanup handler info. */
THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
__libc_signal_restore_set (&pd->sigmask);
/* We are either in (a) or (b), and in either case we either own
PD already (2) or are about to own PD (1), and so our only
restriction would be that we can't free PD until we know we
+25 -8
View File
@@ -56,6 +56,11 @@
#define FORCE_ELISION(m, s)
#endif
#ifndef LLL_MUTEX_READ_LOCK
# define LLL_MUTEX_READ_LOCK(mutex) \
atomic_load_relaxed (&(mutex)->__data.__lock)
#endif
static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
__attribute_noinline__;
@@ -125,16 +130,29 @@ __pthread_mutex_lock (pthread_mutex_t *mutex)
int cnt = 0;
int max_cnt = MIN (max_adaptive_count (),
mutex->__data.__spins * 2 + 10);
int spin_count, exp_backoff = 1;
unsigned int jitter = get_jitter ();
do
{
if (cnt++ >= max_cnt)
/* In each loop, spin count is exponential backoff plus
random jitter, random range is [0, exp_backoff-1]. */
spin_count = exp_backoff + (jitter & (exp_backoff - 1));
cnt += spin_count;
if (cnt >= max_cnt)
{
/* If cnt exceeds max spin count, just go to wait
queue. */
LLL_MUTEX_LOCK (mutex);
break;
}
atomic_spin_nop ();
do
atomic_spin_nop ();
while (--spin_count > 0);
/* Prepare for next loop. */
exp_backoff = get_next_backoff (exp_backoff);
}
while (LLL_MUTEX_TRYLOCK (mutex) != 0);
while (LLL_MUTEX_READ_LOCK (mutex) != 0
|| LLL_MUTEX_TRYLOCK (mutex) != 0);
mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
}
@@ -289,12 +307,11 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
meantime. */
if ((oldval & FUTEX_WAITERS) == 0)
{
if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
oldval | FUTEX_WAITERS,
oldval)
!= 0)
int val = atomic_compare_and_exchange_val_acq
(&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
if (val != oldval)
{
oldval = mutex->__data.__lock;
oldval = val;
continue;
}
oldval |= FUTEX_WAITERS;
+4 -5
View File
@@ -247,12 +247,11 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
meantime. */
if ((oldval & FUTEX_WAITERS) == 0)
{
if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
oldval | FUTEX_WAITERS,
oldval)
!= 0)
int val = atomic_compare_and_exchange_val_acq
(&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
if (val != oldval)
{
oldval = mutex->__data.__lock;
oldval = val;
continue;
}
oldval |= FUTEX_WAITERS;
+6 -2
View File
@@ -57,7 +57,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
return 0;
}
if (lll_trylock (mutex->__data.__lock) == 0)
if (atomic_load_relaxed (&(mutex->__data.__lock)) == 0
&& lll_trylock (mutex->__data.__lock) == 0)
{
/* Record the ownership. */
mutex->__data.__owner = id;
@@ -80,7 +81,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
/*FALL THROUGH*/
case PTHREAD_MUTEX_ADAPTIVE_NP:
case PTHREAD_MUTEX_ERRORCHECK_NP:
if (lll_trylock (mutex->__data.__lock) != 0)
/* Mutex type is already loaded, lock check overhead should
be minimal. */
if (atomic_load_relaxed (&(mutex->__data.__lock)) != 0
|| lll_trylock (mutex->__data.__lock) != 0)
break;
/* Record the ownership. */
+2 -2
View File
@@ -111,11 +111,11 @@ __pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
/* This thread is the first here. Do the initialization.
Register a cleanup handler so that in case the thread gets
interrupted the initialization can be restarted. */
pthread_cleanup_push (clear_once_control, once_control);
pthread_cleanup_combined_push (clear_once_control, once_control);
init_routine ();
pthread_cleanup_pop (0);
pthread_cleanup_combined_pop (0);
/* Mark *once_control as having finished the initialization. We need
+1 -3
View File
@@ -59,7 +59,7 @@ do_test (void)
" throwing an exception", stderr);
}
catch (OnceException) {
if (1 < niter)
if (niter > 1)
fputs ("pthread_once unexpectedly threw", stderr);
result = 0;
}
@@ -75,7 +75,5 @@ do_test (void)
return result;
}
// The test currently hangs and is XFAILed. Reduce the timeout.
#define TIMEOUT 1
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+1
View File
@@ -0,0 +1 @@
#include "tst-pthread-gdb-attach.c"
+217
View File
@@ -0,0 +1,217 @@
/* Smoke testing GDB process attach with thread-local variable access.
Copyright (C) 2021 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 runs GDB against a forked copy of itself, to check
whether libthread_db can be loaded, and that access to thread-local
variables works. */
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <support/xstdio.h>
#include <support/xthread.h>
#include <support/xunistd.h>
#include <unistd.h>
/* Starts out as zero, changed to 1 or 2 by the debugger, depending on
the thread. */
__thread volatile int altered_by_debugger;
/* Common prefix between 32-bit and 64-bit ELF. */
struct elf_prefix
{
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
};
_Static_assert (sizeof (struct elf_prefix) == EI_NIDENT + 8,
"padding in struct elf_prefix");
/* Reads the ELF header from PATH. Returns true if the header can be
read, false if the file is too short. */
static bool
read_elf_header (const char *path, struct elf_prefix *elf)
{
int fd = xopen (path, O_RDONLY, 0);
bool result = read (fd, elf, sizeof (*elf)) == sizeof (*elf);
xclose (fd);
return result;
}
/* Searches for "gdb" alongside the path variable. See execvpe. */
static char *
find_gdb (void)
{
const char *path = getenv ("PATH");
if (path == NULL)
return NULL;
while (true)
{
const char *colon = strchrnul (path, ':');
char *candidate = xasprintf ("%.*s/gdb", (int) (colon - path), path);
if (access (candidate, X_OK) == 0)
return candidate;
free (candidate);
if (*colon == '\0')
break;
path = colon + 1;
}
return NULL;
}
/* Writes the GDB script to run the test to PATH. */
static void
write_gdbscript (const char *path, int tested_pid)
{
FILE *fp = xfopen (path, "w");
fprintf (fp,
"set trace-commands on\n"
"set debug libthread-db 1\n"
#if DO_ADD_SYMBOL_FILE
/* Do not do this unconditionally to work around a GDB
assertion failure: ../../gdb/symtab.c:6404:
internal-error: CORE_ADDR get_msymbol_address(objfile*,
const minimal_symbol*): Assertion `(objf->flags &
OBJF_MAINLINE) == 0' failed. */
"add-symbol-file %1$s/nptl/tst-pthread-gdb-attach\n"
#endif
"set auto-load safe-path %1$s/nptl_db\n"
"set libthread-db-search-path %1$s/nptl_db\n"
"attach %2$d\n",
support_objdir_root, tested_pid);
fputs ("break debugger_inspection_point\n"
"continue\n"
"thread 1\n"
"print altered_by_debugger\n"
"print altered_by_debugger = 1\n"
"thread 2\n"
"print altered_by_debugger\n"
"print altered_by_debugger = 2\n"
"continue\n",
fp);
xfclose (fp);
}
/* The test sets a breakpoint on this function and alters the
altered_by_debugger thread-local variable. */
void __attribute__ ((weak))
debugger_inspection_point (void)
{
}
/* Thread function for the test thread in the subprocess. */
static void *
subprocess_thread (void *closure)
{
/* Wait until altered_by_debugger changes the value away from 0. */
while (altered_by_debugger == 0)
{
usleep (100 * 1000);
debugger_inspection_point ();
}
TEST_COMPARE (altered_by_debugger, 2);
return NULL;
}
/* This function implements the subprocess under test. It creates a
second thread, waiting for its value to change to 2, and checks
that the main thread also changed its value to 1. */
static void
in_subprocess (void)
{
pthread_t thr = xpthread_create (NULL, subprocess_thread, NULL);
TEST_VERIFY (xpthread_join (thr) == NULL);
TEST_COMPARE (altered_by_debugger, 1);
_exit (0);
}
static int
do_test (void)
{
char *gdb_path = find_gdb ();
if (gdb_path == NULL)
FAIL_UNSUPPORTED ("gdb command not found in PATH: %s", getenv ("PATH"));
/* Check that libthread_db is compatible with the gdb architecture
because gdb loads it via dlopen. */
{
char *threaddb_path = xasprintf ("%s/nptl_db/libthread_db.so",
support_objdir_root);
struct elf_prefix elf_threaddb;
TEST_VERIFY_EXIT (read_elf_header (threaddb_path, &elf_threaddb));
struct elf_prefix elf_gdb;
/* If the ELF header cannot be read or "gdb" is not an ELF file,
assume this is a wrapper script that can run. */
if (read_elf_header (gdb_path, &elf_gdb)
&& memcmp (&elf_gdb, ELFMAG, SELFMAG) == 0)
{
if (elf_gdb.e_ident[EI_CLASS] != elf_threaddb.e_ident[EI_CLASS])
FAIL_UNSUPPORTED ("GDB at %s has wrong class", gdb_path);
if (elf_gdb.e_ident[EI_DATA] != elf_threaddb.e_ident[EI_DATA])
FAIL_UNSUPPORTED ("GDB at %s has wrong data", gdb_path);
if (elf_gdb.e_machine != elf_threaddb.e_machine)
FAIL_UNSUPPORTED ("GDB at %s has wrong machine", gdb_path);
}
free (threaddb_path);
}
pid_t tested_pid = xfork ();
if (tested_pid == 0)
in_subprocess ();
char *tested_pid_string = xasprintf ("%d", tested_pid);
char *gdbscript;
xclose (create_temp_file ("tst-pthread-gdb-attach-", &gdbscript));
write_gdbscript (gdbscript, tested_pid);
pid_t gdb_pid = xfork ();
if (gdb_pid == 0)
{
xdup2 (STDOUT_FILENO, STDERR_FILENO);
execl (gdb_path, "gdb", "-nx", "-batch", "-x", gdbscript, NULL);
if (errno == ENOENT)
_exit (EXIT_UNSUPPORTED);
else
_exit (1);
}
int status;
TEST_COMPARE (xwaitpid (gdb_pid, &status, 0), gdb_pid);
if (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_UNSUPPORTED)
/* gdb is not installed. */
return EXIT_UNSUPPORTED;
TEST_COMPARE (status, 0);
TEST_COMPARE (xwaitpid (tested_pid, &status, 0), tested_pid);
TEST_COMPARE (status, 0);
free (tested_pid_string);
free (gdbscript);
free (gdb_path);
return 0;
}
#include <support/test-driver.c>
+1 -1
View File
@@ -26,7 +26,7 @@
#include <libc-diag.h>
#include <jmpbuf-unwind.h>
#ifdef _STACK_GROWS_DOWN
#if _STACK_GROWS_DOWN
# define FRAME_LEFT(frame, other, adj) \
((uintptr_t) frame - adj >= (uintptr_t) other - adj)
#elif _STACK_GROWS_UP
+1 -2
View File
@@ -100,8 +100,7 @@ DB_STRUCT_FIELD (pthread, dtvp)
#endif
#if !(IS_IN (libpthread) && !defined SHARED)
DB_STRUCT (rtld_global)
DB_RTLD_VARIABLE (_rtld_global)
DB_VARIABLE (__nptl_rtld_global)
#endif
DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
DB_RTLD_GLOBAL_FIELD (dl_stack_user)
+8 -7
View File
@@ -33,13 +33,14 @@ td_init (void)
bool
__td_ta_rtld_global (td_thragent_t *ta)
{
if (ta->ta_addr__rtld_global == 0
&& td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
&ta->ta_addr__rtld_global) != PS_OK)
if (ta->ta_addr__rtld_global == 0)
{
ta->ta_addr__rtld_global = (void*)-1;
return false;
psaddr_t rtldglobalp;
if (DB_GET_VALUE (rtldglobalp, ta, __nptl_rtld_global, 0) == TD_OK)
ta->ta_addr__rtld_global = rtldglobalp;
else
ta->ta_addr__rtld_global = (void *) -1;
}
else
return ta->ta_addr__rtld_global != (void*)-1;
return ta->ta_addr__rtld_global != (void *)-1;
}
+2
View File
@@ -108,6 +108,8 @@ struct td_thragent
# undef DB_SYMBOL
# undef DB_VARIABLE
psaddr_t ta_addr__rtld_global;
/* The method of locating a thread's th_unique value. */
enum
{
+137 -112
View File
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <scratch_buffer.h>
#include "../inet/netgroup.h"
#include "nscd.h"
@@ -66,6 +67,16 @@ struct dataset
char strdata[0];
};
/* Send a notfound response to FD. Always returns -1 to indicate an
ephemeral error. */
static time_t
send_notfound (int fd)
{
if (fd != -1)
TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
return -1;
}
/* Sends a notfound message and prepares a notfound dataset to write to the
cache. Returns true if there was enough memory to allocate the dataset and
returns the dataset in DATASETP, total bytes to write in TOTALP and the
@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
total = sizeof (notfound);
timeout = time (NULL) + db->negtimeout;
if (fd != -1)
TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
send_notfound (fd);
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
/* If we cannot permanently store the result, so be it. */
@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
return cacheable;
}
struct addgetnetgrentX_scratch
{
/* This is the result that the caller should use. It can be NULL,
point into buffer, or it can be in the cache. */
struct dataset *dataset;
struct scratch_buffer buffer;
/* Used internally in addgetnetgrentX as a staging area. */
struct scratch_buffer tmp;
/* Number of bytes in buffer that are actually used. */
size_t buffer_used;
};
static void
addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
{
scratch->dataset = NULL;
scratch_buffer_init (&scratch->buffer);
scratch_buffer_init (&scratch->tmp);
/* Reserve space for the header. */
scratch->buffer_used = sizeof (struct dataset);
static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
"initial buffer space");
memset (scratch->tmp.data, 0, sizeof (struct dataset));
}
static void
addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
{
scratch_buffer_free (&scratch->buffer);
scratch_buffer_free (&scratch->tmp);
}
/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
could not be resized, otherwise a pointer to the copy. */
static char *
addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
const char *s, size_t length)
{
while (true)
{
size_t remaining = scratch->buffer.length - scratch->buffer_used;
if (remaining >= length)
break;
if (!scratch_buffer_grow_preserve (&scratch->buffer))
return NULL;
}
char *copy = scratch->buffer.data + scratch->buffer_used;
memcpy (copy, s, length);
scratch->buffer_used += length;
return copy;
}
/* Copy S into SCRATCH, including its null terminator. Returns false
if SCRATCH could not be resized. */
static bool
addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
{
if (s == NULL)
s = "";
return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
}
/* Caller must initialize and free *SCRATCH. If the return value is
negative, this function has sent a notfound response. */
static time_t
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
struct datahead *dh, struct dataset **resultp,
void **tofreep)
struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
{
if (__glibc_unlikely (debug_level > 0))
{
@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
char *key_copy = NULL;
struct __netgrent data;
size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
size_t buffilled = sizeof (*dataset);
char *buffer = NULL;
size_t nentries = 0;
size_t group_len = strlen (key) + 1;
struct name_list *first_needed
= alloca (sizeof (struct name_list) + group_len);
*tofreep = NULL;
if (netgroup_database == NULL
&& __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database))
@@ -148,12 +221,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
/* No such service. */
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
goto writeout;
goto maybe_cache_add;
}
memset (&data, '\0', sizeof (data));
buffer = xmalloc (buflen);
*tofreep = buffer;
first_needed->next = first_needed;
memcpy (first_needed->name, key, group_len);
data.needed_groups = first_needed;
@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
while (1)
{
int e;
status = getfct.f (&data, buffer + buffilled,
buflen - buffilled - req->key_len, &e);
status = getfct.f (&data, scratch->tmp.data,
scratch->tmp.length, &e);
if (status == NSS_STATUS_SUCCESS)
{
if (data.type == triple_val)
@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *nhost = data.val.triple.host;
const char *nuser = data.val.triple.user;
const char *ndomain = data.val.triple.domain;
size_t hostlen = strlen (nhost ?: "") + 1;
size_t userlen = strlen (nuser ?: "") + 1;
size_t domainlen = strlen (ndomain ?: "") + 1;
if (nhost == NULL || nuser == NULL || ndomain == NULL
|| nhost > nuser || nuser > ndomain)
{
const char *last = nhost;
if (last == NULL
|| (nuser != NULL && nuser > last))
last = nuser;
if (last == NULL
|| (ndomain != NULL && ndomain > last))
last = ndomain;
size_t bufused
= (last == NULL
? buffilled
: last + strlen (last) + 1 - buffer);
/* We have to make temporary copies. */
size_t needed = hostlen + userlen + domainlen;
if (buflen - req->key_len - bufused < needed)
{
buflen += MAX (buflen, 2 * needed);
/* Save offset in the old buffer. We don't
bother with the NULL check here since
we'll do that later anyway. */
size_t nhostdiff = nhost - buffer;
size_t nuserdiff = nuser - buffer;
size_t ndomaindiff = ndomain - buffer;
char *newbuf = xrealloc (buffer, buflen);
/* Fix up the triplet pointers into the new
buffer. */
nhost = (nhost ? newbuf + nhostdiff
: NULL);
nuser = (nuser ? newbuf + nuserdiff
: NULL);
ndomain = (ndomain ? newbuf + ndomaindiff
: NULL);
buffer = newbuf;
}
nhost = memcpy (buffer + bufused,
nhost ?: "", hostlen);
nuser = memcpy ((char *) nhost + hostlen,
nuser ?: "", userlen);
ndomain = memcpy ((char *) nuser + userlen,
ndomain ?: "", domainlen);
}
char *wp = buffer + buffilled;
wp = memmove (wp, nhost ?: "", hostlen);
wp += hostlen;
wp = memmove (wp, nuser ?: "", userlen);
wp += userlen;
wp = memmove (wp, ndomain ?: "", domainlen);
wp += domainlen;
buffilled = wp - buffer;
if (!(addgetnetgrentX_append (scratch, nhost)
&& addgetnetgrentX_append (scratch, nuser)
&& addgetnetgrentX_append (scratch, ndomain)))
return send_notfound (fd);
++nentries;
}
else
@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
buflen *= 2;
buffer = xrealloc (buffer, buflen);
if (!scratch_buffer_grow (&scratch->tmp))
return send_notfound (fd);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
@@ -349,13 +362,20 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
{
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
goto writeout;
goto maybe_cache_add;
}
total = buffilled;
/* Capture the result size without the key appended. */
total = scratch->buffer_used;
/* Make a copy of the key. The scratch buffer must not move after
this point. */
key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
if (key_copy == NULL)
return send_notfound (fd);
/* Fill in the dataset. */
dataset = (struct dataset *) buffer;
dataset = scratch->buffer.data;
timeout = datahead_init_pos (&dataset->head, total + req->key_len,
total - offsetof (struct dataset, resp),
he == NULL ? 0 : dh->nreloads + 1,
@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1;
dataset->resp.nresults = nentries;
dataset->resp.result_len = buffilled - sizeof (*dataset);
assert (buflen - buffilled >= req->key_len);
key_copy = memcpy (buffer + buffilled, key, req->key_len);
buffilled += req->key_len;
dataset->resp.result_len = total - sizeof (*dataset);
/* Now we can determine whether on refill we have to create a new
record or not. */
@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
if (__glibc_likely (newp != NULL))
{
/* Adjust pointer into the memory block. */
key_copy = (char *) newp + (key_copy - buffer);
key_copy = (char *) newp + (key_copy - (char *) dataset);
dataset = memcpy (newp, dataset, total + req->key_len);
cacheable = true;
@@ -411,14 +427,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
if (he == NULL && fd != -1)
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would
unnecessarily let the receiver wait. */
writeout:
/* We write the dataset before inserting it to the database since
while inserting this thread might block and so would
unnecessarily let the receiver wait. */
writeall (fd, &dataset->resp, dataset->head.recsize);
}
maybe_cache_add:
if (cacheable)
{
/* If necessary, we also propagate the data to disk. */
@@ -442,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
out:
*resultp = dataset;
scratch->dataset = dataset;
return timeout;
}
@@ -463,6 +477,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
if (user != NULL)
key = (char *) rawmemchr (key, '\0') + 1;
const char *domain = *key++ ? key : NULL;
struct addgetnetgrentX_scratch scratch;
addgetnetgrentX_scratch_init (&scratch);
if (__glibc_unlikely (debug_level > 0))
{
@@ -478,12 +495,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
group, group_len,
db, uid);
time_t timeout;
void *tofree;
if (result != NULL)
{
timeout = result->head.timeout;
tofree = NULL;
}
timeout = result->head.timeout;
else
{
request_header req_get =
@@ -492,7 +505,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
.key_len = group_len
};
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
&result, &tofree);
&scratch);
result = scratch.dataset;
if (timeout < 0)
goto out;
}
struct indataset
@@ -503,24 +519,26 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
= (struct indataset *) mempool_alloc (db,
sizeof (*dataset) + req->key_len,
1);
struct indataset dataset_mem;
bool cacheable = true;
if (__glibc_unlikely (dataset == NULL))
{
cacheable = false;
dataset = &dataset_mem;
/* The alloca is safe because nscd_run_worker verfies that
key_len is not larger than MAXKEYLEN. */
dataset = alloca (sizeof (*dataset) + req->key_len);
}
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
sizeof (innetgroup_response_header),
he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
he == NULL ? 0 : dh->nreloads + 1,
result == NULL ? db->negtimeout : result->head.ttl);
/* Set the notfound status and timeout based on the result from
getnetgrent. */
dataset->head.notfound = result->head.notfound;
dataset->head.notfound = result == NULL || result->head.notfound;
dataset->head.timeout = timeout;
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = result->resp.found;
dataset->resp.found = result != NULL && result->resp.found;
/* Until we find a matching entry the result is 0. */
dataset->resp.result = 0;
@@ -568,7 +586,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
goto out;
}
if (he == NULL)
/* addgetnetgrentX may have already sent a notfound response. Do
not send another one. */
if (he == NULL && dataset->resp.found)
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would
@@ -602,7 +622,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
}
out:
free (tofree);
addgetnetgrentX_scratch_free (&scratch);
return timeout;
}
@@ -612,11 +632,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
struct datahead *dh)
{
struct dataset *ignore;
void *tofree;
time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
&ignore, &tofree);
free (tofree);
struct addgetnetgrentX_scratch scratch;
addgetnetgrentX_scratch_init (&scratch);
time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
addgetnetgrentX_scratch_free (&scratch);
if (timeout < 0)
timeout = 0;
return timeout;
}
@@ -660,5 +681,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
.key_len = he->len
};
return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
he, dh);
if (timeout < 0)
timeout = 0;
return timeout;
}
+2 -2
View File
@@ -398,10 +398,10 @@ nss_database_check_reload_and_get (struct nss_database_state *local,
&& (str.st_ino != local->root_ino
|| str.st_dev != local->root_dev)))
{
/* Change detected; disable reloading. */
/* Change detected; disable reloading and return current state. */
atomic_store_release (&local->data.reload_disabled, 1);
*result = local->data.services[database_index];
__libc_lock_unlock (local->lock);
__nss_module_disable_loading ();
return true;
}
local->root_ino = str.st_ino;
@@ -0,0 +1 @@
hosts: files
+28 -7
View File
@@ -26,6 +26,7 @@
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <netdb.h>
#include <support/support.h>
#include <support/check.h>
@@ -48,7 +49,7 @@ static const char *group_4[] = {
"alpha", "beta", "gamma", "fred", NULL
};
static struct group group_table_data[] =
static struct group group_table_data1[] =
{
GRP (4),
GRP_LAST ()
@@ -58,7 +59,7 @@ void
_nss_test1_init_hook (test_tables *t)
{
t->pwd_table = pwd_table1;
t->grp_table = group_table_data;
t->grp_table = group_table_data1;
}
static struct passwd pwd_table2[] =
@@ -68,10 +69,21 @@ static struct passwd pwd_table2[] =
PWD_LAST ()
};
static const char *group_5[] = {
"fred", NULL
};
static struct group group_table_data2[] =
{
GRP (5),
GRP_LAST ()
};
void
_nss_test2_init_hook (test_tables *t)
{
t->pwd_table = pwd_table2;
t->grp_table = group_table_data2;
}
static int
@@ -79,6 +91,7 @@ do_test (void)
{
struct passwd *pw;
struct group *gr;
struct hostent *he;
char buf1[PATH_MAX];
char buf2[PATH_MAX];
@@ -99,7 +112,9 @@ do_test (void)
TEST_COMPARE (pw->pw_uid, 1234);
/* This just loads the test2 DSO. */
gr = getgrnam ("name4");
gr = getgrgid (5);
TEST_VERIFY (gr != NULL);
/* Change the root dir. */
@@ -114,15 +129,21 @@ do_test (void)
if (pw)
TEST_VERIFY (pw->pw_uid != 2468);
/* The "files" DSO should not be loaded. */
gr = getgrnam ("test3");
TEST_VERIFY (gr == NULL);
/* We should still be using the old configuration. */
pw = getpwnam ("test1");
TEST_VERIFY (pw != NULL);
if (pw)
TEST_COMPARE (pw->pw_uid, 1234);
gr = getgrgid (5);
TEST_VERIFY (gr != NULL);
gr = getgrnam ("name4");
TEST_VERIFY (gr == NULL);
/* hosts in the outer nsswitch is files; the inner one is test1.
Verify that we're still using the outer nsswitch *and* that we
can load the files DSO. */
he = gethostbyname ("test2");
TEST_VERIFY (he != NULL);
return 0;
}
+1
View File
@@ -0,0 +1 @@
1.2.3.4 test1
+1
View File
@@ -1,2 +1,3 @@
passwd: test1
group: test2
hosts: files
+1
View File
@@ -0,0 +1 @@
1.2.3.4 test2
@@ -1,2 +1,3 @@
passwd: test2
group: files
hosts: test1
+16 -4
View File
@@ -102,7 +102,9 @@ tests := test-errno tstgetopt testfnm runtests runptests \
tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
tst-wordexp-nocmd
tst-wordexp-nocmd tst-regcomp-bracket-free \
tst-wordexp-reuse
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
tst-glob_lstat_compat tst-spawn4-compat
@@ -136,11 +138,13 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
bug-glob2.mtrace bug-glob2-mem.out tst-vfork3-mem.out \
tst-vfork3.mtrace getconf.speclist tst-fnmatch-mem.out \
tst-fnmatch.mtrace bug-regex36.mtrace \
testcases.h ptestcases.h
testcases.h ptestcases.h tst-wordexp-reuse-mem.out \
tst-wordexp-reuse.mtrace
ifeq ($(run-built-tests),yes)
ifeq (yes,$(build-shared))
tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out
tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out \
$(objpfx)wordexp-tst.out
endif
endif
@@ -154,7 +158,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
$(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
$(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
$(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
$(objpfx)tst-glob-tilde-mem.out $(objpfx)bug-ga2-mem.out
$(objpfx)tst-glob-tilde-mem.out $(objpfx)bug-ga2-mem.out \
$(objpfx)tst-wordexp-reuse.out
endif
include ../Rules
@@ -401,3 +406,10 @@ $(objpfx)posix-conf-vars-def.h: $(..)scripts/gen-posix-conf-vars.awk \
$(make-target-directory)
$(AWK) -f $(filter-out Makefile, $^) > $@.tmp
mv -f $@.tmp $@
tst-wordexp-reuse-ENV += MALLOC_TRACE=$(objpfx)tst-wordexp-reuse.mtrace \
LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
$(objpfx)tst-wordexp-reuse-mem.out: $(objpfx)tst-wordexp-reuse.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-wordexp-reuse.mtrace > $@; \
$(evaluate-test)
+2 -3
View File
@@ -199,10 +199,9 @@ __NTH (readlinkat (int __fd, const char *__restrict __path,
#endif
extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen)
__THROW __wur __attr_access ((__write_only__, 1, 2));
__THROW __wur;
extern char *__REDIRECT_NTH (__getcwd_alias,
(char *__buf, size_t __size), getcwd)
__wur __attr_access ((__write_only__, 1, 2));
(char *__buf, size_t __size), getcwd) __wur;
extern char *__REDIRECT_NTH (__getcwd_chk_warn,
(char *__buf, size_t __size, size_t __buflen),
__getcwd_chk)
+3 -1
View File
@@ -3367,6 +3367,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
{
#ifdef RE_ENABLE_I18N
free_charset (mbcset);
mbcset = NULL;
#endif
/* Build a tree for simple bracket. */
br_token.type = SIMPLE_BRACKET;
@@ -3382,7 +3383,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
parse_bracket_exp_free_return:
re_free (sbcset);
#ifdef RE_ENABLE_I18N
free_charset (mbcset);
if (__glibc_likely (mbcset != NULL))
free_charset (mbcset);
#endif /* RE_ENABLE_I18N */
return NULL;
}
+176
View File
@@ -0,0 +1,176 @@
/* Test regcomp bracket parsing with injected allocation failures (bug 33185).
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/>. */
/* This test invokes regcomp multiple times, failing one memory
allocation in each call. The function call should fail with
REG_ESPACE (or succeed if it can recover from the allocation
failure). Previously, there was double-free bug. */
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
/* Data structure allocated via MAP_SHARED, so that writes from the
subprocess are visible. */
struct shared_data
{
/* Number of tracked allocations performed so far. */
volatile unsigned int allocation_count;
/* If this number is reached, one allocation fails. */
volatile unsigned int failing_allocation;
/* The subprocess stores the expected name here. */
char name[100];
};
/* Allocation count in shared mapping. */
static struct shared_data *shared;
/* Returns true if a failure should be injected for this allocation. */
static bool
fail_this_allocation (void)
{
if (shared != NULL)
{
unsigned int count = shared->allocation_count;
shared->allocation_count = count + 1;
return count == shared->failing_allocation;
}
else
return false;
}
/* Failure-injecting wrappers for allocation functions used by glibc. */
void *
malloc (size_t size)
{
if (fail_this_allocation ())
{
errno = ENOMEM;
return NULL;
}
extern __typeof (malloc) __libc_malloc;
return __libc_malloc (size);
}
void *
calloc (size_t a, size_t b)
{
if (fail_this_allocation ())
{
errno = ENOMEM;
return NULL;
}
extern __typeof (calloc) __libc_calloc;
return __libc_calloc (a, b);
}
void *
realloc (void *ptr, size_t size)
{
if (fail_this_allocation ())
{
errno = ENOMEM;
return NULL;
}
extern __typeof (realloc) __libc_realloc;
return __libc_realloc (ptr, size);
}
/* No-op subprocess to verify that support_isolate_in_subprocess does
not perform any heap allocations. */
static void
no_op (void *ignored)
{
}
/* Perform a regcomp call in a subprocess. Used to count its
allocations. */
static void
initialize (void *regexp1)
{
const char *regexp = regexp1;
shared->allocation_count = 0;
regex_t reg;
TEST_COMPARE (regcomp (&reg, regexp, 0), 0);
}
/* Perform regcomp in a subprocess with fault injection. */
static void
test_in_subprocess (void *regexp1)
{
const char *regexp = regexp1;
unsigned int inject_at = shared->failing_allocation;
regex_t reg;
int ret = regcomp (&reg, regexp, 0);
if (ret != 0)
{
TEST_COMPARE (ret, REG_ESPACE);
printf ("info: allocation %u failure results in return value %d,"
" error %s (%d)\n",
inject_at, ret, strerrorname_np (errno), errno);
}
}
static int
do_test (void)
{
char regexp[] = "[:alpha:]";
shared = support_shared_allocate (sizeof (*shared));
/* Disable fault injection. */
shared->failing_allocation = ~0U;
support_isolate_in_subprocess (no_op, NULL);
TEST_COMPARE (shared->allocation_count, 0);
support_isolate_in_subprocess (initialize, regexp);
/* The number of allocations in the successful case, plus some
slack. Once the number of expected allocations is exceeded,
injecting further failures does not make a difference. */
unsigned int maximum_allocation_count = shared->allocation_count;
printf ("info: successful call performs %u allocations\n",
maximum_allocation_count);
maximum_allocation_count += 10;
for (unsigned int inject_at = 0; inject_at <= maximum_allocation_count;
++inject_at)
{
shared->allocation_count = 0;
shared->failing_allocation = inject_at;
support_isolate_in_subprocess (test_in_subprocess, regexp);
}
support_shared_free (shared);
return 0;
}
#include <support/test-driver.c>
+89
View File
@@ -0,0 +1,89 @@
/* Test for wordexp with WRDE_REUSE flag.
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 <wordexp.h>
#include <mcheck.h>
#include <support/check.h>
static int
do_test (void)
{
mtrace ();
{
wordexp_t p = { 0 };
TEST_COMPARE (wordexp ("one", &p, 0), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[0], "one");
TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[0], "two");
wordfree (&p);
}
{
wordexp_t p = { .we_offs = 2 };
TEST_COMPARE (wordexp ("one", &p, 0), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[0], "one");
TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_DOOFFS), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
wordfree (&p);
}
{
wordexp_t p = { 0 };
TEST_COMPARE (wordexp ("one", &p, 0), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[0], "one");
TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_APPEND), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[0], "two");
wordfree (&p);
}
{
wordexp_t p = { .we_offs = 2 };
TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
| WRDE_DOOFFS), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
wordfree (&p);
}
{
wordexp_t p = { .we_offs = 2 };
TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
| WRDE_DOOFFS | WRDE_APPEND), 0);
TEST_COMPARE (p.we_wordc, 1);
TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
wordfree (&p);
}
return 0;
}
#include <support/test-driver.c>
+1 -2
View File
@@ -517,8 +517,7 @@ extern int fchdir (int __fd) __THROW __wur;
an array is allocated with `malloc'; the array is SIZE
bytes long, unless SIZE == 0, in which case it is as
big as necessary. */
extern char *getcwd (char *__buf, size_t __size) __THROW __wur
__attr_access ((__write_only__, 1, 2));
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
#ifdef __USE_GNU
/* Return a malloc'd string containing the current directory name.
+1
View File
@@ -183,6 +183,7 @@ struct test_case_struct
{ 0, NULL, "$var", 0, 0, { NULL, }, IFS },
{ 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS },
{ 0, NULL, "", 0, 0, { NULL, }, IFS },
{ 0, NULL, "${1234567890123456789012}", 0, 0, { NULL, }, IFS },
/* Flags not already covered (testit() has special handling for these) */
{ 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS },
+3 -1
View File
@@ -1399,7 +1399,7 @@ envsubst:
/* Is it a numeric parameter? */
else if (isdigit (env[0]))
{
int n = atoi (env);
unsigned long n = strtoul (env, NULL, 10);
if (n >= __libc_argc)
/* Substitute NULL. */
@@ -2220,7 +2220,9 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
{
/* Minimal implementation of WRDE_REUSE for now */
wordfree (pwordexp);
old_word.we_wordc = 0;
old_word.we_wordv = NULL;
pwordexp->we_wordc = 0;
}
if ((flags & WRDE_APPEND) == 0)
+4
View File
@@ -209,6 +209,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
net_bytes[1], net_bytes[0]);
break;
default:
/* Default network (net is originally zero). */
strcpy (qbuf, "0.0.0.0.in-addr.arpa");
break;
}
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
+6
View File
@@ -46,6 +46,9 @@ handle_code (const struct resolv_response_context *ctx,
{
switch (code)
{
case 0:
send_ptr (b, qname, qclass, qtype, "0.in-addr.arpa");
break;
case 1:
send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
break;
@@ -265,6 +268,9 @@ do_test (void)
"error: TRY_AGAIN\n");
/* Lookup by address, success cases. */
check_reverse (0,
"name: 0.in-addr.arpa\n"
"net: 0x00000000\n");
check_reverse (1,
"name: 1.in-addr.arpa\n"
"net: 0x00000001\n");
+1
View File
@@ -44,6 +44,7 @@ tests := tst-shm tst-timer tst-timer2 \
tst-aio7 tst-aio8 tst-aio9 tst-aio10 \
tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
tst-bz28213 \
tst-timer3 tst-timer4 tst-timer5 \
tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \
tst-shm-cancel
+101
View File
@@ -0,0 +1,101 @@
/* Bug 28213: test for NULL pointer dereference in mq_notify.
Copyright (C) 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 <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <mqueue.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
static mqd_t m = -1;
static const char msg[] = "hello";
static void
check_bz28213_cb (union sigval sv)
{
char buf[sizeof (msg)];
(void) sv;
TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL)
== sizeof (buf));
TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0);
exit (0);
}
static void
check_bz28213 (void)
{
struct sigevent sev;
memset (&sev, '\0', sizeof (sev));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = check_bz28213_cb;
/* Step 1: Register & unregister notifier.
Helper thread should receive NOTIFY_REMOVED notification.
In a vulnerable version of glibc, NULL pointer dereference follows. */
TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0);
/* Step 2: Once again, register notification.
Try to send one message.
Test is considered successful, if the callback does exit (0). */
TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0);
/* Wait... */
pause ();
}
static int
do_test (void)
{
static const char m_name[] = "/bz28213_queue";
struct mq_attr m_attr;
memset (&m_attr, '\0', sizeof (m_attr));
m_attr.mq_maxmsg = 1;
m_attr.mq_msgsize = sizeof (msg);
m = mq_open (m_name,
O_RDWR | O_CREAT | O_EXCL,
0600,
&m_attr);
if (m < 0)
{
if (errno == ENOSYS)
FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n");
FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n");
}
TEST_VERIFY_EXIT (mq_unlink (m_name) == 0);
check_bz28213 ();
return 0;
}
#include <support/test-driver.c>
+5 -1
View File
@@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \
routines := accept bind connect getpeername getsockname getsockopt \
listen recv recvfrom recvmsg send sendmsg sendto \
setsockopt shutdown socket socketpair isfdtype opensock \
sockatmark accept4 recvmmsg sendmmsg
sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set
tests := tst-accept4
tests-internal := \
tst-sockaddr_un_set \
# tests-internal
aux := sa_len
include ../Rules
+16 -44
View File
@@ -1,4 +1,5 @@
/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
/* Create socket with an unspecified address family for use with ioctl.
Copyright (C) 1999-2021 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
@@ -15,56 +16,27 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <libc-lock.h>
/* Return a socket of any type. The socket can be used in subsequent
ioctl calls to talk to the kernel. */
int
__opensock (void)
{
/* Cache the last AF that worked, to avoid many redundant calls to
socket(). */
static int sock_af = -1;
int fd = -1;
__libc_lock_define_initialized (static, lock);
/* SOCK_DGRAM is supported by all address families. */
int type = SOCK_DGRAM | SOCK_CLOEXEC;
int fd;
if (sock_af != -1)
{
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd != -1)
return fd;
}
__libc_lock_lock (lock);
if (sock_af != -1)
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd == -1)
{
#ifdef AF_INET
fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
#endif
#ifdef AF_INET6
if (fd < 0)
fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
#endif
#ifdef AF_IPX
if (fd < 0)
fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
#endif
#ifdef AF_AX25
if (fd < 0)
fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
#endif
#ifdef AF_APPLETALK
if (fd < 0)
fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
#endif
}
__libc_lock_unlock (lock);
fd = __socket (AF_UNIX, type, 0);
if (fd >= 0)
return fd;
fd = __socket (AF_INET, type, 0);
if (fd >= 0)
return fd;
fd = __socket (AF_INET6, type, 0);
if (fd >= 0)
return fd;
__set_errno (ENOENT);
return fd;
}
+41
View File
@@ -0,0 +1,41 @@
/* Set the sun_path member of struct sockaddr_un.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
int
__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
{
size_t name_length = strlen (pathname);
/* The kernel supports names of exactly sizeof (addr->sun_path)
bytes, without a null terminator, but userspace does not; see the
SUN_LEN macro. */
if (name_length >= sizeof (addr->sun_path))
{
__set_errno (EINVAL); /* Error code used by the kernel. */
return -1;
}
addr->sun_family = AF_UNIX;
memcpy (addr->sun_path, pathname, name_length + 1);
return 0;
}
+62
View File
@@ -0,0 +1,62 @@
/* Test the __sockaddr_un_set function.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Re-compile the function because the version in libc is not
exported. */
#include "sockaddr_un_set.c"
#include <support/check.h>
static int
do_test (void)
{
struct sockaddr_un sun;
memset (&sun, 0xcc, sizeof (sun));
__sockaddr_un_set (&sun, "");
TEST_COMPARE (sun.sun_family, AF_UNIX);
TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0);
memset (&sun, 0xcc, sizeof (sun));
TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0);
TEST_COMPARE_STRING (sun.sun_path, "/example");
{
char pathname[108]; /* Length of sun_path (ABI constant). */
memset (pathname, 'x', sizeof (pathname));
pathname[sizeof (pathname) - 1] = '\0';
memset (&sun, 0xcc, sizeof (sun));
TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0);
TEST_COMPARE (sun.sun_family, AF_UNIX);
TEST_COMPARE_STRING (sun.sun_path, pathname);
}
{
char pathname[109];
memset (pathname, 'x', sizeof (pathname));
pathname[sizeof (pathname) - 1] = '\0';
memset (&sun, 0xcc, sizeof (sun));
errno = 0;
TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1);
TEST_COMPARE (errno, EINVAL);
}
return 0;
}
#include <support/test-driver.c>
+2 -1
View File
@@ -86,7 +86,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tst-makecontext-align test-bz22786 tst-strtod-nan-sign \
tst-swapcontext1 tst-setcontext4 tst-setcontext5 \
tst-setcontext6 tst-setcontext7 tst-setcontext8 \
tst-setcontext9 tst-bz20544 tst-canon-bz26341
tst-setcontext9 tst-bz20544 tst-canon-bz26341 \
tst-realpath-toolong
tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
tst-tls-atexit tst-tls-atexit-nodelete
+10 -2
View File
@@ -400,8 +400,16 @@ realpath_stk (const char *name, char *resolved,
error:
*dest++ = '\0';
if (resolved != NULL && dest - rname <= get_path_max ())
rname = strcpy (resolved, rname);
if (resolved != NULL)
{
if (dest - rname <= get_path_max ())
rname = strcpy (resolved, rname);
else if (!failed)
{
failed = true;
__set_errno (ENAMETOOLONG);
}
}
error_nomem:
scratch_buffer_free (&extra_buffer);
+53
View File
@@ -0,0 +1,53 @@
/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds
NAME_MAX.
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/>. */
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <support/check.h>
#include <support/temp_file.h>
#include <sys/types.h>
#include <sys/stat.h>
#define BASENAME "tst-realpath-toolong."
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
int
do_test (void)
{
char *base = support_create_and_chdir_toolong_temp_directory (BASENAME);
char buf[PATH_MAX + 1];
const char *res = realpath (".", buf);
/* canonicalize.c states that if the real path is >= PATH_MAX, then
realpath returns NULL and sets ENAMETOOLONG. */
TEST_VERIFY (res == NULL);
TEST_VERIFY (errno == ENAMETOOLONG);
free (base);
return 0;
}
#include <support/test-driver.c>
+18 -181
View File
@@ -30,167 +30,12 @@
#include <sys/wait.h>
#include <unistd.h>
#include <support/check.h>
#include <support/support.h>
#include <support/capture_subprocess.h>
#include <support/test-driver.h>
static char MAGIC_ARGUMENT[] = "run-actual-test";
#define MAGIC_STATUS 19
/* Return a GID which is not our current GID, but is present in the
supplementary group list. */
static gid_t
choose_gid (void)
{
int count = getgroups (0, NULL);
if (count < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t *groups;
groups = xcalloc (count, sizeof (*groups));
int ret = getgroups (count, groups);
if (ret < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t current = getgid ();
gid_t not_current = 0;
for (int i = 0; i < ret; ++i)
{
if (groups[i] != current)
{
not_current = groups[i];
break;
}
}
free (groups);
return not_current;
}
/* Copies the executable into a restricted directory, so that we can
safely make it SGID with the TARGET group ID. Then runs the
executable. */
static int
run_executable_sgid (gid_t target)
{
char *dirname = xasprintf ("%s/secure-getenv.%jd",
test_dir, (intmax_t) getpid ());
char *execname = xasprintf ("%s/bin", dirname);
int infd = -1;
int outfd = -1;
int ret = -1;
if (mkdir (dirname, 0700) < 0)
{
printf ("mkdir: %m\n");
goto err;
}
infd = open ("/proc/self/exe", O_RDONLY);
if (infd < 0)
{
printf ("open (/proc/self/exe): %m\n");
goto err;
}
outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
if (outfd < 0)
{
printf ("open (%s): %m\n", execname);
goto err;
}
char buf[4096];
for (;;)
{
ssize_t rdcount = read (infd, buf, sizeof (buf));
if (rdcount < 0)
{
printf ("read: %m\n");
goto err;
}
if (rdcount == 0)
break;
char *p = buf;
char *end = buf + rdcount;
while (p != end)
{
ssize_t wrcount = write (outfd, buf, end - p);
if (wrcount == 0)
errno = ENOSPC;
if (wrcount <= 0)
{
printf ("write: %m\n");
goto err;
}
p += wrcount;
}
}
if (fchown (outfd, getuid (), target) < 0)
{
printf ("fchown (%s): %m\n", execname);
goto err;
}
if (fchmod (outfd, 02750) < 0)
{
printf ("fchmod (%s): %m\n", execname);
goto err;
}
if (close (outfd) < 0)
{
printf ("close (outfd): %m\n");
goto err;
}
if (close (infd) < 0)
{
printf ("close (infd): %m\n");
goto err;
}
int kid = fork ();
if (kid < 0)
{
printf ("fork: %m\n");
goto err;
}
if (kid == 0)
{
/* Child process. */
char *args[] = { execname, MAGIC_ARGUMENT, NULL };
execve (execname, args, environ);
printf ("execve (%s): %m\n", execname);
_exit (1);
}
int status;
if (waitpid (kid, &status, 0) < 0)
{
printf ("waitpid: %m\n");
goto err;
}
if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS)
{
printf ("Unexpected exit status %d from child process\n",
status);
goto err;
}
ret = 0;
err:
if (outfd >= 0)
close (outfd);
if (infd >= 0)
close (infd);
if (execname)
{
unlink (execname);
free (execname);
}
if (dirname)
{
rmdir (dirname);
free (dirname);
}
return ret;
}
static int
do_test (void)
@@ -212,15 +57,15 @@ do_test (void)
exit (1);
}
gid_t target = choose_gid ();
if (target == 0)
{
fprintf (stderr,
"Could not find a suitable GID for user %jd, skipping test\n",
(intmax_t) getuid ());
exit (0);
}
return run_executable_sgid (target);
int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT);
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status))
FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
return 0;
}
static void
@@ -229,23 +74,15 @@ 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. */
fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
exit (MAGIC_STATUS);
}
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
if (getenv ("PATH") == NULL)
{
printf ("PATH variable not present\n");
exit (3);
}
FAIL_EXIT (3, "PATH variable not present\n");
if (secure_getenv ("PATH") != NULL)
{
printf ("PATH variable not filtered out\n");
exit (4);
}
exit (MAGIC_STATUS);
FAIL_EXIT (4, "PATH variable not filtered out\n");
exit (EXIT_SUCCESS);
}
}
+15 -11
View File
@@ -22,24 +22,28 @@
# define RAWMEMCHR __rawmemchr
#endif
/* The pragmata should be nested inside RAWMEMCHR below, but that
triggers GCC PR 98512. */
DIAG_PUSH_NEEDS_COMMENT;
#if __GNUC_PREREQ (7, 0)
/* GCC 8 warns about the size passed to memchr being larger than
PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-overflow=");
#endif
#if __GNUC_PREREQ (11, 0)
/* Likewise GCC 11, with a different warning option. */
DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
#endif
/* Find the first occurrence of C in S. */
void *
RAWMEMCHR (const void *s, int c)
{
DIAG_PUSH_NEEDS_COMMENT;
#if __GNUC_PREREQ (7, 0)
/* GCC 8 warns about the size passed to memchr being larger than
PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-overflow=");
#endif
#if __GNUC_PREREQ (11, 0)
/* Likewise GCC 11, with a different warning option. */
DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
#endif
if (c != '\0')
return memchr (s, c, (size_t)-1);
DIAG_POP_NEEDS_COMMENT;
return (char *)s + strlen (s);
}
libc_hidden_def (__rawmemchr)
weak_alias (__rawmemchr, rawmemchr)
DIAG_POP_NEEDS_COMMENT;

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