Compare commits

...

144 commits

Author SHA1 Message Date
Samuel Thibault
4e68a5ca5d htl: Make __pthread_create_internal directly call __pthread_sigmask
__pthread_sigmask will already know to pass our current ss to
__sigthreadmask.
2025-03-06 02:28:35 +01:00
Samuel Thibault
81c4ec1ca8 htl: Make __pthread_sigmask directly call __sigthreadmask
If no thread was created yet, __pthread_sigstate will not find our ss
because self->kernel_thread is still nul, and then change the global
sigstate instead of our sigstate! We can directly call __sigthreadmask and
skip the (bogus) lookup step.
2025-03-06 02:28:35 +01:00
Samuel Thibault
7a185eb9e9 hurd: Consolidate signal mask change
__pthread_sigstate and __sigprocmask were already the same, except for
clear_pending.
2025-03-06 02:28:35 +01:00
H.J. Lu
596130591a static-pie: Skip the empty PT_LOAD segment at offset 0 [BZ #32763]
As shown in

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

linker may generate an empty PT_LOAD segments at offset 0:

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

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

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

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

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2025-03-06 07:27:03 +08:00
Ronan Pigott
50351e0570 sysdeps: linux: Add BTRFS_SUPER_MAGIC to pathconf
btrfs has a 65535 maximum link count. Include this value in pathconf to
give the real max link count for this filesystem.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-03-05 15:28:31 -03:00
Adhemerval Zanella
6cb703b81d linux: Prefix AT_HWCAP with 0x on LD_SHOW_AUXV
Suggested-by: Stefan Liebler <stli@linux.ibm.com>
Reviewed-by: Stefan Liebler <stli@linux.ibm.com>
2025-03-05 11:22:09 -03:00
Adhemerval Zanella
1d60b9dfda Remove dl-procinfo.h
powerpc was the only architecture with arch-specific hooks for
LD_SHOW_AUXV, and with the information moved to ld diagnostics there
is no need to keep the _dl_procinfo hook.

Checked with a build for all affected ABIs.

Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
2025-03-05 11:22:09 -03:00
Adhemerval Zanella
2fd580ea46 powerpc: Remove unused dl-procinfo.h
The _dl_string_platform is moved to hwcapinfo.h, since it is only used
by hwcapinfo.c and test-get_hwcap internal test.

Checked on powerpc64le-linux-gnu.

Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
2025-03-05 11:22:09 -03:00
Adhemerval Zanella
a768993c10 powerpc: Move cache geometry information to ld diagnostics
From LD_SHOW_AUXV output.

Checked on powerpc64le-linux-gnu.

Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
2025-03-05 11:22:09 -03:00
Adhemerval Zanella
8a995670a8 powerpc: Move AT_HWCAP descriptions to ld diagnostics
The ld.so diagnostics already prints AT_HWCAP values, but only in
hexadecimal.  To avoid duplicating the strings, consolidate the
hwcap_names from cpu-features.h on a new file, dl-hwcap-info.h
(and it also improves the hwcap string description with more
values).

For future AT_HWCAP3/AT_HWCAP4 extensions, it is just a matter
to add them on dl-hwcap-info.c so both ld diagnostics and
tunable filtering will parse the new values.

Checked on powerpc64le-linux-gnu.

Reviewed-by: Peter Bergner <bergner@linux.ibm.com>
2025-03-05 11:22:09 -03:00
Wilco Dijkstra
3a9fb97caf benchtests: Add random strlen benchmark
Add a new randomized strlen test similar to bench-random-memcpy.  Instead of
repeating the same call to strlen over and over again, it times a large number
of different strings.  The distribution of the string length and alignment is
based on SPEC2017.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-03-05 13:30:50 +00:00
Wilco Dijkstra
dac7ea4a6f benchtests: Improve large memcpy/memset benchmarks
Adjust sizes between 64KB and 16MB and iterations based on length.
Remove incorrect uses of alloc_bufs since we're not interested in measuring
Linux clear_page time.  Use getpagesize() - 1 instead of 4095 when
aligning within a page.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-03-05 13:29:48 +00:00
Siddhesh Poyarekar
226476e322 manual: Explain sched_yield semantics with different schedulers
The manual entry for sched_yield mentions that the function call could
be a nop if there are no other tasks with the same absolute priority.
Expand the explanation to include example schedulers on Linux so that
it's clear that sched_yield may not always result in a different task
being scheduled.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Joseph Myers <josmyers@redhat.com>
2025-03-04 19:36:40 -05:00
Sam James
a2bd5008a9
Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack is used [PR32717]
When GNU Binutils is configured with --enable-error-execstack=yes, a handful
of our tests which rely on -Wl,-z,execstack fail. Pass --Wl,--no-error-execstack
to override the behaviour and get a warning instead.

Bug: https://sourceware.org/PR32717
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-03-04 20:08:50 +00:00
Ben Kallus
4cf2d86936 malloc: Add integrity check to largebin nextsizes
If attacker overwrites the bk_nextsize link in the first chunk of a
largebin that later has a smaller chunk inserted into it, malloc will
write a heap pointer into an attacker-controlled address [0].

This patch adds an integrity check to mitigate this attack.

[0]: https://github.com/shellphish/how2heap/blob/master/glibc_2.39/large_bin_attack.c

Signed-off-by: Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
Reviewed-by: DJ Delorie <dj@redhat.com>
2025-03-03 18:31:27 -05:00
Samuel Zeter
8c6fee9f7f libio: Clean up fputc/putc comments
Remove duplicate comments in stdio.h

Signed-off-by: Samuel Zeter <samuelzeter@gmail.com>
Reviewed-by: Arjun Shankar <arjun@redhat.com>
2025-03-03 16:12:03 +01:00
Samuel Thibault
ccdb68e829 htl: move pthread_once into libc 2025-03-02 15:37:33 +01:00
Wilco Dijkstra
e5893e6349 Remove unused dl-procinfo.h
Remove unused _dl_hwcap_string defines.  As a result many dl-procinfo.h headers
can be removed.  This also removes target specific _dl_procinfo implementations
which only printed HWCAP strings using dl_hwcap_string.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-28 16:55:18 +00:00
Xi Ruoyao
c0f380c465 LoongArch: Optimize f{max,min}imum_mag_num{,f}
Following the logic of the previous commits.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
2025-02-28 11:44:19 +08:00
Xi Ruoyao
efd13567f7 LoongArch: Optimize f{max,min}imum_num{,f}
Following the logic of the previous commits.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
2025-02-28 11:44:19 +08:00
Xi Ruoyao
ee4ee1cb02 LoongArch: Optimize f{max,min}imum_mag{,f}
Following the logic of the previous commit.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
2025-02-28 11:44:19 +08:00
Xi Ruoyao
0195552e15 LoongArch: Optimize f{max,min}imum{,f}
The code now looks like:

	fclass.s        $fa2, $fa0
	movfr2gr.s      $t0, $fa2
	slli.w          $t0, $t0, 0x0
	fclass.s        $fa2, $fa1
	movfr2gr.s      $t1, $fa2
	or              $t0, $t0, $t1
	andi            $t0, $t0, 0x3
	bnez            $t0, 1f
	fmin.s          $fa0, $fa0, $fa1
	ret
	1:
	fmul.s		$fa0, $fa0, $fa1
	ret

This looks really bad, with expensive movfr2gr instructions, redundant
sign-extensions and masking (arguably it's a compiler
missed-optimzation), and a branch.  Rewrite it with inline assembly:

	fcmp.cor.s      $fcc0, $fa0, $fa0
	fcmp.cor.s      $fcc1, $fa1, $fa1
	fsel            $fa2, $fa0, $fa1, $fcc0
	fsel            $fa0, $fa1, $fa0, $fcc1
	fmax.s          $fa0, $fa2, $fa0
	ret

Note that we cannot make it more readable with
"double a = __builtin_isnanf (x) ? y : x" because this C statement only
happens to produce what we want with https://gcc.gnu.org/PR66462, if
this bug is fixed in the future the generated code may change.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
2025-02-28 11:44:19 +08:00
Wilco Dijkstra
0f044be1da AArch64: Use prefer_sve_ifuncs for SVE memset
Use prefer_sve_ifuncs for SVE memset just like memcpy.

Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
2025-02-27 16:51:57 +00:00
Sergei Zimmerman
9e51ae3cd0 sysdeps/ieee754: Fix remainder sign of zero for FE_DOWNWARD (BZ #32711)
Single-precision remainderf() and quad-precision remainderl()
implementation derived from Sun is affected by an issue when the result
is +-0. IEEE754 requires that if remainder(x, y) = 0, its sign shall be
that of x regardless of the rounding direction.

The implementation seems to have assumed that x - x = +0 in all
rounding modes, which is not the case. When rounding direction is
roundTowardNegative the sign of an exact zero sum (or difference) is −0.

Regression tests that triggered this erroneous behavior are added to
math/libm-test-remainder.inc.

Tested for cross riscv64 and powerpc.

Original fix by: Bruce Evans <bde@FreeBSD.org> in FreeBSD's
a2ddfa5ea726c56dbf825763ad371c261b89b7c7.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-26 17:17:25 -03:00
John David Anglin
2fe5e2af09 math: Add optimization barrier to ensure a1 + u.d is not reused [BZ #30664]
A number of fma tests started to fail on hppa when gcc was changed to
use Ranger rather than EVRP.  Eventually I found that the value of
a1 + u.d in this is block of code was being computed in FE_TOWARDZERO
mode and not the original rounding mode:

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

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

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

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2025-02-25 15:57:53 -05:00
Yangyu Chen
3fd2ff7685 RISC-V: Fix IFUNC resolver cannot access gp pointer
In some cases, an IFUNC resolver may need to access the gp pointer to
access global variables. Such an object may have l_relocated == 0 at
this time. In this case, an IFUNC resolver will fail to access a global
variable and cause a SIGSEGV.

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

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

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

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

Co-authored-by: Vivian Wang <dramforever@live.com>
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
2025-02-25 13:08:53 +01:00
Wilco Dijkstra
935563754b AArch64: Remove LP64 and ILP32 ifdefs
Remove LP64 and ILP32 ifdefs.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:20:29 +00:00
Wilco Dijkstra
4c11379106 AArch64: Simplify lrint
Simplify lrint.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:20:03 +00:00
Wilco Dijkstra
0a021727bc AArch64: Remove AARCH64_R macro
Remove AArch64_R relocation macro.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:19:19 +00:00
Wilco Dijkstra
eb7ac024d9 AArch64: Cleanup pointer mangling
Cleanup pointer mangling.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:17:57 +00:00
Wilco Dijkstra
19860fd42e AArch64: Remove PTR_REG defines
Remove PTR_REG defines.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:16:55 +00:00
Wilco Dijkstra
ce2f26a22e AArch64: Remove PTR_ARG/SIZE_ARG defines
This series removes various ILP32 defines that are now
no longer needed.

Remove PTR_ARG/SIZE_ARG.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:15:15 +00:00
Wilco Dijkstra
be0cfd848d stdlib: Add single-threaded fast path to rand()
Improve performance of rand() and __random() by adding a single-threaded
fast path.  Bench-random-lock shows about 5x speedup on Neoverse V1.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-24 14:13:43 +00:00
Stefan Liebler
4734d0f8ad Increase the amount of data tested in stdio-common/tst-fwrite-pipe.c
The number of iterations and the length of the string are not high
enough on some systems causing the test to return false-positives.

Testcase stdio-common/tst-fwrite-bz29459.c was fixed in the same way in
1b6f868625
(Increase the amount of data tested in stdio-common/tst-fwrite-bz29459.c, 2025-02-14)

Testcases stdio-common/tst-fwrite-bz29459.c and stdio-common/tst-fwrite-pipe.c
were introcued in 596a61cf6b
(libio: Start to return errors when flushing fwrite's buffer [BZ #29459], 2025-01-28)
2025-02-24 14:45:55 +01:00
Frédéric Bérat
8a46bf41e5 posix: Rewrite cpuset tests
Rewriting the cpuset macros test to cover more use cases and port the
tests to the new test infrastructure.

The use cases include bad actor access attempts, before and after the
CPU set structure.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@redhat.com>
2025-02-24 14:19:51 +01:00
Frédéric Bérat
fa53723cdb support: Add support_next_to_fault_before support function
Refactor the support_next_to_fault and add the
support_next_to_fault_before method returns a buffer with a protected
page before it, to be able to test buffer underflow accesses.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@redhat.com>
2025-02-24 14:19:36 +01:00
koraynilay
29803ed3ce math: Fix unknown type name '__float128' for clang 3.4 to 3.8.1 (bug 32694)
When compiling a program that includes <bits/floatn.h> using a clang version
between 3.4 (included) and 3.8.1 (included), clang will fail with `unknown type
name '__float128'; did you mean '__cfloat128'?`. This changes fixes the clang
prerequirements macro call in floatn.h to check for clang 3.9 instead of 3.4,
since support for __float128 was actually enabled in 3.9 by:

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

    Enable support for __float128 in Clang

This fixes bug 32694.

Signed-off-by: koraynilay <koray.fra@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2025-02-23 11:47:11 +08:00
Michael Jeanson
689a62a421 nptl: clear the whole rseq area before registration
Due to the extensible nature of the rseq area we can't explictly
initialize fields that are not part of the ABI yet. It was agreed with
upstream that all new fields will be documented as zero initialized by
userspace. Future kernels configured with CONFIG_DEBUG_RSEQ will
validate the content of all fields during registration.

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

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
2025-02-21 22:21:25 +00:00
Yury Khrustalev
41f6684557 aarch64: Add GCS test with signal handler
Test that when we return from a function that enabled GCS at runtime
we get SIGSEGV. Also test that ucontext contains GCS block with the
GCS pointer.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-21 16:23:44 +00:00
Yury Khrustalev
15afd01e80 aarch64: Add GCS tests for dlopen
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-21 16:10:44 +00:00
Yury Khrustalev
57ee1deb1f aarch64: Add GCS tests for transitive dependencies
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-21 16:09:06 +00:00
Yury Khrustalev
82decb59bc aarch64: Add tests for Guarded Control Stack
These tests validate that GCS tunable works as expected depending
on the GCS markings in the test binaries.

Tests validate both static and dynamically linked binaries.

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

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

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-21 16:06:44 +00:00
Carlos O'Donell
6d24313e4a manual: Mark setlogmask as AS-unsafe and AC-unsafe.
This fixes the check-safety.sh failure with commit
ad9c4c5361, and correctly marks
the function AS-unsafe and AC-unsafe due to the use of the
non-recursive lock.

Tested on x86_64 without regressions.
Reviewed-by: Frédéric Bérat <fberat@redhat.com>
2025-02-20 11:55:21 -05:00
Wilco Dijkstra
163b1bbb76 AArch64: Add SVE memset
Add SVE memset based on the generic memset with predicated load for sizes < 16.
Unaligned memsets of 128-1024 are improved by ~20% on average by using aligned
stores for the last 64 bytes.  Performance of random memset benchmark improves
by ~2% on Neoverse V1.

Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
2025-02-20 15:31:50 +00:00
H.J. Lu
5a4573be6f x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL compiler [BZ #32723]
Intel compiler always defines __INTEL_LLVM_COMPILER.  When SYCL is
enabled by -fsycl, it also defines SYCL_LANGUAGE_VERSION.  Since Intel
SYCL compiler doesn't support _Float128:

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

define __HAVE_FLOAT128 to 0 for Intel SYCL compiler.

This fixes BZ #32723.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2025-02-20 08:42:37 +08:00
Carlos O'Donell
ad9c4c5361 manual: Document setlogmask as MT-safe.
setlogmask(3) was made MT-safe in glibc-2.33 with the fix for
bug 26100.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2025-02-19 16:22:54 -05:00
Adhemerval Zanella
0242c9f9e6 math: Consolidate acosf and asinf internal tables
The libm size improvement built with gcc-14, "--enable-stack-protector=strong
--enable-bind-now=yes --enable-fortify-source=2":

Before:

 582292     844      12  583148   8e5ec aarch64-linux-gnu/math/libm.so
 975133    1076      12  976221   ee55d x86_64-linux-gnu/math/libm.so
1203586    5608     368 1209562  1274da powerpc64le-linux-gnu/math/libm.so

After:

 581972     844      12  582828   8e4ac aarch64-linux-gnu/math/libm.so
 974941    1076      12  976029   ee49d x86_64-linux-gnu/math/libm.so
1203394    5608     368 1209370  12741a powerpc64le-linux-gnu/math/libm.so
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
2025-02-17 10:09:09 -03:00
Adhemerval Zanella
1faccf388a math: Consolidate acospif and asinpif internal tables
The libm size improvement built with gcc-14, "--enable-stack-protector=strong
--enable-bind-now=yes --enable-fortify-source=2":

Before:

   text    data     bss     dec     hex filename
 583444     844      12  584300   8ea6c aarch64-linux-gnu/math/libm.so
 976349    1076      12  977437   eea1d x86_64-linux-gnu/math/libm.so
1204738    5608     368 1210714  12795a powerpc64le-linux-gnu/math/libm.so

After:

 582292     844      12  583148   8e5ec aarch64-linux-gnu/math/libm.so
 975133    1076      12  976221   ee55d x86_64-linux-gnu/math/libm.so
1203586    5608     368 1209562  1274da powerpc64le-linux-gnu/math/libm.so
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
2025-02-17 10:09:09 -03:00
Adhemerval Zanella
246e52574d math: Consolidate cospif and sinpif internal tables
The libm size improvement built with gcc-14, "--enable-stack-protector=strong
--enable-bind-now=yes --enable-fortify-source=2":

Before:

   text    data     bss     dec     hex filename
 584500     844      12  585356   8ee8c aarch64-linux-gnu/math/libm.so
 977341    1076      12  978429   eedfd x86_64-linux-gnu/math/libm.so
1205762    5608     368 1211738  127d5a powerpc64le-linux-gnu/math/libm.so

After:

   text    data     bss     dec     hex filename
 583444     844      12  584300   8ea6c aarch64-linux-gnu/math/libm.so
 976349    1076      12  977437   eea1d x86_64-linux-gnu/math/libm.so
1204738    5608     368 1210714  12795a powerpc64le-linux-gnu/math/libm.so
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
2025-02-17 10:09:09 -03:00
gfleury
4afbc1aa2e htl: don't export __pthread_default_rwlockattr anymore.
since now all symbloy that use it are in libc
Message-ID: <20250216145434.7089-11-gfleury@disroot.org>
2025-02-16 23:43:04 +01:00
gfleury
6f6732c1c4 htl: move pthread_rwlock_init into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-10-gfleury@disroot.org>
2025-02-16 23:43:03 +01:00
gfleury
d3ef1b56aa htl: move pthread_rwlock_destroy into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-9-gfleury@disroot.org>
2025-02-16 23:42:38 +01:00
gfleury
25650ef6b9 htl: move pthread_rwlock_{rdlock, timedrdlock, timedwrlock, wrlock, clockrdlock, clockwrlock} into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-8-gfleury@disroot.org>
2025-02-16 23:08:54 +01:00
gfleury
119798a7b1 htl: move pthread_rwlock_unlock into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-7-gfleury@disroot.org>
2025-02-16 23:08:54 +01:00
gfleury
18accc19b9 htl: move pthread_rwlock_tryrdlock, pthread_rwlock_trywrlock into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-6-gfleury@disroot.org>
2025-02-16 22:59:34 +01:00
gfleury
4b25413df5 htl: move pthread_rwlockattr_getpshared, pthread_rwlockattr_setpshared into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-5-gfleury@disroot.org>
2025-02-16 22:59:25 +01:00
gfleury
cd2d31ed58 htl: move pthread_rwlockattr_destroy into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-4-gfleury@disroot.org>
2025-02-16 22:59:16 +01:00
gfleury
e618b671cd htl: move pthread_rwlockattr_init into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-3-gfleury@disroot.org>
2025-02-16 22:59:07 +01:00
gfleury
8f842ce13e htl: move __pthread_default_rwlockattr into libc.
Signed-off-by: gfleury <gfleury@disroot.org>
Message-ID: <20250216145434.7089-2-gfleury@disroot.org>
2025-02-16 22:59:00 +01:00
Aurelien Jarno
60f2d6be65 Fix tst-aarch64-pkey to handle ENOSPC as not supported
The syscall pkey_alloc can return ENOSPC to indicate either that all
keys are in use or that the system runs in a mode in which memory
protection keys are disabled. In such case the test should not fail and
just return unsupported.

This matches the behaviour of the generic tst-pkey.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
2025-02-15 11:08:43 +01:00
Tulio Magno Quites Machado Filho
1b6f868625 Increase the amount of data tested in stdio-common/tst-fwrite-bz29459.c
The number of iterations and the length of the string are not high
enough on some systems causing the test to return false-positives.

Fixes: 596a61cf6b (libio: Start to return errors when flushing fwrite's buffer [BZ #29459], 2025-01-28)
Reported-by: Florian Weimer <fweimer@redhat.com>
2025-02-14 15:46:38 -03:00
Florian Weimer
aa3d7bd529 elf: Keep using minimal malloc after early DTV resize (bug 32412)
If an auditor loads many TLS-using modules during startup, it is
possible to trigger DTV resizing.  Previously, the DTV was marked
as allocated by the main malloc afterwards, even if the minimal
malloc was still in use.  With this change, _dl_resize_dtv marks
the resized DTV as allocated with the minimal malloc.

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

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-13 21:56:52 +01:00
Tulio Magno Quites Machado Filho
88f7ef881d libio: Initialize _total_written for all kinds of streams
Move the initialization code to a general place instead of keeping it
specific to file-backed streams.

Fixes: 596a61cf6b (libio: Start to return errors when flushing fwrite's buffer [BZ #29459], 2025-01-28)
Reported-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Arjun Shankar <arjun@redhat.com>
2025-02-13 16:34:54 -03:00
Ben Kallus
d10176c0ff malloc: Add size check when moving fastbin->tcache
By overwriting a forward link in a fastbin chunk that is subsequently
moved into the tcache, it's possible to get malloc to return an
arbitrary address [0].

When a chunk is fetched from a fastbin, its size is checked against the
expected chunk size for that fastbin (see malloc.c:3991). This patch
adds a similar check for chunks being moved from a fastbin to tcache,
which renders obsolete the exploitation technique described above.

Now updated to use __glibc_unlikely instead of __builtin_expect, as
requested.

[0]: https://github.com/shellphish/how2heap/blob/master/glibc_2.39/fastbin_reverse_into_tcache.c

Signed-off-by: Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-13 16:31:28 -03:00
Tobias Stoeckmann
6a3cb6b1bd nss: Improve network number parsers (bz 32573, 32575)
Make sure that numbers never overflow uint32_t in inet_network to
properly validate octets encountered in IPv4 addresses.

Avoid malloca in NSS networks file code because /etc/networks lines
can be arbitrarily long. Instead of handcrafting the input for
inet_network by adding ".0" octets if they are missing, just left shift
the result. Also, do not accept invalid entries, but ignore the line
instead.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-02-13 16:31:28 -03:00
Carlos O'Donell
991febc2f4 nptl: Remove unused __g_refs comment.
In the block comment for __pthread_cond_wait_common we mention
__g_refs, but the implementation no longer uses group references.
2025-02-13 14:25:25 -05:00
Siddhesh Poyarekar
a30374e4ce advisories: Fix up GLIBC-SA-2025-0001
Add ref for the test case as well as backports.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2025-02-13 14:09:44 -05:00
Yat Long Poon
95e807209b AArch64: Improve codegen for SVE powf
Improve memory access with indexed/unpredicated instructions.
Eliminate register spills.  Speedup on Neoverse V1: 3%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-02-13 18:16:54 +00:00
Yat Long Poon
0b195651db AArch64: Improve codegen for SVE pow
Move constants to struct.  Improve memory access with indexed/unpredicated
instructions.  Eliminate register spills.  Speedup on Neoverse V1: 24%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-02-13 18:16:54 +00:00
Yat Long Poon
f5ff34cb3c AArch64: Improve codegen for SVE erfcf
Reduce number of MOV/MOVPRFXs and use unpredicated FMUL.
Replace MUL with LSL.  Speedup on Neoverse V1: 6%.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-02-13 18:16:54 +00:00
Luna Lamb
c0ff447edf Aarch64: Improve codegen in SVE exp and users, and update expf_inline
Use unpredicted muls, and improve memory access.
7%, 3% and 1% improvement in throughput microbenchmark on Neoverse V1,
for exp, exp2 and cosh respectively.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-02-13 18:16:54 +00:00
Luna Lamb
8f0e7fe61e Aarch64: Improve codegen in SVE asinh
Use unpredicated muls, use lanewise mla's and improve memory access.
1% regression in throughput microbenchmark on Neoverse V1.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-02-13 18:16:54 +00:00
Wilco Dijkstra
5afaf99edb math: Improve layout of exp/exp10 data
GCC aligns global data to 16 bytes if their size is >= 16 bytes.  This patch
changes the exp_data struct slightly so that the fields are better aligned
and without gaps.  As a result on targets that support them, more load-pair
instructions are used in exp.  Exp10 is improved by moving invlog10_2N later
so that neglog10_2hiN and neglog10_2loN can be loaded using load-pair.

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

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-13 18:16:54 +00:00
Siddhesh Poyarekar
cdb9ba8419 assert: Add test for CVE-2025-0395
Use the __progname symbol to override the program name to induce the
failure that CVE-2025-0395 describes.

This is related to BZ #32582

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-02-13 12:33:27 -05:00
Adhemerval Zanella
b81252c4b9 math: Consolidate coshf and sinhf internal tables
The libm size improvement built with "--enable-stack-protector=strong
--enable-bind-now=yes --enable-fortify-source=2":

Before:

   text    data     bss     dec     hex filename
 585192     860      12  586064   8f150 aarch64-linux-gnu/math/libm.so
 960775    1068      12  961855   ead3f x86_64-linux-gnu/math/libm.so
1189174    5544     368 1195086  123c4e powerpc64le-linux-gnu/math/libm.so

After:

   text    data     bss     dec     hex filename
 584952     860      12  585824   8f060 aarch64-linux-gnu/math/libm.so
 960615    1068      12  961695   eac9f x86_64-linux-gnu/math/libm.so
1189078    5544     368 1194990  123bee powerpc64le-linux-gnu/math/libm.so

The are small code changes for x86_64 and powerpc64le, which do not
affect performance; but on aarch64 with gcc-14 I see a slight better
code generation due the usage of ldq for floating point constant loading.
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
994007ff29 math: Consolidate acoshf and asinhf internal tables
The libm size improvement built with "--enable-stack-protector=strong
--enable-bind-now=yes --enable-fortify-source=2":

Before:

   text    data     bss     dec     hex filename
 587304     860      12  588176   8f990 aarch64-linux-gnu-master/math/libm.so
 962855    1068      12  963935   eb55f x86_64-linux-gnu-master/math/libm.so
1191222    5544     368 1197134  12444e powerpc64le-linux-gnu-master/math/libm.so

After:

   text    data     bss     dec     hex filename
 585192     860      12  586064   8f150 aarch64-linux-gnu/math/libm.so
 960775    1068      12  961855   ead3f x86_64-linux-gnu/math/libm.so
1189174    5544     368 1195086  123c4e powerpc64le-linux-gnu/math/libm.so

The are small code changes for x86_64 and powerpc64le, which do not
affect performance; but on aarch64 with gcc-14 I see a slight better
code generation due the usage of ldq for floating point constant loading.
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
8f170dc819 math: Use tanpif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic tanpif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                      master        patched   improvement
x86_64                      85.1683        47.7990        43.88%
x86_64v2                    76.8219        41.4679        46.02%
x86_64v3                    73.7775        37.7734        48.80%
aarch64 (Neoverse)          35.4514        18.0742        49.02%
power8                      22.7604        10.1054        55.60%
power10                     22.1358         9.9553        55.03%

reciprocal-throughput        master        patched   improvement
x86_64                      41.0174        19.4718        52.53%
x86_64v2                    34.8565        11.3761        67.36%
x86_64v3                    34.0325         9.6989        71.50%
aarch64 (Neoverse)          25.4349         9.2017        63.82%
power8                      13.8626         3.8486        72.24%
power10                     11.7933         3.6420        69.12%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
de2fca9fe2 math: Use sinpif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic sinpif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                      master        patched   improvement
x86_64                      47.5710        38.4455        19.18%
x86_64v2                    46.8828        40.7563        13.07%
x86_64v3                    44.0034        34.1497        22.39%
aarch64 (Neoverse)          19.2493        14.1968        26.25%
power8                      23.5312        16.3854        30.37%
power10                     22.6485        10.2888        54.57%

reciprocal-throughput        master        patched   improvement
x86_64                      21.8858        11.6717        46.67%
x86_64v2                    22.0620        11.9853        45.67%
x86_64v3                    21.5653        11.3291        47.47%
aarch64 (Neoverse)          13.0615         6.5499        49.85%
power8                      16.2030         6.9580        57.06%
power10                     12.8911         4.2858        66.75%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
be85208b9f math: Use cospif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic cospif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                    master        patched   improvement
x86_64                    47.4679        38.4157        19.07%
x86_64v2                  46.9686        38.3329        18.39%
x86_64v3                  43.8929        31.8510        27.43%
aarch64 (Neoverse)        18.8867        13.2089        30.06%
power8                    22.9435         7.8023        65.99%
power10                   15.4472        7.77505        49.67%

reciprocal-throughput      master        patched   improvement
x86_64                    20.9518        11.4991        45.12%
x86_64v2                  19.8699        10.5921        46.69%
x86_64v3                  19.3475         9.3998        51.42%
aarch64 (Neoverse)        12.5767         6.2158        50.58%
power8                    15.0566         3.2654        78.31%
power10                    9.2866         3.1147        66.46%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
95a01ea955 math: Use atanpif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic atanpif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                     master        patched   improvement
x86_64                     66.3296        52.7558        20.46%
x86_64v2                   66.0429        51.4007        22.17%
x86_64v3                   60.6294        48.7876        19.53%
aarch64 (Neoverse)         24.3163        20.9110        14.00%
power8                     16.5766        13.3620        19.39%
power10                    16.5115        13.4072        18.80%

reciprocal-throughput       master        patched   improvement
x86_64                     30.8599        16.0866        47.87%
x86_64v2                   29.2286        15.4688        47.08%
x86_64v3                   23.0960        12.8510        44.36%
aarch64 (Neoverse)         15.4619        10.6752        30.96%
power8                      7.9200         5.2483        33.73%
power10                     6.8539         4.6262        32.50%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
1cd9ccd8c0 math: Use atan2pif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic atan2pif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                 master        patched   improvement
x86_64                 79.4006        70.8726        10.74%
x86_64v2               77.5136        69.1424        10.80%
x86_64v3               71.8050        68.1637         5.07%
aarch64 (Neoverse)     27.8363        24.7700        11.02%
power8                 39.3893        17.2929        56.10%
power10                19.7200        16.8187        14.71%

reciprocal-throughput   master        patched   improvement
x86_64                 38.3457        30.9471        19.29%
x86_64v2               37.4023        30.3112        18.96%
x86_64v3               33.0713        24.4891        25.95%
aarch64 (Neoverse)     19.3683        15.3259        20.87%
power8                 19.5507        8.27165        57.69%
power10                9.05331        7.63775        15.64%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
ae679a0aca math: Use asinpif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic asinpif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                 master        patched   improvement
x86_64                 46.4996        41.6126        10.51%
x86_64v2               46.7551        38.8235        16.96%
x86_64v3               42.6235        33.7603        20.79%
aarch64 (Neoverse)     17.4161        14.3604        17.55%
power8                 10.7347         9.0193        15.98%
power10                10.6420         9.0362        15.09%

reciprocal-throughput   master        patched   improvement
x86_64                 24.7208        16.5544        33.03%
x86_64v2               24.2177        14.8938        38.50%
x86_64v3               20.5617        10.5452        48.71%
aarch64 (Neoverse)     13.4827        7.17613        46.78%
power8                 6.46134        3.56089        44.89%
power10                5.79007        3.49544        39.63%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
edb2a8f0ae math: Use acospif from CORE-MATH
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic acospif.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

latency                  master        patched   improvement
x86_64                  54.8281        42.9070        21.74%
x86_64v2                54.1717        42.7497        21.08%
x86_64v3                49.3552        34.1512        30.81%
aarch64 (Neoverse)      17.9395        14.3733        19.88%
power8                  20.3110         8.8609        56.37%
power10                 11.3113        8.84067        21.84%

reciprocal-throughput    master        patched   improvement
x86_64                  21.2301        14.4803        31.79%
x86_64v2                20.6858        13.9506        32.56%
x86_64v3                16.1944        11.3377        29.99%
aarch64 (Neoverse)      11.4474        7.13282        37.69%
power8                  10.6916        3.57547        66.56%
power10                 4.64269        3.54145        23.72%

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:57 -03:00
Adhemerval Zanella
57d1fc9971 benchtests: Add tanpif
Random inputs in the range of [-4,4].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:54 -03:00
Adhemerval Zanella
10370a4d00 benchtests: Add sinpif
Random inputs in the range of [-4,4].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:51 -03:00
Adhemerval Zanella
180e97bee6 benchtests: Add cospif
Random inputs in the range of [-4,4].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-12 16:31:44 -03:00
Adhemerval Zanella
1700d306d4 benchtests: Add atanpif
Random inputs in the range of [-10,10].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-11 10:07:13 -03:00
Adhemerval Zanella
ec9d2f3066 benchtests: Add atan2pif
Random inputs in the range of [-10,10].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-11 10:07:08 -03:00
Adhemerval Zanella
082ffa4ddc benchtests: Add asinpif
Random inputs in the range of [-1,1].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-11 10:07:02 -03:00
Adhemerval Zanella
3e0e782b29 benchtests: Add acospif
Random inputs in the range of [-1,1].

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-11 10:06:56 -03:00
Samuel Thibault
392261a2b6 hurd: Replace char foo[1024] with string_t
Like already done in various other places and advised by Roland in

https://lists.gnu.org/archive/html/bug-hurd/2012-04/msg00124.html
2025-02-10 20:10:59 +01:00
Samuel Thibault
659fa18dde hurd: Drop useless buffer initialization in ttyname*
The RPC stub will write a string anyway.
2025-02-10 20:10:59 +01:00
Flavio Cruz
da49165ea6 mig_strncpy: ensure destination string is null terminated
Message-ID: <xaqw66fuawxm5hzgjscfg2oyp6lxflm5tnbb7u253pw3gmdy4m@5z42mw2qz2l2>
2025-02-10 19:44:46 +01:00
gfleury
6bcd7bf100 htl: stop exporting __pthread_default_barrierattr.
since all symbol that use it are now in libc
Message-ID: <20250209200108.865599-9-gfleury@disroot.org>
2025-02-10 01:39:17 +01:00
gfleury
710bbc9659 htl: move pthread_barrier_wait into libc.
Message-ID: <20250209200108.865599-8-gfleury@disroot.org>
2025-02-10 01:39:17 +01:00
gfleury
2789003489 htl: move pthread_barrier_init into libc.
Message-ID: <20250209200108.865599-7-gfleury@disroot.org>
2025-02-10 01:39:17 +01:00
gfleury
735c9b73d6 htl: move pthread_barrier_destroy into libc.
Message-ID: <20250209200108.865599-6-gfleury@disroot.org>
2025-02-10 01:39:17 +01:00
gfleury
ccf19a68ab htl: move pthread_barrierattr_getpshared, pthread_barrierattr_setpshared into libc.
Message-ID: <20250209200108.865599-5-gfleury@disroot.org>
2025-02-10 01:39:17 +01:00
gfleury
ca2a95ee67 htl: move pthread_barrierattr_init into libc.
Message-ID: <20250209200108.865599-4-gfleury@disroot.org>
2025-02-10 01:18:56 +01:00
gfleury
40cbd3c361 htl: move pthread_barrierattr_destroy into libc.
Message-ID: <20250209200108.865599-3-gfleury@disroot.org>
2025-02-10 01:18:17 +01:00
gfleury
7d799d85e8 htl: move __pthread_default_barrierattr into libc.
Message-ID: <20250209200108.865599-2-gfleury@disroot.org>
2025-02-10 01:17:50 +01:00
DJ Delorie
bb6496b964 manual: Update signal descriptions
Based on auditing all the signals and source trees for Hurd and
Linux...

SIGSYS - This is not used for a bad system call (ENOSYS is used
for that).  This is used by SECCOMP and some cases where an invalid
sub-function was requested.

SIGSTKFLT - Note it used to be a coprocessor stack fault but is now
obsolete and available for general user use.

SIGLOST - Hurd only now; note that its original purpose as an NFS
lock lost signal is obsolete.

SIGPWR - Note this is for power lost *and* power restored, and is
more a user-mode signal than a kernel-generated signal.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2025-02-05 23:35:29 -05:00
Tulio Magno Quites Machado Filho
cdb0800022 libio: Replace __LP64__ with __WORDSIZE
__LP64__ is a GCC extension and shouldn't be used in an installed
header.

Fixes: 596a61cf6b (libio: Start to return errors when flushing fwrite's buffer [BZ #29459], 2025-01-28)
Reported-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Arjun Shankar <arjun@redhat.com>
2025-02-05 16:18:40 -03:00
Florian Weimer
3755ffb665 powerpc64le: Also avoid IFUNC for __mempcpy
Code used during early static startup in elf/dl-tls.c uses
__mempcpy.

Fixes commit cbd9fd2369 ("Consolidate
TLS block allocation for static binaries with ld.so").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2025-02-05 09:53:11 +01:00
Florian Weimer
68c9ef4419 elf: Build dl-tls.o with early startup symbol redirections
This is required when building for powerpc64le POWER8 with GCC 8
at least.

Fixes commit cbd9fd2369 ("Consolidate
TLS block allocation for static binaries with ld.so").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2025-02-05 09:52:16 +01:00
DJ Delorie
37a0933e1b manual: make @manpageurl more specific to each output
Tweak the @manpageurl macro to customize the output for
each of html, info, and pdf output.  HTML and PDF (at
least, these days) support clicking on the link title,
whereas info does not.  Add text to the intro section
explaining which man pages are normative and which
aren't.
2025-02-04 14:30:13 -05:00
Adhemerval Zanella
09e7f4d594 math: Fix tanf for some inputs (BZ 32630)
The logic was copied wrong from CORE-MATH.
2025-02-03 09:40:39 -03:00
Florian Weimer
fc058b46c7 elf: Use _dl_find_object instead of _dl_find_dso_for_object in dlopen
The _dl_find_object function uses a binary search and is faster if
there are many objects.
2025-02-02 20:10:09 +01:00
Florian Weimer
b05e78d473 elf: Add fast path to dlopen for fully-opened maps
If the map is already fully open (has matching flags and its
own scope allocated), it is not necessary to unprotected memory
during dlopen.
2025-02-02 20:10:09 +01:00
Florian Weimer
edc6842bbc elf: Determine the caller link map in _dl_open
No functional change expected.

This is in preparation of adding a fast path to dlopen in case
no link map changes are required.
2025-02-02 20:10:09 +01:00
Florian Weimer
d12cb8e452 elf: Merge __dl_libc_freemem into __rtld_libc_freeres
The functions serve very similar purposes.  The advantage of
__rtld_libc_freeres is that it is located within ld.so, so it is
more natural to poke at link map internals there.

This slightly regresses cleanup capabilities for statically linked
binaries.  If that becomes a problem, we should start calling
__rtld_libc_freeres from __libc_freeres (perhaps after renaming it).
2025-02-02 20:10:09 +01:00
Florian Weimer
749310c61b elf: Add l_soname accessor function for DT_SONAME values
It's not necessary to introduce temporaries because the compiler
is able to evaluate l_soname just once in constracts like:

  l_soname (l) != NULL && strcmp (l_soname (l), LIBC_SO) != 0
2025-02-02 20:10:09 +01:00
Florian Weimer
aa1bf89039 elf: Split _dl_lookup_map, _dl_map_new_object from _dl_map_object
So that they can eventually be called separately from dlopen.
2025-02-02 20:10:08 +01:00
Sergey Bugaev
a7aad6e2b7 hurd: Use the new __proc_reauthenticate_complete protocol 2025-02-01 18:20:42 +01:00
Florian Weimer
96429bcc91 elf: Do not add a copy of _dl_find_object to libc.so
This reduces code size and dependencies on ld.so internals from
libc.so.

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

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2025-02-01 12:37:58 +01:00
gfleury
cf51d18b9d htl: move pthread_setcancelstate into libc.
sysdeps/pthread/sem_open.c: call pthread_setcancelstate directely
since forward declaration is gone on hurd too
Message-ID: <20250201080202.494671-1-gfleury@disroot.org>
2025-02-01 11:24:14 +01:00
Adhemerval Zanella
04588633cf math: Fix sinhf for some inputs (BZ 32627)
The logic was copied wrong from CORE-MATH.
2025-01-31 13:05:41 -03:00
Adhemerval Zanella
c79277a167 math: Fix log10p1f internal table value (BZ 32626)
It was copied wrong from CORE-MATH.
2025-01-31 13:05:41 -03:00
Tulio Magno Quites Machado Filho
1b29cb7b78 manual: Safety annotations for timespec_get and timespec_getres
Add preliminary annotations that are consistent with clock_gettime and
clock_getres.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2025-01-31 12:13:20 -03:00
Adhemerval Zanella
22a11aa1c3 sh: Fix tst-guard1 build
The tests uses ARCH_MIN_GUARD_SIZE and the sysdep.h include is not
required.
2025-01-31 09:34:36 -03:00
Arjun Shankar
47c4f4045c manual: Add links to POSIX Semaphores man-pages documentation
The POSIX Semaphores functions are currently undocumented in our info
pages.  This commit adds links to the man-pages documentation for all
the `sem_*' functions (except `sem_clockwait') so that they refer to
some useful documentation instead of just being stubs.  `sem_clockwait'
isn't documented by man-pages but thankfully already has a small useful
blurb in our own docs.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-01-30 15:18:45 +01:00
Arjun Shankar
a3a5634d9b manual: Consolidate POSIX Semaphores docs in Threads chapter
This commit moves the `sem_*' family of functions from the IPC chapter,
replacing them with a reference to their new location in the Threads
chapter.  `sem_clockwait' is also moved out of the Non-POSIX Extensions
subsection since it is now included in the standard since Issue 8:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_clockwait.html

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-01-30 15:18:45 +01:00
Petr Malat
4c43173eba ld.so: Decorate BSS mappings
Decorate BSS mappings with [anon: glibc: .bss <file>], for example
[anon: glibc: .bss /lib/libc.so.6]. The string ".bss" is already used
by bionic so use the same, but add the filename as well. If the name
would be longer than what the kernel allows, drop the directory part
of the path.

Refactor glibc.mem.decorate_maps check to a separate function and use
it to avoid assembling a name, which would not be used later.

Signed-off-by: Petr Malat <oss@malat.biz>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-01-30 10:16:37 -03:00
Adhemerval Zanella
a6fbe36b7f nptl: Add support for setup guard pages with MADV_GUARD_INSTALL
Linux 6.13 (662df3e5c3766) added a lightweight way to define guard areas
through madvise syscall.  Instead of PROT_NONE the guard region through
mprotect, userland can madvise the same area with a special flag, and
the kernel ensures that accessing the area will trigger a SIGSEGV (as for
PROT_NONE mapping).

The madvise way has the advantage of less kernel memory consumption for
the process page-table (one less VMA per guard area), and slightly less
contention on kernel (also due to the fewer VMA areas being tracked).

The pthread_create allocates a new thread stack in two ways: if a guard
area is set (the default) it allocates the memory range required using
PROT_NONE and then mprotect the usable stack area. Otherwise, if a
guard page is not set it allocates the region with the required flags.

For the MADV_GUARD_INSTALL support, the stack area region is allocated
with required flags and then the guard region is installed.  If the
kernel does not support it, the usual way is used instead (and
MADV_GUARD_INSTALL is disabled for future stack creations).

The stack allocation strategy is recorded on the pthread struct, and it
is used in case the guard region needs to be resized.  To avoid needing
an extra field, the 'user_stack' is repurposed and renamed to 'stack_mode'.

This patch also adds a proper test for the pthread guard.

I checked on x86_64, aarch64, powerpc64le, and hppa with kernel 6.13.0-rc7.

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-01-30 10:16:37 -03:00
John David Anglin
8e86549d14 nptl: Correct stack size attribute when stack grows up [BZ #32574]
Set stack size attribute to the size of the mmap'd region only
when the size of the remaining stack space is less than the size
of the mmap'd region.

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

Signed-off-by: John David Anglin <dave.anglin@bell.net>
2025-01-29 16:51:16 -05:00
Florian Weimer
32ac9f8049 manual: Update compatibility note on flushing of line-oriented files
Operation systems which represent text files in a line-oriented
fashion (and not as byte streams with a character sequence reserved
for line termination) logically cannot flush a buffer without
also creating a terminated line.

Update this portability note and move it to the Binary Streams
section.  Add another related compatibility concern, too.
2025-01-29 13:16:50 +01:00
gfleury
9a31eb64db htl: move pthread_setcanceltype into libc.
Message-ID: <20250103103750.870897-7-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
265c5991af htl: move pthread_mutex_consistent, pthread_mutex_consistent_np into libc.
Message-ID: <20250103103750.870897-6-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
8bfabe7a92 htl: move pthread_mutex_destroy into libc.
Message-ID: <20250103103750.870897-5-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
be9f0e7681 htl: move pthread_mutex_getprioceiling, pthread_mutex_setprioceiling into libc
Message-ID: <20250103103750.870897-4-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
2ebc2d8e24 htl: move pthread_mutex_{lock, unlock, trylock, timedlock, clocklock}
I haven't exposed _pthread_mutex_lock,  _pthread_mutex_trylock and
_pthread_mutex_unlock in GLIBC_PRIVATE since there aren't used in any
code in libpthread
Message-ID: <20250103103750.870897-3-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
e892a93073 htl: move pthread_mutex_init into libc.
Message-ID: <20250103103750.870897-2-gfleury@disroot.org>
2025-01-29 02:32:36 +01:00
gfleury
56b25bfd60 htl: remove leftover for pthread_mutexattr_settype
from b386295727
2025-01-29 02:32:36 +01:00
Joseph Myers
203452a460 Add test of input file flushing / offset issues
Having fixed several bugs relating to flushing of FILE* streams (with
fflush and other operations) and their offsets (both the file position
indicator in the FILE*, and the offset in the underlying open file
description), especially after ungetc but not limited to that case,
add a test that more systematically covers different combinations of
cases for such issues, with 57220 separate scenarios tested (which
include examples of all the five separate fixed bugs), all of which
pass given the five previous bug fixes.

Tested for x86_64.
2025-01-28 23:39:12 +00:00
Joseph Myers
3ff3b9997c Fix fflush handling for mmap files after ungetc (bug 32535)
As discussed in bug 32535, fflush fails on files opened for reading
using mmap after ungetc.  Fix the logic to handle this case and still
compute the file offset correctly.

Tested for x86_64.
2025-01-28 23:20:08 +00:00
Joseph Myers
0dcc0b2f63 Fix fseek handling for mmap files after ungetc or fflush (bug 32529)
As discussed in bug 32529, fseek fails on files opened for reading
using mmap after ungetc.  The implementation of fseek for such files
has an offset computation that's also incorrect after fflush.  A
combined fix addresses both problems (with tests for both included as
well) and it seems reasonable to consider them a single bug.

Tested for x86_64.
2025-01-28 22:35:21 +00:00
Joseph Myers
94251ae99e Make fflush (NULL) flush input files (bug 32369)
As discussed in bug 32369 and required by POSIX, the POSIX feature
fflush (NULL) should flush input files, not just output files.  The
POSIX requirement is that "fflush() shall perform this flushing action
on all streams for which the behavior is defined above", and the
definition for input files is for "a stream open for reading with an
underlying file description, if the file is not already at EOF, and
the file is one capable of seeking".

Implement this requirement in glibc.  (The underlying flushing
implementation is what deals with avoiding errors for seeking on an
unseekable file.)

Tested for x86_64.
2025-01-28 21:53:49 +00:00
Joseph Myers
be6818be31 Make fclose seek input file to right offset (bug 12724)
As discussed in bug 12724 and required by POSIX, before an input file
(based on an underlying seekable file descriptor) is closed, fclose is
sometimes required to seek that file descriptor to the correct offset,
so that any other file descriptors sharing the underlying open file
description are left at that offset (as a motivating example, a script
could call a sequence of commands each of which processes some data
from (seekable) stdin using stdio; fclose needs to do this so that
each successive command can read exactly the data not handled by
previous commands), but glibc fails to do this.

The precise POSIX wording has changed a few times; in the 2024 edition
it's "If the file is not already at EOF, and the file is one capable
of seeking, the file offset of the underlying open file description
shall be set to the file position of the stream if the stream is the
active handle to the underlying file description.".

Add appropriate logic to _IO_new_file_close_it to handle this case.  I
haven't made any attempt to test or change things in this area for the
"old" functions.

Note that there was a previous attempt to fix bug 12724, reverted in
commit eb6cbd249f.  The fix version here
addresses the original test in that bug report without breaking the
one given in a subsequent comment in that bug report (which works with
glibc before the patch, but maybe was broken by the original fix that
was reverted).

The logic here tries to take care not to seek the file, even to its
newly computed current offset, if at EOF / possibly not the active
handle; even seeking to the current offset would be problematic
because of a potential race (fclose computes the current offset,
another thread or process with the active handle does its own seek,
fclose does a seek (not permitted by POSIX in this case) that loses
the effect of the seek on the active handle in another thread or
process).  There are tests included for various cases of being or not
being the active handle, though there aren't tests for the potential
race condition.

Tested for x86_64.
2025-01-28 20:22:56 +00:00
Joseph Myers
377e9733b5 Fix fflush after ungetc on input file (bug 5994)
As discussed in bug 5994 (plus duplicates), POSIX requires fflush
after ungetc to discard pushed-back characters but preserve the file
position indicator.  For this purpose, each ungetc decrements the file
position indicator by 1; it is unspecified after ungetc at the start
of the file, and after ungetwc, so no special handling is needed for
either of those cases.

This is fixed with appropriate logic in _IO_new_file_sync.  I haven't
made any attempt to test or change things in this area for the "old"
functions; the case of files using mmap is addressed in a subsequent
patch (and there seem to be no problems in this area with files opened
with fmemopen).

Tested for x86_64.
2025-01-28 19:38:27 +00:00
Tulio Magno Quites Machado Filho
1515f74fd8 libio: Add a new fwrite test that evaluates partial writes
Test if the file-position is correctly updated when fwrite tries to
flush its internal cache but is not able to completely write all items.

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-01-28 15:37:44 -03:00
Tulio Magno Quites Machado Filho
596a61cf6b libio: Start to return errors when flushing fwrite's buffer [BZ #29459]
When an error happens, fwrite is expected to return a value that is less
than nmemb.  If this error happens while flushing its internal buffer,
fwrite is in a complex scenario: all the data might have been written to
the buffer, indicating a successful copy, but the buffer is expected to
be flushed and it was not.

POSIX.1-2024 states the following about errors on fwrite:

    If an error occurs, the resulting value of the file-position indicator
    for the stream is unspecified.

    The fwrite() function shall return the number of elements successfully
    written, which may be less than nitems if a write error is encountered.

With that in mind, this commit modifies _IO_new_file_write in order to
return the total number of bytes written via the file pointer.  It also
modifies fwrite in order to use the new information and return the
correct number of bytes written even when sputn returns EOF.

Add 2 tests:

1. tst-fwrite-bz29459: This test is based on the reproducer attached to
   bug 29459.  In order to work, it requires to pipe stdout to another
   process making it hard to reuse test-driver.c.  This code is more
   specific to the issue reported.
2. tst-fwrite-pipe: Recreates the issue by creating a pipe that is shared
   with a child process.  Reuses test-driver.c.  Evaluates a more generic
   scenario.

Co-authored-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: DJ Delorie <dj@redhat.com>
2025-01-28 15:37:44 -03:00
Martin Coufal
45c42b65c2 Add new tests for fopen
Adding some basic tests for fopen, testing different modes, stream
positioning and concurrent read/write operation on files.
Reviewed-by: DJ Delorie <dj@redhat.com>
2025-01-28 12:50:50 -05:00
Andreas K. Hüttel
42aba91895
Increase version to 2.41.9000, add new section to NEWS
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
2025-01-28 18:42:35 +01:00
407 changed files with 25076 additions and 4127 deletions

View file

@ -633,7 +633,7 @@ link-libc-printers-tests = $(link-libc-rpath) \
$(link-libc-tests-after-rpath-link)
# This is how to find at build-time things that will be installed there.
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support misc
rpath-link = \
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
else # build-static

27
NEWS
View file

@ -5,6 +5,33 @@ 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.42
Major new features:
[Add new features here]
Deprecated and removed features, and other changes affecting compatibility:
[Add deprecations, removals and changes affecting compatibility here]
Changes to build and runtime requirements:
[Add changes to build and runtime requirements here]
Security related changes:
The following CVEs were fixed in this release, details of which can be
found in the advisories directory of the release tarball:
[The release manager will add the list generated by
scripts/process-advisories.sh just before the release.]
The following bugs were resolved with this release:
[The release manager will add the list generated by
scripts/list-fixed-bugs.py just before the release.]
Version 2.41
Major new features:

View file

@ -334,3 +334,31 @@ sysdeps/ieee754/flt-32/s_tanhf.c:
(src/binary32/tanh/tanhf.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_acospif.c:
(src/binary32/acospi/acospif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_asinpif.c:
(src/binary32/asinpi/asinpif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_atan2pif.c:
(src/binary32/atan2pi/atan2pif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_atanpif.c:
(src/binary32/atanpi/atanpif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_cospif.c:
(src/binary32/cospi/cospif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_sinpif.c:
(src/binary32/sinpi/sinpif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.
sysdeps/ieee754/flt-32/s_tanpif.c:
(src/binary32/tanpi/tanpif.c in CORE-MATH)
- the code was adapted to use glibc code style and internal
functions to handle errno, overflow, and underflow.

View file

@ -21,5 +21,20 @@ CVE-Id: CVE-2025-0395
Public-Date: 2025-01-22
Vulnerable-Commit: f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 (2.13-175)
Fix-Commit: 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578 (2.41)
Fix-Commit: cdb9ba84191ce72e86346fb8b1d906e7cd930ea2 (2.42)
Fix-Commit: 69fda28279b497bd405fdd442a6d8e4d3d5f681b (2.41-7)
Fix-Commit: 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c (2.40-66)
Fix-Commit: d6c156c326999f144cb5b73d29982108d549ad8a (2.40-71)
Fix-Commit: 808a84a8b81468b517a4d721fdc62069cb8c211f (2.39-146)
Fix-Commit: f6d48470aef9264d2d56f4c4533eb76db7f9c2e4 (2.39-150)
Fix-Commit: c32fd59314c343db88c3ea4a203870481d33c3d2 (2.38-122)
Fix-Commit: f984e2d7e8299726891a1a497a3c36cd5542a0bf (2.38-124)
Fix-Commit: a3d7865b098a3a67c44f7812208d9ce4718873ba (2.37-143)
Fix-Commit: b989519fe1683c204ac24ec92830e3fe3bfaccad (2.37-146)
Fix-Commit: 7971add7ee4171fdd8dfd17e7c04c4ed77a18845 (2.36-216)
Fix-Commit: 0487893d5c5bc6710d83d7c3152d888a0339559e (2.36-219)
Fix-Commit: 8b5d4be762419c4f6176261c6fea40ac559b88dc (2.35-370)
Fix-Commit: 8b3d09dc0d350191985f9d291cc30ce96f034b49 (2.35-373)
Fix-Commit: df4e1f4a5096b385c9bcc94424cf2eaa227b3761 (2.34-500)
Fix-Commit: 31eb872cb21449832ab47ad5db83281d240e1d03 (2.34-503)
Reported-By: Qualys Security Advisory

View file

@ -39,6 +39,7 @@ tests := \
test-assert-perr \
tst-assert-c++ \
tst-assert-g++ \
tst-assert-sa-2025-0001 \
# tests
ifeq ($(have-cxx-thread_local),yes)

View file

@ -0,0 +1,92 @@
/* Test for CVE-2025-0395.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Test that a large enough __progname does not result in a buffer overflow
when printing an assertion failure. This was CVE-2025-0395. */
#include <assert.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
#include <support/check.h>
#include <support/support.h>
#include <support/xstdio.h>
#include <support/xunistd.h>
extern const char *__progname;
int
do_test (int argc, char **argv)
{
support_need_proc ("Reads /proc/self/maps to add guards to writable maps.");
ignore_stderr ();
/* XXX assumes that the assert is on a 2 digit line number. */
const char *prompt = ": %s:99: do_test: Assertion `argc < 1' failed.\n";
int ret = fprintf (stderr, prompt, __FILE__);
if (ret < 0)
FAIL_EXIT1 ("fprintf failed: %m\n");
size_t pagesize = getpagesize ();
size_t namesize = pagesize - 1 - ret;
/* Alter the progname so that the assert message fills the entire page. */
char progname[namesize];
memset (progname, 'A', namesize - 1);
progname[namesize - 1] = '\0';
__progname = progname;
FILE *f = xfopen ("/proc/self/maps", "r");
char *line = NULL;
size_t len = 0;
uintptr_t prev_to = 0;
/* Pad the beginning of every writable mapping with a PROT_NONE map. This
ensures that the mmap in the assert_fail path never ends up below a
writable map and will terminate immediately in case of a buffer
overflow. */
while (xgetline (&line, &len, f))
{
uintptr_t from, to;
char perm[4];
sscanf (line, "%" SCNxPTR "-%" SCNxPTR " %c%c%c%c ",
&from, &to,
&perm[0], &perm[1], &perm[2], &perm[3]);
bool writable = (memchr (perm, 'w', 4) != NULL);
if (prev_to != 0 && from - prev_to > pagesize && writable)
xmmap ((void *) from - pagesize, pagesize, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
prev_to = to;
}
xfclose (f);
assert (argc < 1);
return 0;
}
#define EXPECTED_SIGNAL SIGABRT
#define TEST_FUNCTION_ARGV do_test
#include <support/test-driver.c>

View file

@ -28,16 +28,20 @@ bench-math := \
acosf \
acosh \
acoshf \
acospif \
asin \
asinf \
asinh \
asinhf \
asinpif \
atan \
atan2 \
atan2f \
atan2pif \
atanf \
atanh \
atanhf \
atanpif \
cbrt \
cbrtf \
ceil \
@ -46,6 +50,7 @@ bench-math := \
cosf \
cosh \
coshf \
cospif \
erf \
erfc \
erfcf \
@ -110,11 +115,13 @@ bench-math := \
sinf \
sinh \
sinhf \
sinpif \
sqrt \
tan \
tanf \
tanh \
tanhf \
tanpif \
tgamma \
tgammaf \
trunc \
@ -194,6 +201,7 @@ string-benchset := \
strcpy_chk \
strcspn \
strlen \
strlen-random \
strncasecmp \
strncat \
strncmp \

2710
benchtests/acospif-inputs Normal file

File diff suppressed because it is too large Load diff

2710
benchtests/asinpif-inputs Normal file

File diff suppressed because it is too large Load diff

2005
benchtests/atan2pif-inputs Normal file

File diff suppressed because it is too large Load diff

2005
benchtests/atanpif-inputs Normal file

File diff suppressed because it is too large Load diff

View file

@ -22,9 +22,8 @@
#else
# define TEST_NAME "bzero"
#endif
#define START_SIZE (128 * 1024)
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
#define TIMEOUT (20 * 60)
#define START_SIZE (64 * 1024)
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
#include "bench-string.h"
#include "json-lib.h"
@ -52,7 +51,7 @@ IMPL (memset_zero, 0)
static void
do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s, size_t n)
{
size_t i, iters = 16;
size_t i, iters = (MIN_PAGE_SIZE * 64) / n;
timing_t start, stop, cur;
TIMING_NOW (start);
@ -74,20 +73,13 @@ do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s, size_t n)
static void
do_test (json_ctx_t *json_ctx, size_t align, size_t len)
{
align &= 63;
if ((align + len) * sizeof (CHAR) > page_size)
return;
json_element_object_begin (json_ctx);
json_attr_uint (json_ctx, "length", len);
json_attr_uint (json_ctx, "alignment", align);
json_array_begin (json_ctx, "timings");
FOR_EACH_IMPL (impl, 0)
{
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, len);
alloc_bufs ();
}
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, len);
json_array_end (json_ctx);
json_element_object_end (json_ctx);

View file

@ -19,10 +19,9 @@
#ifndef MEMCPY_RESULT
# define MEMCPY_RESULT(dst, len) dst
# define START_SIZE (64 * 1024)
# define MIN_PAGE_SIZE (getpagesize () + 32 * 1024 * 1024)
# define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
# define TEST_MAIN
# define TEST_NAME "memcpy"
# define TIMEOUT (20 * 60)
# include "bench-string.h"
IMPL (memcpy, 1)
@ -36,7 +35,7 @@ static void
do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, const char *src,
size_t len)
{
size_t i, iters = 16;
size_t i, iters = (MIN_PAGE_SIZE * 8) / len;
timing_t start, stop, cur;
TIMING_NOW (start);
@ -59,12 +58,7 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len,
char *s1, *s2;
size_t repeats;
align1 &= 4095;
if (align1 + len >= page_size)
return;
align2 &= 4095;
if (align2 + len >= page_size)
return;
s1 = (char *) (buf1 + align1);
s2 = (char *) (buf2 + align2);

View file

@ -16,12 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define BASE_PAGE_SIZE (1024 * 1024)
#define START_SIZE (4 * 1024)
#define START_SIZE (64 * 1024)
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
#define TEST_MAIN
#define TEST_NAME "memmove"
#define TIMEOUT (20 * 60)
#include "bench-string.h"
#include "json-lib.h"
@ -33,7 +31,7 @@ static void
do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, char *src,
size_t len)
{
size_t i, iters = 16;
size_t i, iters = (MIN_PAGE_SIZE * 8) / len;
timing_t start, stop, cur;
TIMING_NOW (start);
@ -54,13 +52,8 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len)
size_t i, j;
char *s1, *s2;
align1 &= 127;
if (align1 + len >= page_size)
return;
align2 &= 127;
if (align2 + len >= page_size)
return;
align1 &= 4095;
align2 &= 4095;
s1 = (char *) (buf2 + align1);
s2 = (char *) (buf2 + align2);

View file

@ -18,9 +18,8 @@
#define TEST_MAIN
#define TEST_NAME "memset"
#define START_SIZE (128 * 1024)
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
#define TIMEOUT (20 * 60)
#define START_SIZE (64 * 1024)
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
#include "bench-string.h"
#include "json-lib.h"
@ -35,7 +34,7 @@ static void
do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s,
int c __attribute ((unused)), size_t n)
{
size_t i, iters = 16;
size_t i, iters = (MIN_PAGE_SIZE * 64) / n;
timing_t start, stop, cur;
TIMING_NOW (start);
@ -53,10 +52,6 @@ do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s,
static void
do_test (json_ctx_t *json_ctx, size_t align, int c, size_t len)
{
align &= 63;
if ((align + len) * sizeof (CHAR) > page_size)
return;
json_element_object_begin (json_ctx);
json_attr_uint (json_ctx, "length", len);
json_attr_uint (json_ctx, "alignment", align);
@ -64,10 +59,7 @@ do_test (json_ctx_t *json_ctx, size_t align, int c, size_t len)
json_array_begin (json_ctx, "timings");
FOR_EACH_IMPL (impl, 0)
{
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, c, len);
alloc_bufs ();
}
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, c, len);
json_array_end (json_ctx);
json_element_object_end (json_ctx);

View file

@ -0,0 +1,194 @@
/* Measure strlen performance.
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/>. */
#define TEST_MAIN
#define TEST_NAME "strlen"
#define NUM_TESTS 65536
#define MAX_ALIGN 32
#define MAX_STRLEN 128
#define MIN_PAGE_SIZE (2 * getpagesize())
#include "bench-string.h"
#include <assert.h>
#include "json-lib.h"
typedef size_t (*proto_t) (const CHAR *);
size_t memchr_strlen (const CHAR *);
IMPL (memchr_strlen, 0)
size_t
memchr_strlen (const CHAR *p)
{
return (const CHAR *)MEMCHR (p, 0, PTRDIFF_MAX) - p;
}
IMPL (STRLEN, 1)
static uint32_t strlen_tests[NUM_TESTS];
typedef struct { uint16_t size; uint16_t freq; } freq_data_t;
typedef struct { uint16_t align; uint16_t freq; } align_data_t;
#define SIZE_NUM 65536
#define SIZE_MASK (SIZE_NUM-1)
static uint8_t strlen_len_arr[SIZE_NUM];
/* Frequency data for strlen sizes up to 256 based on SPEC2017. */
static freq_data_t strlen_len_freq[] =
{
{ 12,22671}, { 18,12834}, { 13, 9555}, { 6, 6348}, { 17, 6095}, { 11, 2115},
{ 10, 1335}, { 7, 814}, { 2, 646}, { 9, 483}, { 8, 471}, { 16, 418},
{ 4, 390}, { 1, 388}, { 5, 233}, { 3, 204}, { 0, 79}, { 14, 79},
{ 15, 69}, { 26, 36}, { 22, 35}, { 31, 24}, { 32, 24}, { 19, 21},
{ 25, 17}, { 28, 15}, { 21, 14}, { 33, 14}, { 20, 13}, { 24, 9},
{ 29, 9}, { 30, 9}, { 23, 7}, { 34, 7}, { 27, 6}, { 44, 5},
{ 42, 4}, { 45, 3}, { 47, 3}, { 40, 2}, { 41, 2}, { 43, 2},
{ 58, 2}, { 78, 2}, { 36, 2}, { 48, 1}, { 52, 1}, { 60, 1},
{ 64, 1}, { 56, 1}, { 76, 1}, { 68, 1}, { 80, 1}, { 84, 1},
{ 72, 1}, { 86, 1}, { 35, 1}, { 39, 1}, { 50, 1}, { 38, 1},
{ 37, 1}, { 46, 1}, { 98, 1}, {102, 1}, {128, 1}, { 51, 1},
{107, 1}, { 0, 0}
};
#define ALIGN_NUM 1024
#define ALIGN_MASK (ALIGN_NUM-1)
static uint8_t strlen_align_arr[ALIGN_NUM];
/* Alignment data for strlen based on SPEC2017. */
static align_data_t string_align_freq[] =
{
{8, 470}, {32, 427}, {16, 99}, {1, 19}, {2, 6}, {4, 3}, {0, 0}
};
static void
init_strlen_distribution (void)
{
int i, j, freq, size, n;
for (n = i = 0; (freq = strlen_len_freq[i].freq) != 0; i++)
for (j = 0, size = strlen_len_freq[i].size; j < freq; j++)
strlen_len_arr[n++] = size;
assert (n == SIZE_NUM);
for (n = i = 0; (freq = string_align_freq[i].freq) != 0; i++)
for (j = 0, size = string_align_freq[i].align; j < freq; j++)
strlen_align_arr[n++] = size;
assert (n == ALIGN_NUM);
}
static volatile size_t maskv = 0;
static void
do_one_test (json_ctx_t *json_ctx, impl_t *impl, size_t iters,
uint32_t *input, size_t n)
{
timing_t start, stop, cur;
size_t res = 0;
size_t mask = maskv;
/* Avoid 'cold start' performance penalty. */
for (int i = 0; i < 10; i++)
for (int j = 0; j < n; j++)
CALL (impl, (const char*)buf1 + input[j]);
TIMING_NOW (start);
for (int i = 0; i < iters; ++i)
for (int j = 0; j < n; j++)
res = CALL (impl, (const char*)buf1 + input[j] + (res & mask));
TIMING_NOW (stop);
TIMING_DIFF (cur, start, stop);
json_element_double (json_ctx, (double) cur / (double) iters);
}
static void
do_test (json_ctx_t *json_ctx)
{
size_t n;
uint8_t *a = buf1;
uint16_t index[MAX_ALIGN];
memset (a, 'x', MIN_PAGE_SIZE);
/* Create indices for strings at all alignments. */
for (int i = 0; i < MAX_ALIGN; i++)
{
index[i] = i * (MAX_STRLEN + 1);
a[index[i] + MAX_STRLEN] = 0;
}
/* Create a random set of strlen input strings using the string length
and alignment distributions. */
for (n = 0; n < NUM_TESTS; n++)
{
int align = strlen_align_arr[rand () & ALIGN_MASK];
int exp_len = strlen_len_arr[rand () & SIZE_MASK];
strlen_tests[n] =
index[(align + exp_len) & (MAX_ALIGN - 1)] + MAX_STRLEN - exp_len;
assert ((strlen_tests[n] & (align - 1)) == 0);
assert (strlen ((char*) a + strlen_tests[n]) == exp_len);
}
json_element_object_begin (json_ctx);
json_array_begin (json_ctx, "timings");
FOR_EACH_IMPL (impl, 0)
do_one_test (json_ctx, impl, INNER_LOOP_ITERS_MEDIUM, strlen_tests, n);
json_array_end (json_ctx);
json_element_object_end (json_ctx);
}
int
test_main (void)
{
json_ctx_t json_ctx;
test_init ();
init_strlen_distribution ();
json_init (&json_ctx, 0, stdout);
json_document_begin (&json_ctx);
json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
json_attr_object_begin (&json_ctx, "functions");
json_attr_object_begin (&json_ctx, TEST_NAME);
json_attr_string (&json_ctx, "bench-variant", "random");
json_array_begin (&json_ctx, "ifuncs");
FOR_EACH_IMPL (impl, 0)
json_element_string (&json_ctx, impl->name);
json_array_end (&json_ctx);
json_array_begin (&json_ctx, "results");
do_test (&json_ctx);
json_array_end (&json_ctx);
json_attr_object_end (&json_ctx);
json_attr_object_end (&json_ctx);
json_document_end (&json_ctx);
return ret;
}
#include <support/test-driver.c>

2409
benchtests/cospif-inputs Normal file

File diff suppressed because it is too large Load diff

2409
benchtests/sinpif-inputs Normal file

File diff suppressed because it is too large Load diff

2409
benchtests/tanpif-inputs Normal file

File diff suppressed because it is too large Load diff

View file

@ -53,6 +53,7 @@ c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@
enable-werror = @enable_werror@
have-z-execstack = @libc_cv_z_execstack@
have-no-error-execstack = @libc_cv_no_error_execstack@
have-protected-data = @libc_cv_protected_data@
have-insert = @libc_cv_insert@
have-glob-dat-reloc = @libc_cv_has_glob_dat@

134
configure vendored
View file

@ -659,6 +659,7 @@ libc_cv_has_glob_dat
libc_cv_fpie
libc_cv_test_static_pie
libc_cv_z_execstack
libc_cv_no_error_execstack
ASFLAGS_config
libc_cv_cc_with_libunwind
libc_cv_insert
@ -7114,6 +7115,40 @@ if test $libc_cv_as_noexecstack = yes; then
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-error-execstack" >&5
printf %s "checking for linker that supports --no-error-execstack... " >&6; }
libc_linker_feature=no
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
-Wl,-no-error-execstack -nostdlib -nostartfiles
-fPIC -shared -o conftest.so conftest.c
1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-no-error-execstack -nostdlib \
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
| grep "warning: --no-error-execstack ignored" > /dev/null 2>&1; then
true
else
libc_linker_feature=yes
fi
fi
rm -f conftest*
if test $libc_linker_feature = yes; then
libc_cv_no_error_execstack=yes
else
libc_cv_no_error_execstack=no
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
printf "%s\n" "$libc_linker_feature" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z execstack" >&5
printf %s "checking for linker that supports -z execstack... " >&6; }
libc_linker_feature=no
@ -8908,6 +8943,105 @@ printf "%s\n" "$libc_linker_feature" >&6; }
config_vars="$config_vars
load-address-ldflag = $libc_cv_load_address_ldflag"
# Check if compilers support GCS in branch protection:
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5
printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; }
if test ${libc_cv_cc_gcs+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then :
libc_cv_cc_gcs=yes
else case e in #(
e) libc_cv_cc_gcs=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5
printf "%s\n" "$libc_cv_cc_gcs" >&6; }
if test "$TEST_CC" = "$CC"; then
libc_cv_test_cc_gcs=$libc_cv_cc_gcs
else
saved_CC="$CC"
CC="$TEST_CC"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5
printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; }
if test ${libc_cv_test_cc_gcs+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then :
libc_cv_test_cc_gcs=yes
else case e in #(
e) libc_cv_test_cc_gcs=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5
printf "%s\n" "$libc_cv_test_cc_gcs" >&6; }
CC="$saved_CC"
fi
config_vars="$config_vars
have-cc-gcs = $libc_cv_cc_gcs"
config_vars="$config_vars
have-test-cc-gcs = $libc_cv_test_cc_gcs"
# Check if linker supports GCS marking
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5
printf %s "checking for linker that supports -z gcs=always... " >&6; }
libc_linker_feature=no
cat > conftest.c <<EOF
int _start (void) { return 42; }
EOF
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
-Wl,-z,gcs=always -nostdlib -nostartfiles
-fPIC -shared -o conftest.so conftest.c
1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
| grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then
true
else
libc_linker_feature=yes
fi
fi
rm -f conftest*
if test $libc_linker_feature = yes; then
libc_cv_ld_gcs=yes
else
libc_cv_ld_gcs=no
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
printf "%s\n" "$libc_linker_feature" >&6; }
config_vars="$config_vars
have-ld-gcs = $libc_cv_ld_gcs"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
printf %s "checking if we can build programs as PIE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext

View file

@ -1318,6 +1318,10 @@ if test $libc_cv_as_noexecstack = yes; then
fi
AC_SUBST(ASFLAGS_config)
LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,-no-error-execstack],
[libc_cv_no_error_execstack=yes], [libc_cv_no_error_execstack=no])
AC_SUBST(libc_cv_no_error_execstack)
LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
[libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
AC_SUBST(libc_cv_z_execstack)
@ -1992,6 +1996,23 @@ LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
[libc_cv_load_address_ldflag=])
LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
# Check if compilers support GCS in branch protection:
LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -mbranch-protection=gcs],
[-Werror -mbranch-protection=gcs],
libc_cv_cc_gcs,
[libc_cv_cc_gcs=yes],
[libc_cv_cc_gcs=no],
libc_cv_test_cc_gcs,
[libc_cv_test_cc_gcs=yes],
[libc_cv_test_cc_gcs=no])
LIBC_CONFIG_VAR([have-cc-gcs], [$libc_cv_cc_gcs])
LIBC_CONFIG_VAR([have-test-cc-gcs], [$libc_cv_test_cc_gcs])
# Check if linker supports GCS marking
LIBC_LINKER_FEATURE([-z gcs=always], [-Wl,-z,gcs=always],
[libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no])
LIBC_CONFIG_VAR([have-ld-gcs], [$libc_cv_ld_gcs])
AC_MSG_CHECKING(if we can build programs as PIE)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
# error PIE is not supported

View file

@ -30,6 +30,7 @@
#include <dl-extra_tls.h>
#include <array_length.h>
#include <elf/dl-tls_block_align.h>
#include <dl-symbol-redir-ifunc.h>
#ifdef SHARED
#error makefile bug, this file is for static only

View file

@ -34,7 +34,6 @@ routines = \
dl-addr \
dl-addr-obj \
dl-early_allocate \
dl-find_object \
dl-iteratephdr \
dl-libc \
dl-origin \
@ -61,6 +60,7 @@ dl-routines = \
dl-deps \
dl-exception \
dl-execstack \
dl-find_object \
dl-fini \
dl-init \
dl-load \
@ -379,6 +379,7 @@ tests += \
tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit-tlsdesc-dlopen2 \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@ -863,6 +864,7 @@ modules-names += \
tst-auditmanymod8 \
tst-auditmanymod9 \
tst-auditmod-tlsdesc \
tst-auditmod-tlsdesc2 \
tst-auditmod1 \
tst-auditmod11 \
tst-auditmod12 \
@ -1135,12 +1137,14 @@ tests += \
tst-dlopen-pie \
tst-dlopen-self-pie \
tst-dlopen-tlsmodid-pie \
tst-pie-bss \
tst-pie1 \
tst-pie2 \
# tests
tests-pie += \
tst-dlopen-self-pie \
tst-dlopen-tlsmodid-pie \
tst-pie-bss \
tst-pie1 \
tst-pie2 \
# tests-pie
@ -1155,9 +1159,11 @@ LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
ifeq (yes,$(enable-static-pie))
tests += \
tst-pie-address-static \
tst-pie-bss-static \
# tests
tests-static += \
tst-pie-address-static \
tst-pie-bss-static \
# tests-static
LDFLAGS-tst-pie-address-static += \
$(load-address-ldflag)=$(pde-load-address)
@ -1988,6 +1994,9 @@ $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
CPPFLAGS-tst-execstack.c += -DUSE_PTHREADS=0
LDFLAGS-tst-execstack = -Wl,-z,noexecstack
LDFLAGS-tst-execstack-mod.so = -Wl,-z,execstack
ifeq ($(have-no-error-execstack),yes)
LDFLAGS-tst-execstack-mod.so += -Wl,--no-error-execstack
endif
$(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
@ -1997,6 +2006,9 @@ CFLAGS-tst-execstack-prog.c += -Wno-trampolines
CFLAGS-tst-execstack-mod.c += -Wno-trampolines
LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack
ifeq ($(have-no-error-execstack),yes)
LDFLAGS-tst-execstack-prog-static += -Wl,--no-error-execstack
endif
CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines
ifeq (yes,$(build-hardcoded-path-in-tests))
@ -2074,6 +2086,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
CFLAGS-tst-pie1.c += $(pie-ccflag)
CFLAGS-tst-pie2.c += $(pie-ccflag)
CFLAGS-tst-pie-bss.c += $(pie-ccflag)
CFLAGS-tst-pie-address.c += $(pie-ccflag)
$(objpfx)tst-piemod1.so: $(libsupport)
@ -3189,6 +3202,9 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
$(objpfx)tst-audit-tlsdesc-dlopen2.out: $(objpfx)tst-auditmod-tlsdesc2.so \
$(patsubst %, $(objpfx)%.so, $(tlsmod17a-modules))
tst-audit-tlsdesc-dlopen2-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc2.so
$(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \

View file

@ -21,7 +21,6 @@
#include <ldsodefs.h>
#include <sys/mman.h>
#include <dl-cache.h>
#include <dl-procinfo.h>
#include <stdint.h>
#include <_itoa.h>
#include <dl-hwcaps.h>

View file

@ -24,7 +24,6 @@
#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"

View file

@ -356,7 +356,7 @@ _dlfo_lookup (uintptr_t pc, struct dl_find_object_internal *first1, size_t size)
}
int
__dl_find_object (void *pc1, struct dl_find_object *result)
_dl_find_object (void *pc1, struct dl_find_object *result)
{
uintptr_t pc = (uintptr_t) pc1;
@ -463,8 +463,7 @@ __dl_find_object (void *pc1, struct dl_find_object *result)
return -1;
} /* Transaction retry loop. */
}
hidden_def (__dl_find_object)
weak_alias (__dl_find_object, _dl_find_object)
rtld_hidden_def (_dl_find_object)
/* _dlfo_process_initial is called twice. First to compute the array
sizes from the initial loaded mappings. Second to fill in the

View file

@ -23,7 +23,6 @@
#include <unistd.h>
#include <ldsodefs.h>
#include <dl-procinfo.h>
#include <dl-hwcaps.h>
/* This is the result of counting the substrings in a colon-separated

View file

@ -226,110 +226,3 @@ __libc_dlclose (void *map)
#endif
return dlerror_run (do_dlclose, map);
}
static bool
free_slotinfo (struct dtv_slotinfo_list **elemp)
{
size_t cnt;
if (*elemp == NULL)
/* Nothing here, all is removed (or there never was anything). */
return true;
if (!free_slotinfo (&(*elemp)->next))
/* We cannot free the entry. */
return false;
/* That cleared our next pointer for us. */
for (cnt = 0; cnt < (*elemp)->len; ++cnt)
if ((*elemp)->slotinfo[cnt].map != NULL)
/* Still used. */
return false;
/* We can remove the list element. */
free (*elemp);
*elemp = NULL;
return true;
}
void
__dl_libc_freemem (void)
{
struct link_map *l;
struct r_search_path_elem *d;
/* Remove all search directories. */
d = GL(dl_all_dirs);
while (d != GLRO(dl_init_all_dirs))
{
struct r_search_path_elem *old = d;
d = d->next;
free (old);
}
for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
{
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
{
struct libname_list *lnp = l->l_libname->next;
l->l_libname->next = NULL;
/* Remove all additional names added to the objects. */
while (lnp != NULL)
{
struct libname_list *old = lnp;
lnp = lnp->next;
if (! old->dont_free)
free (old);
}
/* Free the initfini dependency list. */
if (l->l_free_initfini)
free (l->l_initfini);
l->l_initfini = NULL;
}
if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
&& (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
// XXX Check whether we need NS-specific initial_searchlist
== GLRO(dl_initial_searchlist).r_nlist))
{
/* All object dynamically loaded by the program are unloaded. Free
the memory allocated for the global scope variable. */
struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
/* Put the old map in. */
GL(dl_ns)[ns]._ns_main_searchlist->r_list
// XXX Check whether we need NS-specific initial_searchlist
= GLRO(dl_initial_searchlist).r_list;
/* Signal that the original map is used. */
GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
/* Now free the old map. */
free (old);
}
}
/* Free the memory allocated for the dtv slotinfo array. We can do
this only if all modules which used this memory are unloaded. */
#ifdef SHARED
if (GL(dl_initial_dtv) == NULL)
/* There was no initial TLS setup, it was set up later when
it used the normal malloc. */
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
else
#endif
/* The first element of the list does not have to be deallocated.
It was allocated in the dynamic linker (i.e., with a different
malloc), and in the static library it's in .bss space. */
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
void *scope_free_list = GL(dl_scope_free_list);
GL(dl_scope_free_list) = NULL;
free (scope_free_list);
}

View file

@ -19,8 +19,109 @@
#include <ldsodefs.h>
#include <dl-find_object.h>
static bool
free_slotinfo (struct dtv_slotinfo_list **elemp)
{
size_t cnt;
if (*elemp == NULL)
/* Nothing here, all is removed (or there never was anything). */
return true;
if (!free_slotinfo (&(*elemp)->next))
/* We cannot free the entry. */
return false;
/* That cleared our next pointer for us. */
for (cnt = 0; cnt < (*elemp)->len; ++cnt)
if ((*elemp)->slotinfo[cnt].map != NULL)
/* Still used. */
return false;
/* We can remove the list element. */
free (*elemp);
*elemp = NULL;
return true;
}
void
__rtld_libc_freeres (void)
{
struct link_map *l;
struct r_search_path_elem *d;
/* Remove all search directories. */
d = GL(dl_all_dirs);
while (d != GLRO(dl_init_all_dirs))
{
struct r_search_path_elem *old = d;
d = d->next;
free (old);
}
for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
{
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
{
struct libname_list *lnp = l->l_libname->next;
l->l_libname->next = NULL;
/* Remove all additional names added to the objects. */
while (lnp != NULL)
{
struct libname_list *old = lnp;
lnp = lnp->next;
if (! old->dont_free)
free (old);
}
/* Free the initfini dependency list. */
if (l->l_free_initfini)
free (l->l_initfini);
l->l_initfini = NULL;
}
if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
&& (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
// XXX Check whether we need NS-specific initial_searchlist
== GLRO(dl_initial_searchlist).r_nlist))
{
/* All object dynamically loaded by the program are unloaded. Free
the memory allocated for the global scope variable. */
struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
/* Put the old map in. */
GL(dl_ns)[ns]._ns_main_searchlist->r_list
// XXX Check whether we need NS-specific initial_searchlist
= GLRO(dl_initial_searchlist).r_list;
/* Signal that the original map is used. */
GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
/* Now free the old map. */
free (old);
}
}
/* Free the memory allocated for the dtv slotinfo array. We can do
this only if all modules which used this memory are unloaded. */
#ifdef SHARED
if (GL(dl_initial_dtv) == NULL)
/* There was no initial TLS setup, it was set up later when
it used the normal malloc. */
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
else
#endif
/* The first element of the list does not have to be deallocated.
It was allocated in the dynamic linker (i.e., with a different
malloc), and in the static library it's in .bss space. */
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
void *scope_free_list = GL(dl_scope_free_list);
GL(dl_scope_free_list) = NULL;
free (scope_free_list);
_dl_find_object_freeres ();
}

View file

@ -1421,10 +1421,8 @@ cannot enable executable stack as shared object requires");
/* When we profile the SONAME might be needed for something else but
loading. Add it right away. */
if (__glibc_unlikely (GLRO(dl_profile) != NULL)
&& l->l_info[DT_SONAME] != NULL)
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val));
if (__glibc_unlikely (GLRO(dl_profile) != NULL) && l_soname (l) != NULL)
add_name_to_object (l, l_soname (l));
#else
/* Audit modules only exist when linking is dynamic so ORIGNAME
cannot be non-NULL. */
@ -1434,9 +1432,7 @@ cannot enable executable stack as shared object requires");
/* If we have newly loaded libc.so, update the namespace
description. */
if (GL(dl_ns)[nsid].libc_map == NULL
&& l->l_info[DT_SONAME] != NULL
&& strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
&& l_soname (l) != NULL && strcmp (l_soname(l), LIBC_SO) == 0)
GL(dl_ns)[nsid].libc_map = l;
/* _dl_close can only eventually undo the module ID assignment (via
@ -1887,24 +1883,14 @@ open_path (const char *name, size_t namelen, int mode,
return -1;
}
/* Map in the shared object file NAME. */
struct link_map *
_dl_map_object (struct link_map *loader, const char *name,
int type, int trace_mode, int mode, Lmid_t nsid)
_dl_lookup_map (Lmid_t nsid, const char *name)
{
int fd;
const char *origname = NULL;
char *realname;
char *name_copy;
struct link_map *l;
struct filebuf fb;
assert (nsid >= 0);
assert (nsid < GL(dl_nns));
/* Look for this name among those already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
for (struct link_map *l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
{
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
@ -1913,19 +1899,12 @@ _dl_map_object (struct link_map *loader, const char *name,
continue;
if (!_dl_name_match_p (name, l))
{
const char *soname;
if (__glibc_likely (l->l_soname_added)
|| l->l_info[DT_SONAME] == NULL)
continue;
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val);
if (strcmp (name, soname) != 0)
if (__glibc_likely (l->l_soname_added) || l_soname (l) == NULL
|| strcmp (name, l_soname (l)) != 0)
continue;
/* We have a match on a new name -- cache it. */
add_name_to_object (l, soname);
add_name_to_object (l, l_soname (l));
l->l_soname_added = 1;
}
@ -1933,6 +1912,22 @@ _dl_map_object (struct link_map *loader, const char *name,
return l;
}
return NULL;
}
/* Map in the shared object file NAME. */
struct link_map *
_dl_map_new_object (struct link_map *loader, const char *name,
int type, int trace_mode, int mode, Lmid_t nsid)
{
int fd;
const char *origname = NULL;
char *realname;
char *name_copy;
struct link_map *l;
struct filebuf fb;
/* Display information if we are debugging. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
&& loader != NULL)
@ -2183,6 +2178,17 @@ _dl_map_object (struct link_map *loader, const char *name,
type, mode, &stack_end, nsid);
}
struct link_map *
_dl_map_object (struct link_map *loader, const char *name,
int type, int trace_mode, int mode, Lmid_t nsid)
{
struct link_map *l = _dl_lookup_map (nsid, name);
if (l != NULL)
return l;
return _dl_map_new_object (loader, name, type, trace_mode, mode, nsid);
}
struct add_path_state
{
bool counting;

View file

@ -18,6 +18,7 @@
<https://www.gnu.org/licenses/>. */
#include <dl-load.h>
#include <setvmaname.h>
/* Map a segment and align it properly. */
@ -182,12 +183,41 @@ _dl_map_segments (struct link_map *l, int fd,
if (zeroend > zeropage)
{
/* Map the remaining zero pages in from the zero fill FD. */
char bssname[ANON_VMA_NAME_MAX_LEN] = " glibc: .bss";
caddr_t mapat;
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
-1, 0);
if (__glibc_unlikely (mapat == MAP_FAILED))
return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
if (__is_decorate_maps_enabled ())
{
if (l->l_name != NULL && *l->l_name != '\0')
{
int i = strlen (bssname), j = 0;
int namelen = strlen (l->l_name);
bssname[i++] = ' ';
if (namelen > sizeof (bssname) - i - 1)
for (j = namelen - 1; j > 0; j--)
if (l->l_name[j - 1] == '/')
break;
for (; l->l_name[j] != '\0' && i < sizeof (bssname) - 1;
i++, j++)
{
char ch = l->l_name[j];
/* Replace non-printable characters and
\, `, $, [ and ]. */
if (ch <= 0x1f || ch >= 0x7f || strchr("\\`$[]", ch))
ch = '!';
bssname[i] = ch;
}
bssname[i] = 0;
}
__set_vma_name ((void*)zeropage, zeroend - zeropage, bssname);
}
}
}

View file

@ -49,8 +49,7 @@ struct dl_open_args
{
const char *file;
int mode;
/* This is the caller of the dlopen() function. */
const void *caller_dlopen;
struct link_map *caller_map; /* Derived from the caller address. */
struct link_map *map;
/* Namespace ID. */
Lmid_t nsid;
@ -493,36 +492,29 @@ call_dl_init (void *closure)
_dl_init (args->map, args->argc, args->argv, args->env);
}
/* Return true if the object does not need any processing beyond the
l_direct_opencount update. Needs to be kept in sync with the logic
in dl_open_worker_begin after the l->l_searchlist.r_list != NULL check.
MODE is the dlopen mode argument. */
static bool
is_already_fully_open (struct link_map *map, int mode)
{
return (map != NULL /* An existing map was found. */
/* dlopen completed initialization of this map. Maps with
l_type == lt_library start out as partially initialized. */
&& map->l_searchlist.r_list != NULL
/* The object is already in the global scope if requested. */
&& (!(mode & RTLD_GLOBAL) || map->l_global)
/* The object is already NODELETE if requested. */
&& (!(mode & RTLD_NODELETE) || map->l_nodelete_active));
}
static void
dl_open_worker_begin (void *a)
{
struct dl_open_args *args = a;
const char *file = args->file;
int mode = args->mode;
struct link_map *call_map = NULL;
/* Determine the caller's map if necessary. This is needed in case
we have a DST, when we don't know the namespace ID we have to put
the new object in, or when the file name has no path in which
case we need to look along the RUNPATH/RPATH of the caller. */
const char *dst = strchr (file, '$');
if (dst != NULL || args->nsid == __LM_ID_CALLER
|| strchr (file, '/') == NULL)
{
const void *caller_dlopen = args->caller_dlopen;
/* We have to find out from which object the caller is calling.
By default we assume this is the main application. */
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
if (l)
call_map = l;
if (args->nsid == __LM_ID_CALLER)
args->nsid = call_map->l_ns;
}
/* The namespace ID is now known. Keep track of whether libc.so was
already loaded, to determine whether it is necessary to call the
@ -538,9 +530,10 @@ dl_open_worker_begin (void *a)
_dl_debug_initialize (0, args->nsid);
/* Load the named object. */
struct link_map *new;
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
struct link_map *new = args->map;
if (new == NULL)
args->map = new = _dl_map_new_object (args->caller_map, file, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
@ -557,7 +550,7 @@ dl_open_worker_begin (void *a)
/* This object is directly loaded. */
++new->l_direct_opencount;
/* It was already open. */
/* It was already open. See is_already_fully_open above. */
if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
{
/* Let the user know about the opencount. */
@ -617,9 +610,7 @@ dl_open_worker_begin (void *a)
Perform partial initialization in this case. This must
come after the symbol versioning initialization in
_dl_check_map_versions. */
if (map->l_info[DT_SONAME] != NULL
&& strcmp (((const char *) D_PTR (map, l_info[DT_STRTAB])
+ map->l_info[DT_SONAME]->d_un.d_val), LD_SO) == 0)
if (l_soname (map) != NULL && strcmp (l_soname (map), LD_SO) == 0)
__rtld_static_init (map);
#endif
}
@ -861,8 +852,6 @@ no more namespaces available for dlmopen()"));
struct dl_open_args args;
args.file = file;
args.mode = mode;
args.caller_dlopen = caller_dlopen;
args.map = NULL;
args.nsid = nsid;
/* args.libc_already_loaded is always assigned by dl_open_worker
(before any explicit/non-local returns). */
@ -870,6 +859,34 @@ no more namespaces available for dlmopen()"));
args.argv = argv;
args.env = env;
/* Determine the caller's map if necessary. This is needed when we
don't know the namespace ID in which we have to put the new object,
in case we have a DST, or when the file name has no path in
which case we need to look along the RUNPATH/RPATH of the caller. */
if (nsid == __LM_ID_CALLER || strchr (file, '$') != NULL
|| strchr (file, '/') == NULL)
{
struct dl_find_object dlfo;
if (_dl_find_object ((void *) caller_dlopen, &dlfo) == 0)
args.caller_map = dlfo.dlfo_link_map;
else
/* By default we assume this is the main application. */
args.caller_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (args.nsid == __LM_ID_CALLER)
args.nsid = args.caller_map->l_ns;
}
else
args.caller_map = NULL;
args.map = _dl_lookup_map (args.nsid, file);
if (is_already_fully_open (args.map, mode))
{
/* We can use the fast path. */
++args.map->l_direct_opencount;
__rtld_lock_unlock_recursive (GL(dl_load_lock));
return args.map;
}
struct dl_exception exception;
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);

View file

@ -51,7 +51,8 @@ _dl_relocate_static_pie (void)
switch (ph->p_type)
{
case PT_LOAD:
if (ph->p_offset == 0)
/* Skip the empty PT_LOAD segment at offset 0. */
if (ph->p_filesz != 0 && ph->p_offset == 0)
file_p_vaddr = ph->p_vaddr;
break;
case PT_DYNAMIC:

View file

@ -35,7 +35,6 @@
#include <dl-machine.h>
#include <libc-lock.h>
#include <dl-cache.h>
#include <dl-procinfo.h>
#include <unsecvars.h>
#include <hp-timing.h>
#include <stackinfo.h>

View file

@ -39,6 +39,12 @@
#include <dl-extra_tls.h>
/* This code is used during early startup when statically linked,
via __libc_setup_tls in csu/libc-tls.c. */
#ifndef SHARED
# include <dl-symbol-redir-ifunc.h>
#endif
/* Surplus static TLS, GLRO(dl_tls_static_surplus), is used for
- IE TLS in libc.so for all dlmopen namespaces except in the initial
@ -560,6 +566,13 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
if (newp == NULL)
oom ();
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
#ifdef SHARED
/* Auditors can trigger a DTV resize event while the full malloc
is not yet in use. Mark the new DTV allocation as the
initial allocation. */
if (!__rtld_malloc_is_complete ())
GL(dl_initial_dtv) = &newp[1];
#endif
}
else
{

View file

@ -22,7 +22,6 @@
#include <unistd.h>
#include "version.h"
#include <dl-procinfo.h>
#include <dl-hwcaps.h>
void

View file

@ -2906,19 +2906,6 @@ enum
#define R_AARCH64_NONE 0 /* No relocation. */
/* ILP32 AArch64 relocs. */
#define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */
#define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */
#define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */
#define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */
#define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */
#define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */
#define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */
#define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */
#define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */
#define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */
/* LP64 AArch64 relocs. */
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
#define R_AARCH64_ABS16 259 /* Direct 16-bit. */

View file

@ -45,7 +45,6 @@
#include <dl-hwcaps.h>
#include <dl-is_dso.h>
#include <dl-procinfo.h>
#ifndef LD_SO_CONF
# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"

View file

@ -35,7 +35,6 @@
#include <unsecvars.h>
#include <dl-cache.h>
#include <dl-osinfo.h>
#include <dl-procinfo.h>
#include <dl-prop.h>
#include <dl-vdso.h>
#include <dl-vdso-setup.h>
@ -1055,13 +1054,9 @@ static void
rtld_chain_load (struct link_map *main_map, char *argv0)
{
/* The dynamic loader run against itself. */
const char *rtld_soname
= ((const char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_val);
if (main_map->l_info[DT_SONAME] != NULL
&& strcmp (rtld_soname,
((const char *) D_PTR (main_map, l_info[DT_STRTAB])
+ main_map->l_info[DT_SONAME]->d_un.d_val)) == 0)
const char *rtld_soname = l_soname (&_dl_rtld_map);
if (l_soname (main_map) != NULL
&& strcmp (rtld_soname, l_soname (main_map)) == 0)
_dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname);
/* With DT_NEEDED dependencies, the executable is dynamically
@ -1632,20 +1627,20 @@ dl_main (const ElfW(Phdr) *phdr,
/* If the current libname is different from the SONAME, add the
latter as well. */
if (_dl_rtld_map.l_info[DT_SONAME] != NULL
&& strcmp (_dl_rtld_map.l_libname->name,
(const char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_val) != 0)
{
static struct libname_list newname;
newname.name = ((char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_ptr);
newname.next = NULL;
newname.dont_free = 1;
{
const char *soname = l_soname (&_dl_rtld_map);
if (soname != NULL
&& strcmp (_dl_rtld_map.l_libname->name, soname) != 0)
{
static struct libname_list newname;
newname.name = soname;
newname.next = NULL;
newname.dont_free = 1;
assert (_dl_rtld_map.l_libname->next == NULL);
_dl_rtld_map.l_libname->next = &newname;
}
assert (_dl_rtld_map.l_libname->next == NULL);
_dl_rtld_map.l_libname->next = &newname;
}
}
/* The ld.so must be relocated since otherwise loading audit modules
will fail since they reuse the very same ld.so. */
assert (_dl_rtld_map.l_relocated);
@ -1658,10 +1653,8 @@ dl_main (const ElfW(Phdr) *phdr,
/* If the main map is libc.so, update the base namespace to
refer to this map. If libc.so is loaded later, this happens
in _dl_map_object_from_fd. */
if (main_map->l_info[DT_SONAME] != NULL
&& (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB])
+ main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO)
== 0))
if (l_soname (main_map) != NULL
&& strcmp (l_soname (main_map), LIBC_SO) == 0)
GL(dl_ns)[LM_ID_BASE].libc_map = main_map;
/* Set up our cache of pointers into the hash table. */

View file

@ -76,13 +76,14 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
/* Now that we have the info handy, use the DSO image's soname
so this object can be looked up by name. */
if (l->l_info[DT_SONAME] != NULL)
{
char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val);
l->l_libname->name = dsoname;
l->l_name = dsoname;
}
{
const char *dsoname = l_soname (l);
if (dsoname != NULL)
{
l->l_libname->name = dsoname;
l->l_name = (char *) dsoname;
}
}
/* Add the vDSO to the object list. */
_dl_add_to_namespace_list (l, LM_ID_BASE);

View file

@ -530,10 +530,7 @@ load_shobj (const char *name)
printf ("string table: %p\n", result->dynstrtab);
/* Determine the soname. */
if (map->l_info[DT_SONAME] == NULL)
result->soname = NULL;
else
result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
result->soname = l_soname (map);
if (do_test && result->soname != NULL)
printf ("soname: %s\n", result->soname);

View file

@ -0,0 +1,46 @@
/* Loading TLS-using modules from auditors (bug 32412). Main program.
Copyright (C) 2021-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <support/xdlfcn.h>
#include <stdio.h>
static int
do_test (void)
{
puts ("info: start of main program");
/* Load TLS-using modules, to trigger DTV resizing. The dynamic
linker will load them again (requiring their own TLS) because the
dlopen calls from the auditor were in the auditing namespace. */
for (int i = 1; i <= 19; ++i)
{
char dso[30];
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
char sym[30];
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
void *handle = xdlopen (dso, RTLD_LAZY);
int (*func) (void) = xdlsym (handle, sym);
/* Trigger TLS allocation. */
func ();
}
return 0;
}
#include <support/test-driver.c>

View file

@ -0,0 +1,59 @@
/* Loading TLS-using modules from auditors (bug 32412). Audit module.
Copyright (C) 2021-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <link.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
unsigned int
la_version (unsigned int version)
{
/* Open some modules, to trigger DTV resizing before the switch to
the main malloc. */
for (int i = 1; i <= 19; ++i)
{
char dso[30];
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
char sym[30];
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
void *handle = dlopen (dso, RTLD_LAZY);
if (handle == NULL)
{
printf ("error: dlmopen from auditor: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
int (*func) (void) = dlsym (handle, sym);
if (func == NULL)
{
printf ("error: dlsym from auditor: %s\n", dlerror ());
fflush (stdout);
_exit (1);
}
/* Trigger TLS allocation. */
func ();
}
puts ("info: TLS-using modules loaded from auditor");
fflush (stdout);
return LAV_CURRENT;
}

19
elf/tst-pie-bss-static.c Normal file
View file

@ -0,0 +1,19 @@
/* Test static PIE with an empty PT_LOAD segment at offset 0.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "tst-pie-bss.c"

View file

@ -1,5 +1,5 @@
/* x86 version of processor capability information handling macros.
Copyright (C) 2017-2025 Free Software Foundation, Inc.
/* Test PIE with an empty PT_LOAD segment at offset 0.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -16,11 +16,15 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _DL_PROCINFO_H
#define _DL_PROCINFO_H 1
#include <ldsodefs.h>
#include <dl-hwcap.h>
#include <stdio.h>
#define _DL_HWCAP_COUNT HWCAP_COUNT
char bss[0xb5dce8] __attribute__ ((aligned (65536)));
#endif /* dl-procinfo.h */
static int
do_test (void)
{
printf ("Hello\n");
return 0;
}
#include <support/test-driver.c>

View file

@ -25,21 +25,12 @@ SYSDEPS := lockfile
LCLHDRS :=
libpthread-routines := \
pt-barrier-destroy \
pt-barrier-init \
pt-barrier-wait \
pt-barrier \
pt-barrierattr-destroy \
pt-barrierattr-init \
pt-barrierattr-getpshared \
pt-barrierattr-setpshared \
pt-destroy-specific \
pt-init-specific \
pt-key-create \
pt-key-delete \
pt-getspecific \
pt-setspecific \
pt-once \
pt-alloc \
pt-create \
pt-getattr \
@ -50,34 +41,9 @@ libpthread-routines := \
pt-join \
pt-spin-inlines \
pt-cleanup \
pt-setcancelstate \
pt-setcanceltype \
pt-testcancel \
pt-cancel \
pt-mutex-init \
pt-mutex-destroy \
pt-mutex-lock \
pt-mutex-trylock \
pt-mutex-timedlock \
pt-mutex-unlock \
pt-mutex-transfer-np \
pt-mutex-getprioceiling \
pt-mutex-setprioceiling \
pt-mutex-consistent \
pt-rwlock-attr \
pt-rwlockattr-init \
pt-rwlockattr-destroy \
pt-rwlockattr-getpshared \
pt-rwlockattr-setpshared \
pt-rwlock-init \
pt-rwlock-destroy \
pt-rwlock-rdlock \
pt-rwlock-tryrdlock \
pt-rwlock-trywrlock \
pt-rwlock-wrlock \
pt-rwlock-timedrdlock \
pt-rwlock-timedwrlock \
pt-rwlock-unlock \
pt-hurd-cond-wait \
pt-hurd-cond-timedwait \
pt-stack-alloc \
@ -172,6 +138,14 @@ routines := \
pt-attr-setstack \
pt-attr-setstackaddr \
pt-attr-setstacksize \
pt-barrier \
pt-barrier-destroy \
pt-barrier-init \
pt-barrier-wait \
pt-barrierattr-destroy \
pt-barrierattr-getpshared \
pt-barrierattr-init \
pt-barrierattr-setpshared \
pt-block \
pt-block-intr \
pt-cond \
@ -189,6 +163,15 @@ routines := \
pt-condattr-setpshared \
pt-getschedparam \
pt-mutex-checklocked \
pt-mutex-consistent \
pt-mutex-destroy \
pt-mutex-getprioceiling \
pt-mutex-init \
pt-mutex-lock \
pt-mutex-setprioceiling \
pt-mutex-timedlock \
pt-mutex-trylock \
pt-mutex-unlock \
pt-mutexattr-destroy \
pt-mutexattr-getprioceiling \
pt-mutexattr-getprotocol \
@ -202,8 +185,25 @@ routines := \
pt-mutexattr-setrobust \
pt-mutexattr-settype \
pt-nthreads \
pt-once \
pt-pthread_self \
pt-rwlock-attr \
pt-rwlock-destroy \
pt-rwlock-init \
pt-rwlock-rdlock \
pt-rwlock-timedrdlock \
pt-rwlock-timedwrlock \
pt-rwlock-tryrdlock \
pt-rwlock-trywrlock \
pt-rwlock-unlock \
pt-rwlock-wrlock \
pt-rwlockattr-destroy \
pt-rwlockattr-getpshared \
pt-rwlockattr-init \
pt-rwlockattr-setpshared \
pt-self pt-equal \
pt-setcancelstate \
pt-setcanceltype \
pt-setschedparam \
pt-sigmask \
pt-sigstate \

View file

@ -26,6 +26,13 @@ libc {
pthread_attr_setscope;
pthread_attr_setschedparam;
pthread_attr_init;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_cond_broadcast;
pthread_cond_destroy;
pthread_cond_init;
@ -38,6 +45,14 @@ libc {
pthread_condattr_getpshared;
pthread_condattr_setclock;
pthread_condattr_setpshared;
pthread_mutex_destroy;
pthread_mutex_getprioceiling;
pthread_mutex_init;
pthread_mutex_lock;
pthread_mutex_setprioceiling;
pthread_mutex_timedlock;
pthread_mutex_trylock;
pthread_mutex_unlock;
pthread_mutexattr_destroy;
pthread_mutexattr_getprioceiling;
pthread_mutexattr_getprotocol;
@ -48,6 +63,22 @@ libc {
pthread_mutexattr_setprotocol;
pthread_mutexattr_setpshared;
pthread_mutexattr_settype;
pthread_once;
pthread_rwlock_destroy;
pthread_rwlock_init;
pthread_rwlock_rdlock;
pthread_rwlock_timedrdlock;
pthread_rwlock_timedwrlock;
pthread_rwlock_tryrdlock;
pthread_rwlock_trywrlock;
pthread_rwlock_unlock;
pthread_rwlock_wrlock;
pthread_rwlockattr_destroy;
pthread_rwlockattr_getpshared;
pthread_rwlockattr_init;
pthread_rwlockattr_setpshared;
pthread_setcancelstate;
pthread_setcanceltype;
pthread_sigmask;
}
@ -65,7 +96,7 @@ libc {
pthread_equal;
pthread_exit; pthread_getschedparam; pthread_setschedparam;
pthread_mutex_destroy; pthread_mutex_init;
pthread_mutex_lock; pthread_mutex_trylock; pthread_mutex_unlock;
pthread_mutex_lock; pthread_mutex_unlock;
pthread_self; pthread_setcancelstate; pthread_setcanceltype;
__pthread_get_cleanup_stack;
}
@ -79,8 +110,14 @@ libc {
pthread_cond_clockwait;
pthread_mutex_clocklock;
pthread_mutex_consistent; pthread_mutex_consistent_np;
pthread_mutexattr_getrobust; pthread_mutexattr_getrobust_np;
pthread_mutexattr_setrobust; pthread_mutexattr_setrobust_np;
pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
}
GLIBC_2.41 {
@ -109,6 +146,35 @@ libc {
pthread_sigmask;
}
GLIBC_2.42 {
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_mutex_consistent; pthread_mutex_consistent_np;
pthread_mutex_getprioceiling;
pthread_mutex_setprioceiling;
pthread_rwlock_destroy;
pthread_mutex_trylock;
pthread_once;
pthread_rwlock_clockrdlock;
pthread_rwlock_clockwrlock;
pthread_rwlock_init;
pthread_rwlock_rdlock;
pthread_rwlock_timedrdlock;
pthread_rwlock_timedwrlock;
pthread_rwlock_wrlock;
pthread_rwlock_tryrdlock;
pthread_rwlock_trywrlock;
pthread_rwlock_unlock;
pthread_rwlockattr_destroy;
pthread_rwlockattr_getpshared;
pthread_rwlockattr_init;
pthread_rwlockattr_setpshared;
}
GLIBC_PRIVATE {
__libc_alloca_cutoff;
@ -127,6 +193,7 @@ libc {
__pthread_attr_setstacksize;
__pthread_attr_setstackaddr;
__pthread_attr_setstack;
__pthread_setcancelstate;
__pthread_cond_broadcast;
__pthread_cond_destroy;
__pthread_cond_init;
@ -137,9 +204,16 @@ libc {
__pthread_condattr_init;
__pthread_default_condattr;
__pthread_mutex_checklocked;
__pthread_mutex_destroy;
__pthread_mutex_init;
__pthread_mutex_lock;
__pthread_mutex_timedlock;
__pthread_mutex_trylock;
__pthread_mutex_unlock;
__pthread_mutexattr_destroy;
__pthread_mutexattr_init;
__pthread_mutexattr_settype;
__pthread_once;
__pthread_sigstate;
__pthread_sigstate_destroy;
__pthread_sigmask;
@ -174,10 +248,6 @@ libpthread {
pthread_atfork;
pthread_barrier_destroy; pthread_barrier_init; pthread_barrier_wait;
pthread_barrierattr_destroy; pthread_barrierattr_getpshared;
pthread_barrierattr_init; pthread_barrierattr_setpshared;
pthread_cancel;
pthread_create; pthread_detach; pthread_exit;
@ -195,22 +265,8 @@ libpthread {
pthread_kill;
__pthread_kill;
pthread_mutex_destroy; pthread_mutex_getprioceiling;
pthread_mutex_init; pthread_mutex_lock; pthread_mutex_setprioceiling;
pthread_mutex_timedlock; pthread_mutex_transfer_np;
pthread_mutex_trylock; pthread_mutex_unlock;
pthread_mutex_transfer_np;
pthread_once;
pthread_rwlock_destroy; pthread_rwlock_init; pthread_rwlock_rdlock;
pthread_rwlock_timedrdlock; pthread_rwlock_timedwrlock;
pthread_rwlock_tryrdlock; pthread_rwlock_trywrlock;
pthread_rwlock_unlock; pthread_rwlock_wrlock;
pthread_rwlockattr_destroy; pthread_rwlockattr_getpshared;
pthread_rwlockattr_init; pthread_rwlockattr_setpshared;
pthread_setcancelstate; pthread_setcanceltype;
pthread_setconcurrency;
pthread_setschedprio; pthread_setspecific;
@ -239,11 +295,6 @@ libpthread {
cnd_broadcast; cnd_destroy; cnd_init; cnd_signal; cnd_timedwait; cnd_wait;
tss_create; tss_delete; tss_get; tss_set;
pthread_mutex_consistent; pthread_mutex_consistent_np;
pthread_mutex_clocklock;
pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
pthread_tryjoin_np; pthread_timedjoin_np; pthread_clockjoin_np;
sem_clockwait;
@ -267,14 +318,7 @@ libpthread {
__pthread_getspecific;
__pthread_setspecific;
__pthread_getattr_np;
__pthread_mutex_init;
__pthread_mutex_destroy;
__pthread_mutex_timedlock;
__pthread_enable_asynccancel;
__pthread_disable_asynccancel;
__pthread_mutex_lock; __pthread_mutex_trylock; __pthread_mutex_unlock;
_pthread_mutex_lock; _pthread_mutex_trylock; _pthread_mutex_unlock;
_pthread_rwlock_destroy; _pthread_rwlock_init;
}
}

View file

@ -58,21 +58,5 @@ FORWARD_NORETURN (__pthread_exit, void, (void *retval), (retval),
exit (EXIT_SUCCESS))
strong_alias (__pthread_exit, pthread_exit);
FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
FORWARD (pthread_mutex_init,
(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
(mutex, mutexattr), 0)
FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
FORWARD (__pthread_setcancelstate, (int state, int *oldstate),
(state, oldstate), 0)
strong_alias (__pthread_setcancelstate, pthread_setcancelstate);
FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
FORWARD2 (__pthread_get_cleanup_stack, struct __pthread_cancelation_handler **,
(void), (), return &__pthread_cleanup_stack);

View file

@ -203,10 +203,7 @@ __pthread_create_internal (struct __pthread **thread,
creating thread. The set of signals pending for the new thread
shall be empty." If the current thread is not a pthread then we
just inherit the process' sigmask. */
if (GL (dl_pthread_num_threads) == 1)
err = __sigprocmask (0, 0, &pthread->init_sigset);
else
err = __pthread_sigstate (_pthread_self (), 0, 0, &pthread->init_sigset, 0);
err = __pthread_sigmask (0, 0, &pthread->init_sigset);
assert_perror (err);
if (start_routine)

View file

@ -28,18 +28,8 @@
#if IS_IN (libpthread)
static const struct pthread_functions pthread_functions = {
.ptr___pthread_exit = __pthread_exit,
.ptr_pthread_mutex_destroy = __pthread_mutex_destroy,
.ptr_pthread_mutex_init = __pthread_mutex_init,
.ptr_pthread_mutex_lock = __pthread_mutex_lock,
.ptr_pthread_mutex_trylock = __pthread_mutex_trylock,
.ptr_pthread_mutex_unlock = __pthread_mutex_unlock,
.ptr___pthread_setcancelstate = __pthread_setcancelstate,
.ptr_pthread_setcanceltype = __pthread_setcanceltype,
.ptr___pthread_get_cleanup_stack = __pthread_get_cleanup_stack,
.ptr_pthread_once = __pthread_once,
.ptr_pthread_rwlock_rdlock = __pthread_rwlock_rdlock,
.ptr_pthread_rwlock_wrlock = __pthread_rwlock_wrlock,
.ptr_pthread_rwlock_unlock = __pthread_rwlock_unlock,
.ptr___pthread_key_create = __pthread_key_create,
.ptr___pthread_getspecific = __pthread_getspecific,
.ptr___pthread_setspecific = __pthread_setspecific,

View file

@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <shlib-compat.h>
#include <pt-internal.h>
int
@ -42,5 +42,9 @@ __pthread_setcancelstate (int state, int *oldstate)
return 0;
}
libc_hidden_def (__pthread_setcancelstate)
versioned_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_21);
weak_alias (__pthread_setcancelstate, pthread_setcancelstate);
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
compat_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_12);
#endif

View file

@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <shlib-compat.h>
#include <pt-internal.h>
int
@ -42,5 +42,9 @@ __pthread_setcanceltype (int type, int *oldtype)
return 0;
}
libc_hidden_def (__pthread_setcanceltype)
versioned_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_21);
weak_alias (__pthread_setcanceltype, pthread_setcanceltype);
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
compat_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_12);
#endif

View file

@ -19,15 +19,14 @@
#include <pthread.h>
#include <signal.h>
#include <shlib-compat.h>
#include <hurd/signal.h>
#include <pt-internal.h>
int
__pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
{
struct __pthread *self = _pthread_self ();
/* Do not clear SELF's pending signals. */
return __pthread_sigstate (self, how, set, oset, 0);
return __sigthreadmask (_hurd_self_sigstate (), how, set, oset, 0);
}
libc_hidden_def (__pthread_sigmask)
versioned_symbol (libc, __pthread_sigmask, pthread_sigmask, GLIBC_2_41);

View file

@ -131,6 +131,7 @@ sig = \
longjmp-ts \
preempt-sig \
siginfo \
sigthreadmask \
sigunwind \
thread-cancel \
thread-self \

View file

@ -138,7 +138,7 @@ error_t __hurd_file_name_lookup_retry (error_t (*use_init_port)
string_t retry_name,
mach_port_t *result),
enum retry_type doretry,
char retryname[1024],
string_t retryname,
int flags, mode_t mode,
file_t *result);
error_t hurd_file_name_lookup_retry (error_t (*use_init_port)
@ -152,7 +152,7 @@ error_t hurd_file_name_lookup_retry (error_t (*use_init_port)
string_t retry_name,
mach_port_t *result),
enum retry_type doretry,
char retryname[1024],
string_t retryname,
int flags, mode_t mode,
file_t *result);

View file

@ -99,6 +99,7 @@ __lll_abstimed_lock (void *ptr,
return ETIMEDOUT;
}
}
libc_hidden_def (__lll_abstimed_lock)
/* Robust locks. */
@ -157,6 +158,7 @@ __lll_robust_lock (void *ptr, int flags)
}
}
}
libc_hidden_def (__lll_robust_lock)
int
__lll_robust_abstimed_lock (void *ptr,
@ -206,6 +208,7 @@ __lll_robust_abstimed_lock (void *ptr,
}
}
}
libc_hidden_def (__lll_robust_abstimed_lock)
int
__lll_robust_trylock (void *ptr)
@ -225,6 +228,7 @@ __lll_robust_trylock (void *ptr)
return EBUSY;
}
libc_hidden_def (__lll_robust_trylock)
void
__lll_robust_unlock (void *ptr, int flags)
@ -241,3 +245,5 @@ __lll_robust_unlock (void *ptr, int flags)
break;
}
}
libc_hidden_def (__lll_robust_unlock)

View file

@ -68,23 +68,27 @@ extern int __lll_abstimed_xwait (void *__ptr, int __lo, int __hi,
using clock CLK. */
extern int __lll_abstimed_lock (void *__ptr,
const struct timespec *__tsp, int __flags, int __clk);
libc_hidden_proto (__lll_abstimed_lock)
/* Acquire the lock at PTR, but return with an error if
the process containing the owner thread dies. */
extern int __lll_robust_lock (void *__ptr, int __flags);
#define lll_robust_lock(var, flags) \
__lll_robust_lock (&(var), flags)
libc_hidden_proto (__lll_robust_lock)
/* Same as '__lll_robust_lock', but only block until TSP
elapses, using clock CLK. */
extern int __lll_robust_abstimed_lock (void *__ptr,
const struct timespec *__tsp, int __flags, int __clk);
libc_hidden_proto (__lll_robust_abstimed_lock)
/* Same as '__lll_robust_lock', but return with an error
if the lock cannot be acquired without blocking. */
extern int __lll_robust_trylock (void *__ptr);
#define lll_robust_trylock(var) \
__lll_robust_trylock (&(var))
libc_hidden_proto (__lll_robust_trylock)
/* Wake one or more threads waiting on address PTR,
setting its value to VAL before doing so. */
@ -96,6 +100,7 @@ extern int __lll_robust_trylock (void *__ptr);
extern void __lll_robust_unlock (void *__ptr, int __flags);
#define lll_robust_unlock(var, flags) \
__lll_robust_unlock (&(var), flags)
libc_hidden_proto (__lll_robust_unlock)
/* Rearrange threads waiting on address SRC to instead wait on
DST, waking one of them if WAIT_ONE is non-zero. */

View file

@ -51,7 +51,7 @@ __hurd_file_name_lookup (error_t (*use_init_port)
{
error_t err;
enum retry_type doretry;
char retryname[1024]; /* XXX string_t LOSES! */
string_t retryname;
int startport;
error_t lookup_op (mach_port_t startdir)

View file

@ -1611,28 +1611,53 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
static void
reauth_proc (mach_port_t new)
{
mach_port_t ref, ignore;
error_t err;
mach_port_t ref, newproc;
ref = __mach_reply_port ();
if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
err = HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
__proc_reauthenticate (port, ref,
MACH_MSG_TYPE_MAKE_SEND)
|| __auth_user_authenticate (new, ref,
MACH_MSG_TYPE_MAKE_SEND,
&ignore))
&& ignore != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), ignore);
__mach_port_destroy (__mach_task_self (), ref);
MACH_MSG_TYPE_MAKE_SEND));
if (err)
{
__mach_port_destroy (__mach_task_self (), ref);
return;
}
/* Set the owner of the process here too. */
__mutex_lock (&_hurd_id.lock);
if (!_hurd_check_ids ())
HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
__proc_setowner (port,
(_hurd_id.gen.nuids
? _hurd_id.gen.uids[0] : 0),
!_hurd_id.gen.nuids));
__mutex_unlock (&_hurd_id.lock);
err = __auth_user_authenticate (new, ref,
MACH_MSG_TYPE_MAKE_SEND,
&newproc);
__mach_port_destroy (__mach_task_self (), ref);
if (err)
return;
if (newproc == MACH_PORT_NULL)
{
/* Old versions of the proc server did not recreate the process
port when reauthenticating, and passed MACH_PORT_NULL through
the auth server. That must be what we're dealing with. */
/* Set the owner of the process here too. */
__mutex_lock (&_hurd_id.lock);
if (!_hurd_check_ids ())
HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
__proc_setowner (port,
(_hurd_id.gen.nuids
? _hurd_id.gen.uids[0] : 0),
!_hurd_id.gen.nuids));
__mutex_unlock (&_hurd_id.lock);
return;
}
err = __proc_reauthenticate_complete (newproc);
if (err)
{
__mach_port_deallocate (__mach_task_self (), newproc);
return;
}
_hurd_port_set (&_hurd_ports[INIT_PORT_PROC], newproc);
(void) &reauth_proc; /* Silence compiler warning. */
}

View file

@ -40,7 +40,7 @@ __file_name_lookup_at (int fd, int at_flags,
if (empty != 0 && file_name[0] == '\0')
{
enum retry_type doretry;
char retryname[1024]; /* XXX string_t LOSES! */
string_t retryname;
err = HURD_DPORT_USE (fd, __dir_lookup (port, "", flags, mode,
&doretry, retryname,

View file

@ -53,7 +53,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
retry_type *do_retry, string_t retry_name,
mach_port_t *result),
enum retry_type doretry,
char retryname[1024],
string_t retryname,
int flags, mode_t mode,
file_t *result)
{

View file

@ -4,8 +4,7 @@
#include <link.h> /* For ElfW. */
#include <stdbool.h>
extern __typeof (_dl_find_object) __dl_find_object;
hidden_proto (__dl_find_object)
rtld_hidden_proto (_dl_find_object)
/* Internally used flag. */
#define __RTLD_DLOPEN 0x80000000

View file

@ -38,7 +38,6 @@
Each free routines must be explicit listed below. */
/* From libc.so. */
extern void __dl_libc_freemem (void) attribute_hidden;
extern void __hdestroy (void) attribute_hidden;
extern void __gconv_cache_freemem (void) attribute_hidden;
extern void __gconv_conf_freemem (void) attribute_hidden;

View file

@ -69,6 +69,8 @@ again:
if (*cp == 'x' || *cp == 'X')
digit = 0, base = 16, cp++;
while ((c = *cp) != 0) {
if (val > 0xff)
return (INADDR_NONE);
if (isdigit(c)) {
if (base == 8 && (c == '8' || c == '9'))
return (INADDR_NONE);

View file

@ -32,6 +32,7 @@
#endif
#include <bits/types.h>
#include <bits/wordsize.h>
struct _IO_FILE;
struct _IO_marker;
@ -97,8 +98,15 @@ struct _IO_FILE_complete
void *_freeres_buf;
struct _IO_FILE **_prevchain;
int _mode;
#if __WORDSIZE == 64
int _unused3;
#endif
__uint64_t _total_written;
#if __WORDSIZE == 32
int _unused3;
#endif
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 5 * sizeof (void *)];
char _unused2[12 * sizeof (int) - 5 * sizeof (void *)];
};
/* These macros are used by bits/stdio.h and internal headers. */

View file

@ -127,15 +127,48 @@ _IO_new_file_init (struct _IO_FILE_plus *fp)
int
_IO_new_file_close_it (FILE *fp)
{
int write_status;
int flush_status = 0;
if (!_IO_file_is_open (fp))
return EOF;
if ((fp->_flags & _IO_NO_WRITES) == 0
&& (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
write_status = _IO_do_flush (fp);
else
write_status = 0;
flush_status = _IO_do_flush (fp);
else if (fp->_fileno >= 0
/* If this is the active handle, we must seek the
underlying open file description (possibly shared with
other file descriptors that remain open) to the correct
offset. But if this stream is in a state such that some
other handle might have become the active handle, then
(a) at the time it entered that state, the underlying
open file description had the correct offset, and (b)
seeking the underlying open file description, even to
its newly determined current offset, is not safe because
it can race with operations on a different active
handle. So check here for cases where it is necessary
to seek, while avoiding seeking in cases where it is
unsafe to do so. */
&& (_IO_in_backup (fp)
|| (fp->_mode <= 0 && fp->_IO_read_ptr < fp->_IO_read_end)
|| (_IO_vtable_offset (fp) == 0
&& fp->_mode > 0 && (fp->_wide_data->_IO_read_ptr
< fp->_wide_data->_IO_read_end))))
{
off64_t o = _IO_SEEKOFF (fp, 0, _IO_seek_cur, 0);
if (o == EOF)
{
if (errno != ESPIPE)
flush_status = EOF;
}
else
{
if (_IO_in_backup (fp))
o -= fp->_IO_save_end - fp->_IO_save_base;
flush_status = (_IO_SYSSEEK (fp, o, SEEK_SET) < 0 && errno != ESPIPE
? EOF
: 0);
}
}
_IO_unsave_markers (fp);
@ -160,7 +193,7 @@ _IO_new_file_close_it (FILE *fp)
fp->_fileno = -1;
fp->_offset = _IO_pos_BAD;
return close_status ? close_status : write_status;
return close_status ? close_status : flush_status;
}
libc_hidden_ver (_IO_new_file_close_it, _IO_file_close_it)
@ -799,6 +832,11 @@ _IO_new_file_sync (FILE *fp)
if (fp->_IO_write_ptr > fp->_IO_write_base)
if (_IO_do_flush(fp)) return EOF;
delta = fp->_IO_read_ptr - fp->_IO_read_end;
if (_IO_in_backup (fp))
{
_IO_switch_to_main_get_area (fp);
delta += fp->_IO_read_ptr - fp->_IO_read_end;
}
if (delta != 0)
{
off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
@ -820,17 +858,21 @@ libc_hidden_ver (_IO_new_file_sync, _IO_file_sync)
int
_IO_file_sync_mmap (FILE *fp)
{
off64_t o = fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
if (fp->_IO_read_ptr != fp->_IO_read_end)
{
if (__lseek64 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base,
SEEK_SET)
!= fp->_IO_read_ptr - fp->_IO_buf_base)
if (_IO_in_backup (fp))
{
_IO_switch_to_main_get_area (fp);
o -= fp->_IO_read_end - fp->_IO_read_base;
}
if (__lseek64 (fp->_fileno, o, SEEK_SET) != o)
{
fp->_flags |= _IO_ERR_SEEN;
return EOF;
}
}
fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
fp->_offset = o;
fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
return 0;
}
@ -1068,11 +1110,18 @@ _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode)
if (mode == 0)
return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
if (_IO_in_backup (fp))
{
if (dir == _IO_seek_cur)
offset += fp->_IO_read_ptr - fp->_IO_read_end;
_IO_switch_to_main_get_area (fp);
}
switch (dir)
{
case _IO_seek_cur:
/* Adjust for read-ahead (bytes is buffer). */
offset += fp->_IO_read_ptr - fp->_IO_read_base;
offset += fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
break;
case _IO_seek_set:
break;
@ -1185,6 +1234,7 @@ _IO_new_file_write (FILE *f, const void *data, ssize_t n)
f->_flags |= _IO_ERR_SEEN;
break;
}
f->_total_written += count;
to_do -= count;
data = (void *) ((char *) data + count);
}

View file

@ -611,6 +611,7 @@ _IO_no_init (FILE *fp, int flags, int orientation,
stream. */
fp->_wide_data = (struct _IO_wide_data *) -1L;
fp->_freeres_list = NULL;
fp->_total_written = 0;
}
int
@ -730,6 +731,13 @@ _IO_flush_all (void)
)
&& _IO_OVERFLOW (fp, EOF) == EOF)
result = EOF;
if (_IO_fileno (fp) >= 0
&& ((fp->_mode <= 0 && fp->_IO_read_ptr < fp->_IO_read_end)
|| (_IO_vtable_offset (fp) == 0
&& fp->_mode > 0 && (fp->_wide_data->_IO_read_ptr
< fp->_wide_data->_IO_read_end)))
&& _IO_SYNC (fp) != 0)
result = EOF;
_IO_funlockfile (fp);
run_fp = NULL;

View file

@ -36,13 +36,42 @@ _IO_fwrite (const void *buf, size_t size, size_t count, FILE *fp)
return 0;
_IO_acquire_lock (fp);
if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1)
written = _IO_sputn (fp, (const char *) buf, request);
{
/* Compute actually written bytes plus pending buffer
contents. */
uint64_t original_total_written
= fp->_total_written + (fp->_IO_write_ptr - fp->_IO_write_base);
written = _IO_sputn (fp, (const char *) buf, request);
if (written == EOF)
{
/* An error happened and we need to find the appropriate return
value. There 3 possible scenarios:
1. If the number of bytes written is between 0..[buffer content],
we need to return 0 because none of the bytes from this
request have been written;
2. If the number of bytes written is between
[buffer content]+1..request-1, that means we managed to write
data requested in this fwrite call;
3. We might have written all the requested data and got an error
anyway. We can't return success, which means we still have to
return less than request. */
if (fp->_total_written > original_total_written)
{
written = fp->_total_written - original_total_written;
/* If everything was reported as written and somehow an
error occurred afterwards, avoid reporting success. */
if (written == request)
--written;
}
else
/* Only already-pending buffer contents was written. */
written = 0;
}
}
_IO_release_lock (fp);
/* We have written all of the input in case the return value indicates
this or EOF is returned. The latter is a special case where we
simply did not manage to flush the buffer. But the data is in the
buffer and therefore written as far as fwrite is concerned. */
if (written == request || written == EOF)
this. */
if (written == request)
return count;
else
return written / size;

View file

@ -604,9 +604,6 @@ extern int fgetc_unlocked (FILE *__stream) __nonnull ((1));
/* Write a character to STREAM.
These functions are possible cancellation points and therefore not
marked with __THROW.
These functions is a possible cancellation point and therefore not
marked with __THROW. */
extern int fputc (int __c, FILE *__stream) __nonnull ((2));
extern int putc (int __c, FILE *__stream) __nonnull ((2));

View file

@ -6,6 +6,14 @@
vm_size_t
__mig_strncpy (char *dst, const char *src, vm_size_t len)
{
return __stpncpy (dst, src, len) - dst;
if (len == 0)
return 0;
char *end = __stpncpy (dst, src, len - 1);
vm_size_t ret = end - dst;
/* Null terminate the string. */
if (ret == len - 1)
*end = '\0';
return ret;
}
weak_alias (__mig_strncpy, mig_strncpy)

View file

@ -4005,6 +4005,9 @@ _int_malloc (mstate av, size_t bytes)
{
if (__glibc_unlikely (misaligned_chunk (tc_victim)))
malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
size_t victim_tc_idx = csize2tidx (chunksize (tc_victim));
if (__glibc_unlikely (tc_idx != victim_tc_idx))
malloc_printerr ("malloc(): chunk size mismatch in fastbin");
if (SINGLE_THREAD_P)
*fb = REVEAL_PTR (tc_victim->fd);
else
@ -4241,6 +4244,9 @@ _int_malloc (mstate av, size_t bytes)
fwd = bck;
bck = bck->bk;
if (__glibc_unlikely (fwd->fd->bk_nextsize->fd_nextsize != fwd->fd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
victim->fd_nextsize = fwd->fd;
victim->bk_nextsize = fwd->fd->bk_nextsize;
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;

View file

@ -28,7 +28,6 @@
# pragma weak __nss_module_freeres
# pragma weak __nss_action_freeres
# pragma weak __nss_database_freeres
# pragma weak __dl_libc_freemem
# pragma weak __hdestroy
# pragma weak __gconv_cache_freemem
# pragma weak __gconv_conf_freemem
@ -136,7 +135,6 @@ __libc_freeres (void)
_IO_cleanup ();
/* We run the resource freeing after IO cleanup. */
call_function_static_weak (__dl_libc_freemem);
call_function_static_weak (__hdestroy);
call_function_static_weak (__gconv_cache_freemem);
call_function_static_weak (__gconv_conf_freemem);

View file

@ -966,13 +966,25 @@ functionality is available on commercial systems.
@Theglibc{} includes by reference the Linux man-pages
@value{man_pages_version} documentation to document the listed
syscalls for the Linux kernel. For reference purposes only the latest
syscalls for the Linux kernel. For reference purposes only, the latest
@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project}
documentation can be accessed from the
@uref{https://www.kernel.org,Linux kernel} website. Where the syscall
has more specific documentation in this manual that more specific
documentation is considered authoritative.
Throughout this manual, when we refer to a man page, for example:
@quotation
@manpageurl{sendmsg,2}
@end quotation
@noindent
we are referring primarily to the specific version noted above (the
``normative'' version), typically accessed by running (for example)
@code{man 2 sendmsg} on a system with that version installed. For
convenience, we will also link to the online latest copy of the man
pages, but keep in mind that version will almost always be newer than,
and thus different than, the normative version noted above.
Additional details on the Linux system call interface can be found in
@xref{System Calls}.

View file

@ -46,71 +46,6 @@ by @theglibc{}.
@end deftypefun
@subsection POSIX Semaphores
@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@c Does not atomically update sem_t therefore AC-unsafe
@c because it can leave sem_t partially initialized.
@end deftypefun
@deftypefun int sem_destroy (sem_t *@var{sem})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@c Function does nothing and is therefore always safe.
@end deftypefun
@deftypefun {sem_t *} sem_open (const char *@var{name}, int @var{oflag}, ...)
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acuinit{}}}
@c pthread_once asuinit
@c
@c We are AC-Unsafe because we use pthread_once to initialize
@c a global variable that holds the location of the mounted
@c shmfs on Linux.
@end deftypefun
@deftypefun int sem_close (sem_t *@var{sem})
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
@c lll_lock asulock aculock
@c twalk mtsrace{:root}
@c
@c We are AS-unsafe because we take a non-recursive lock.
@c We are AC-unsafe because several internal data structures
@c are not updated atomically.
@end deftypefun
@deftypefun int sem_unlink (const char *@var{name})
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acucorrupt{}}}
@c pthread_once asuinit acucorrupt aculock
@c mempcpy acucorrupt
@end deftypefun
@deftypefun int sem_wait (sem_t *@var{sem})
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@c atomic_fetch_add_relaxed (nwaiters) acucorrupt
@c
@c Given the use atomic operations this function seems
@c to be AS-safe. It is AC-unsafe because there is still
@c a window between atomic_fetch_add_relaxed and the pthread_push
@c of the handler that undoes that operation. A cancellation
@c at that point would fail to remove the process from the
@c waiters count.
@end deftypefun
@deftypefun int sem_timedwait (sem_t *@var{sem}, const struct timespec *@var{abstime})
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@c Same safety issues as sem_wait.
@end deftypefun
@deftypefun int sem_trywait (sem_t *@var{sem})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@c All atomic operations are safe in all contexts.
@end deftypefun
@deftypefun int sem_post (sem_t *@var{sem})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@c Same safety as sem_trywait.
@end deftypefun
@deftypefun int sem_getvalue (sem_t *@var{sem}, int *@var{sval})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@c Atomic write of a value is safe in all contexts.
@end deftypefun
@Theglibc{} provides POSIX semaphores as well. These functions' names begin
with @code{sem_} and they are declared in @file{semaphore.h}. @xref{POSIX
Semaphores}.

View file

@ -282,14 +282,22 @@ cwd\comments\
@macro standardsx {element, standard, header}
@end macro
@ifhtml
@macro manpageurl {func, sec}
@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}
@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html,,\func\(\sec\)}
@xref{Linux Kernel}
@end macro
@end ifhtml
@ifnothtml
@macro manpageurl {func, sec}
\func\(\sec\) (Latest, online: @url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html})
@xref{Linux Kernel}
@end macro
@end ifnothtml
@macro manpagefunctionstub {func,sec}
This documentation is a stub. For additional information on this
function, consult the manual page @manpageurl{\func\,\sec\}.
@xref{Linux Kernel}.
@end macro
@end ifclear

View file

@ -929,18 +929,31 @@ function, so there are no specific @code{errno} values.
@c Direct syscall on Linux; alias to swtch on HURD.
This function voluntarily gives up the task's claim on the CPU.
Depending on the scheduling policy in effect and the tasks ready to run
on the system, another task may be scheduled to run instead.
Technically, @code{sched_yield} causes the calling task to be made
immediately ready to run (as opposed to running, which is what it was
before). This means that if it has absolute priority higher than 0, it
gets pushed onto the tail of the queue of tasks that share its
A call to @code{sched_yield} does not guarantee that a different task
from the calling task is scheduled as a result; it depends on the
scheduling policy used on the target system. It is possible that the
call may not result in any visible effect, i.e., the same task gets
scheduled again.
For example on Linux systems, when a simple priority-based FIFO
scheduling policy (@code{SCHED_FIFO}) is in effect, the calling task is
made immediately ready to run (as opposed to running, which is what it
was before). This means that if it has absolute priority higher than 0,
it gets pushed onto the tail of the queue of tasks that share its
absolute priority and are ready to run, and it will run again when its
turn next arrives. If its absolute priority is 0, it is more
complicated, but still has the effect of yielding the CPU to other
tasks.
tasks. If there are no other tasks that share the calling task's
absolute priority, it will be scheduled again as if @code{sched_yield}
was never called.
If there are no other tasks that share the calling task's absolute
priority, this function doesn't have any effect.
Another example could be a time slice based preemptive round-robin
policy, such as the @code{SCHED_RR} policy on Linux. It is possible
with this policy that the calling task is scheduled again because it
still has time left in its slice.
To the extent that the containing program is oblivious to what other
processes in the system are doing and how fast it executes, this
@ -966,7 +979,6 @@ scheduling policies.
For additional information about scheduling policies, consult consult
the manual pages @manpageurl{sched,7} and @manpageurl{sched_setattr,2}.
@xref{Linux Kernel}.
@strong{Note:} Calling the @code{sched_setattr} function is incompatible
with support for @code{PTHREAD_PRIO_PROTECT} mutexes.
@ -1000,7 +1012,7 @@ Scheduling flags associated with the scheduling policy.
In addition to the generic fields, policy-specific fields are available.
For additional information, consult the manual page
@manpageurl{sched_setattr,2}. @xref{Linux Kernel}.
@manpageurl{sched_setattr,2}.
@end deftp
@deftypefun int sched_setaddr (pid_t @var{tid}, struct sched_attr *@var{attr}, unsigned int flags)

View file

@ -427,9 +427,18 @@ failure to properly emulate them.
@deftypevr Macro int SIGSYS
@standards{Unix, signal.h}
Bad system call; that is to say, the instruction to trap to the
operating system was executed, but the code number for the system call
to perform was invalid.
System call event. This signal may be generated by a valid system
call which requested an invalid sub-function, and also by the SECCOMP
filter when it filters or traps a system call.
If the system call itself is invalid or unsupported by the kernel, the
call will not raise this signal, but will return @code{ENOSYS}.
@end deftypevr
@deftypevr Macro int SIGSTKFLT
Coprocessor stack fault. Obsolete, no longer generated. This signal
may be used by applications in much the way @code{SIGUSR1} and
@code{SIGUSR2} are.
@end deftypevr
@node Termination Signals
@ -752,12 +761,11 @@ that isn't connected. @xref{Sending Data}.
@deftypevr Macro int SIGLOST
@standards{GNU, signal.h}
@cindex lost resource signal
Resource lost. This signal is generated when you have an advisory lock
on an NFS file, and the NFS server reboots and forgets about your lock.
On @gnuhurdsystems{}, @code{SIGLOST} is generated when any server program
dies unexpectedly. It is usually fine to ignore the signal; whatever
call was made to the server that died just returns an error.
Resource lost. On @gnuhurdsystems{}, @code{SIGLOST} is generated when
any server program dies unexpectedly. It is usually fine to ignore
the signal; whatever call was made to the server that died just
returns an error. This signal's original purpose of signalling a lost
NFS lock is obsolete.
@end deftypevr
@deftypevr Macro int SIGXCPU
@ -817,6 +825,17 @@ to print some status information about the system and what the process
is doing. Otherwise the default is to do nothing.
@end deftypevr
@deftypevr Macro int SIGPWR
@cindex power event signal
Power lost or restored. On s390x Linux systems, this signal is
generated when a machine check warning is issued, and is sent to the
process designated to receive ctrl-alt-del notifications. Otherwise,
it is up to userspace applications to generate this signal and manage
notifications as to the type of power event that happened.
The default action is to terminate the process.
@end deftypevr
@node Signal Messages
@subsection Signal Messages
@cindex signal messages

View file

@ -4346,6 +4346,18 @@ fail to handle lines more than 254 characters long (including the
terminating newline character).
@cindex lines (in a text file)
@item
If the system does not use POSIX-style in-band signalling to indicate
line termination, it can be impossibe to write anything to a text stream
without adding a line terminator. As a result, flushing a text stream
(by calling @code{fflush}, for example) may produce a logical line
terminator even if no @code{'\n'} character was written by the program.
@item
Text files may contain lines that embed @code{'\n'} characters that are
not treated as line terminators by the system. C programs cannot read
such text files reliably using the @file{stdio.h} facilities.
@item
On some systems, text files can contain only printing characters,
horizontal tab characters, and newlines, and so text streams may not
@ -4838,12 +4850,6 @@ currently opened.
This function is declared in the @file{stdio_ext.h} header.
@end deftypefun
@strong{Compatibility Note:} Some brain-damaged operating systems have
been known to be so thoroughly fixated on line-oriented input and output
that flushing a line buffered stream causes a newline to be written!
Fortunately, this ``feature'' seems to be becoming less common. You do
not need to worry about this with @theglibc{}.
In some situations it might be useful to not flush the output pending
for a stream but instead simply forget it. If transmission is costly
and the output is not needed anymore this is valid reasoning. In this

View file

@ -498,10 +498,7 @@ The symbols referred to in this section are declared in the file
@deftypefun int setlogmask (int @var{mask})
@standards{BSD, syslog.h}
@safety{@prelim{}@mtunsafe{@mtasurace{:LogMask}}@asunsafe{}@acsafe{}}
@c Read and modify are not guarded by syslog_lock, so concurrent changes
@c or even uses are undefined. This should use an atomic swap instead,
@c at least for modifications.
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
@code{setlogmask} sets a mask (the ``logmask'') that determines which
future @code{syslog} calls shall be ignored. If a program has not

View file

@ -554,6 +554,8 @@ This section describes the @glibcadj{} POSIX Threads implementation.
@menu
* Thread-specific Data:: Support for creating and
managing thread-specific data
* POSIX Semaphores:: Support for process and thread
synchronization using semaphores
* Non-POSIX Extensions:: Additional functions to extend
POSIX Thread functionality
@end menu
@ -615,6 +617,107 @@ Associate the thread-specific @var{value} with @var{key} in the calling thread.
@end deftypefun
@node POSIX Semaphores
@subsection POSIX Semaphores
@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@manpagefunctionstub{sem_init,3}
@c Does not atomically update sem_t therefore AC-unsafe
@c because it can leave sem_t partially initialized.
@end deftypefun
@deftypefun int sem_destroy (sem_t *@var{sem})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@manpagefunctionstub{sem_destroy,3}
@c Function does nothing and is therefore always safe.
@end deftypefun
@deftypefun {sem_t *} sem_open (const char *@var{name}, int @var{oflag}, ...)
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acuinit{}}}
@manpagefunctionstub{sem_open,3}
@c pthread_once asuinit
@c
@c We are AC-Unsafe because we use pthread_once to initialize
@c a global variable that holds the location of the mounted
@c shmfs on Linux.
@end deftypefun
@deftypefun int sem_close (sem_t *@var{sem})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
@manpagefunctionstub{sem_close,3}
@c lll_lock asulock aculock
@c twalk mtsrace{:root}
@c
@c We are AS-unsafe because we take a non-recursive lock.
@c We are AC-unsafe because several internal data structures
@c are not updated atomically.
@end deftypefun
@deftypefun int sem_unlink (const char *@var{name})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acucorrupt{}}}
@manpagefunctionstub{sem_unlink,3}
@c pthread_once asuinit acucorrupt aculock
@c mempcpy acucorrupt
@end deftypefun
@deftypefun int sem_wait (sem_t *@var{sem})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@manpagefunctionstub{sem_wait,3}
@c atomic_fetch_add_relaxed (nwaiters) acucorrupt
@c
@c Given the use atomic operations this function seems
@c to be AS-safe. It is AC-unsafe because there is still
@c a window between atomic_fetch_add_relaxed and the pthread_push
@c of the handler that undoes that operation. A cancellation
@c at that point would fail to remove the process from the
@c waiters count.
@end deftypefun
@deftypefun int sem_timedwait (sem_t *@var{sem}, const struct timespec *@var{abstime})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
@manpagefunctionstub{sem_timedwait,3}
@c Same safety issues as sem_wait.
@end deftypefun
@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
@standards{POSIX.1-2024, semaphore.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
against the clock specified by @var{clockid} rather than
@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
@end deftypefun
@deftypefun int sem_trywait (sem_t *@var{sem})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@manpagefunctionstub{sem_trywait,3}
@c All atomic operations are safe in all contexts.
@end deftypefun
@deftypefun int sem_post (sem_t *@var{sem})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@manpagefunctionstub{sem_post,3}
@c Same safety as sem_trywait.
@end deftypefun
@deftypefun int sem_getvalue (sem_t *@var{sem}, int *@var{sval})
@standards{POSIX.1-2008, semaphore.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@manpagefunctionstub{sem_getvalue,3}
@c Atomic write of a value is safe in all contexts.
@end deftypefun
@node Non-POSIX Extensions
@subsection Non-POSIX Extensions
@ -752,16 +855,6 @@ freed.
@Theglibc{} provides several waiting functions that expect an explicit
@code{clockid_t} argument.
@comment semaphore.h
@comment POSIX-proposed
@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
against the clock specified by @var{clockid} rather than
@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
@end deftypefun
@comment pthread.h
@comment POSIX-proposed
@deftypefun int pthread_cond_clockwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
@ -835,6 +928,9 @@ Currently, @var{clockid} must be either @code{CLOCK_MONOTONIC} or
@code{CLOCK_REALTIME}.
@end deftypefun
The @code{sem_clockwait} function also works using a @code{clockid_t}
argument. @xref{POSIX Semaphores}.
@node Single-Threaded
@subsubsection Detecting Single-Threaded Execution

View file

@ -595,6 +595,7 @@ Systems may support more than just this @w{ISO C} clock.
@deftypefun int timespec_get (struct timespec *@var{ts}, int @var{base})
@standards{ISO, time.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Store into @code{*@var{ts}} the current time according to the @w{ISO
C} time @var{base}.
@ -603,6 +604,7 @@ The return value is @var{base} on success and @code{0} on failure.
@deftypefun int timespec_getres (struct timespec *@var{res}, int @var{base})
@standards{ISO, time.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
If @var{ts} is non-null, store into @code{*@var{ts}} the resolution of
the time provided by @code{timespec_get} function for the @w{ISO C}
time @var{base}.

View file

@ -366,8 +366,13 @@ type-float-routines := \
e_log2f_data \
e_logf_data \
e_powf_log2_data \
e_sincoshf_data \
math_errf \
s_asincosf_data \
s_asincoshf_data \
s_asincospif_data \
s_sincosf_data \
s_sincospif_data \
# type-float-routines
# _Float128 support

View file

@ -936,6 +936,7 @@ atanpi -0x3.eb8e18p+0
atanpi 0x3.53c188p+0
atanpi -0x1.58c83p+0
atanpi 0x1.626772p-1
atanpi 0x1p-126
atanpi min
atanpi -min
atanpi min_subnorm
@ -7291,6 +7292,8 @@ log10p1 -0x1p-125
log10p1 -0x1p-1021
log10p1 -0x1p-16381
log10p1 0x1.27f7dap-17
log10p1 0x7.2a4368p-4
log10p1 0x6.d3a118p-4
log10p1 0x5.03f228p+0
@ -8298,6 +8301,7 @@ sinh -0x1.3dda8ap+0
sinh -0x5.ee9218p-4
sinh -0x1.bcfc98p+0
sinh -0x6.9bbb6df7c5d08p-4
sinh 0x1.250bfep-11
# the next value generates larger error bounds on x86_64 (ldbl-96)
sinh 0x2.c5d376167f4052f4p+12
sinh max
@ -8661,6 +8665,7 @@ tan 0x1.1ad374p+0
tan -0x1.0d55b8p+0
tan 1.57079697
tan -1.57079697
tan 0x1.ada6aap+27
tan 0x1p-5
tan 0x1p-10
tan 0x1p-15

View file

@ -1061,6 +1061,31 @@ atanpi 0x1.626772p-1
= atanpi tonearest ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e127p-4 : inexact-ok
= atanpi towardzero ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e127p-4 : inexact-ok
= atanpi upward ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e128p-4 : inexact-ok
atanpi 0x1p-126
= atanpi downward binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
= atanpi tonearest binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok
= atanpi towardzero binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
= atanpi upward binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok
= atanpi downward binary64 0x4p-128 : 0x1.45f306dc9c882p-128 : inexact-ok
= atanpi tonearest binary64 0x4p-128 : 0x1.45f306dc9c883p-128 : inexact-ok
= atanpi towardzero binary64 0x4p-128 : 0x1.45f306dc9c882p-128 : inexact-ok
= atanpi upward binary64 0x4p-128 : 0x1.45f306dc9c883p-128 : inexact-ok
= atanpi downward intel96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
= atanpi tonearest intel96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
= atanpi towardzero intel96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
= atanpi upward intel96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
= atanpi downward m68k96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
= atanpi tonearest m68k96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
= atanpi towardzero m68k96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
= atanpi upward m68k96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
= atanpi downward binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea69p-128 : inexact-ok
= atanpi tonearest binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea6ap-128 : inexact-ok
= atanpi towardzero binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea69p-128 : inexact-ok
= atanpi upward binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea6ap-128 : inexact-ok
= atanpi downward ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3eap-128 : inexact-ok
= atanpi tonearest ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea8p-128 : inexact-ok
= atanpi towardzero ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3eap-128 : inexact-ok
= atanpi upward ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea8p-128 : inexact-ok
atanpi min
= atanpi downward binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
= atanpi tonearest binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok

View file

@ -1789,6 +1789,31 @@ log10p1 -0x1p-16381
= log10p1 tonearest binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4dp-16384 : inexact-ok underflow errno-erange-ok
= log10p1 towardzero binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
= log10p1 upward binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
log10p1 0x1.27f7dap-17
= log10p1 downward binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
= log10p1 tonearest binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
= log10p1 towardzero binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
= log10p1 upward binary32 0x9.3fbedp-20 : 0x4.044b58p-20 : inexact-ok
= log10p1 downward binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
= log10p1 tonearest binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
= log10p1 towardzero binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
= log10p1 upward binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
= log10p1 downward intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 tonearest intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 towardzero intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 upward intel96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
= log10p1 downward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 tonearest m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 towardzero m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
= log10p1 upward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
= log10p1 downward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
= log10p1 tonearest binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
= log10p1 towardzero binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
= log10p1 upward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
= log10p1 downward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
= log10p1 tonearest ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
= log10p1 towardzero ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
= log10p1 upward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287dap-20 : inexact-ok
log10p1 0x7.2a4368p-4
= log10p1 downward binary32 0x7.2a4368p-4 : 0x2.9248dcp-4 : inexact-ok
= log10p1 tonearest binary32 0x7.2a4368p-4 : 0x2.9248ep-4 : inexact-ok

View file

@ -2115,6 +2115,31 @@ sinh -0x6.9bbb6df7c5d08p-4
= sinh tonearest ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
= sinh towardzero ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
= sinh upward ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
sinh 0x1.250bfep-11
= sinh downward binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
= sinh tonearest binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
= sinh towardzero binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
= sinh upward binary32 0x2.4a17fcp-12 : 0x2.4a18p-12 : inexact-ok
= sinh downward binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
= sinh tonearest binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
= sinh towardzero binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
= sinh upward binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
= sinh downward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
= sinh tonearest intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
= sinh towardzero intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
= sinh upward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
= sinh downward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
= sinh tonearest m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
= sinh towardzero m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
= sinh upward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
= sinh downward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
= sinh tonearest binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
= sinh towardzero binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
= sinh upward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
= sinh downward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
= sinh tonearest ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
= sinh towardzero ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
= sinh upward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
sinh 0x2.c5d376167f4052f4p+12
= sinh downward binary32 0x2.c5d378p+12 : 0xf.fffffp+124 : inexact-ok overflow errno-erange-ok
= sinh tonearest binary32 0x2.c5d378p+12 : plus_infty : inexact-ok overflow errno-erange

View file

@ -2532,6 +2532,31 @@ tan -1.57079697
= tan tonearest ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
= tan towardzero ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5cp+20 : inexact-ok
= tan upward ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
tan 0x1.ada6aap+27
= tan downward binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan tonearest binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan towardzero binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan upward binary32 0xd.6d355p+24 : 0x3.d0060cp-4 : inexact-ok
= tan downward binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan tonearest binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan towardzero binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
= tan upward binary64 0xd.6d355p+24 : 0x3.d006080000002p-4 : inexact-ok
= tan downward intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
= tan tonearest intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
= tan towardzero intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
= tan upward intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
= tan downward m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
= tan tonearest m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
= tan towardzero m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
= tan upward m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
= tan downward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
= tan tonearest binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
= tan towardzero binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
= tan upward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15cp-4 : inexact-ok
= tan downward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
= tan tonearest ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
= tan towardzero ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
= tan upward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c2p-4 : inexact-ok
tan 0x1p-5
= tan downward binary32 0x8p-8 : 0x8.00aabp-8 : inexact-ok
= tan tonearest binary32 0x8p-8 : 0x8.00aacp-8 : inexact-ok

View file

@ -173,6 +173,10 @@ static const struct test_ff_f_data remainder_test_data[] =
TEST_ff_f (remainder, 2, -1, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -2, 1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, -2, -1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_ff_f (remainder, 0x1.08001cp-2, 0x1p-24, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_ff_f (remainder, -0x1.003ffep-126, -0x1.8p-148, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_ff_f (remainder, 0x1.2c3224p+17, 0x1p-5, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
};
static void

View file

@ -289,6 +289,7 @@ tests = \
tst-dlsym1 \
tst-exec4 \
tst-exec5 \
tst-guard1 \
tst-initializers1 \
tst-initializers1-c11 \
tst-initializers1-c89 \
@ -701,6 +702,9 @@ $(objpfx)tst-execstack-threads.out: $(objpfx)tst-execstack-threads-mod.so
LDFLAGS-tst-execstack-threads = -Wl,-z,noexecstack
LDFLAGS-tst-execstack-threads-mod.so = -Wl,-z,execstack
CFLAGS-tst-execstack-threads-mod.c += -Wno-trampolines
ifeq ($(have-no-error-execstack),yes)
LDFLAGS-tst-execstack-threads-mod.so += -Wl,--no-error-execstack
endif
tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"

View file

@ -1,7 +1,3 @@
pthread_attr_setguardsize
test effectiveness
pthread_attr_[sg]etschedparam
what to test?

View file

@ -146,10 +146,37 @@ get_cached_stack (size_t *sizep, void **memp)
return result;
}
/* Assume support for MADV_ADVISE_GUARD, setup_stack_prot will disable it
and fallback to ALLOCATE_GUARD_PROT_NONE if the madvise call fails. */
static int allocate_stack_mode = ALLOCATE_GUARD_MADV_GUARD;
static inline int stack_prot (void)
{
return (PROT_READ | PROT_WRITE
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
}
static void *
allocate_thread_stack (size_t size, size_t guardsize)
{
/* MADV_ADVISE_GUARD does not require an additional PROT_NONE mapping. */
int prot = stack_prot ();
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_PROT_NONE)
/* If a guard page is required, avoid committing memory by first allocate
with PROT_NONE and then reserve with required permission excluding the
guard page. */
prot = guardsize == 0 ? prot : PROT_NONE;
return __mmap (NULL, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1,
0);
}
/* Return the guard page position on allocated stack. */
static inline char *
__attribute ((always_inline))
guard_position (void *mem, size_t size, size_t guardsize, struct pthread *pd,
guard_position (void *mem, size_t size, size_t guardsize, const struct pthread *pd,
size_t pagesize_m1)
{
#if _STACK_GROWS_DOWN
@ -159,27 +186,131 @@ guard_position (void *mem, size_t size, size_t guardsize, struct pthread *pd,
#endif
}
/* Based on stack allocated with PROT_NONE, setup the required portions with
'prot' flags based on the guard page position. */
static inline int
setup_stack_prot (char *mem, size_t size, char *guard, size_t guardsize,
const int prot)
/* Setup the MEM thread stack of SIZE bytes with the required protection flags
along with a guard area of GUARDSIZE size. It first tries with
MADV_GUARD_INSTALL, and then fallback to setup the guard area using the
extra PROT_NONE mapping. Update PD with the type of guard area setup. */
static inline bool
setup_stack_prot (char *mem, size_t size, struct pthread *pd,
size_t guardsize, size_t pagesize_m1)
{
char *guardend = guard + guardsize;
if (__glibc_unlikely (guardsize == 0))
return true;
char *guard = guard_position (mem, size, guardsize, pd, pagesize_m1);
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_MADV_GUARD)
{
if (__madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0)
{
pd->stack_mode = ALLOCATE_GUARD_MADV_GUARD;
return true;
}
/* If madvise fails it means the kernel does not support the guard
advise (we assume that the syscall is available, guard is page-aligned
and length is non negative). The stack has already the expected
protection flags, so it just need to PROT_NONE the guard area. */
atomic_store_relaxed (&allocate_stack_mode, ALLOCATE_GUARD_PROT_NONE);
if (__mprotect (guard, guardsize, PROT_NONE) != 0)
return false;
}
else
{
const int prot = stack_prot ();
char *guardend = guard + guardsize;
#if _STACK_GROWS_DOWN
/* As defined at guard_position, for architectures with downward stack
the guard page is always at start of the allocated area. */
if (__mprotect (guardend, size - guardsize, prot) != 0)
return errno;
/* As defined at guard_position, for architectures with downward stack
the guard page is always at start of the allocated area. */
if (__mprotect (guardend, size - guardsize, prot) != 0)
return false;
#else
size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
if (__mprotect (mem, mprots1, prot) != 0)
return errno;
size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
if (__mprotect (guardend, mprots2, prot) != 0)
return errno;
size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
if (__mprotect (mem, mprots1, prot) != 0)
return false;
size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
if (__mprotect (guardend, mprots2, prot) != 0)
return false;
#endif
return 0;
}
pd->stack_mode = ALLOCATE_GUARD_PROT_NONE;
return true;
}
/* Update the guard area of the thread stack MEM of size SIZE with the new
GUARDISZE. It uses the method defined by PD stack_mode. */
static inline bool
adjust_stack_prot (char *mem, size_t size, const struct pthread *pd,
size_t guardsize, size_t pagesize_m1)
{
/* The required guard area is larger than the current one. For
_STACK_GROWS_DOWN it means the guard should increase as:
|guard|---------------------------------stack|
|new guard--|---------------------------stack|
while for _STACK_GROWS_UP:
|stack---------------------------|guard|-----|
|stack--------------------|new guard---|-----|
Both madvise and mprotect allows overlap the required region,
so use the new guard placement with the new size. */
if (guardsize > pd->guardsize)
{
char *guard = guard_position (mem, size, guardsize, pd, pagesize_m1);
if (pd->stack_mode == ALLOCATE_GUARD_MADV_GUARD)
return __madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0;
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
return __mprotect (guard, guardsize, PROT_NONE) == 0;
}
/* The current guard area is larger than the required one. For
_STACK_GROWS_DOWN is means change the guard as:
|guard-------|-------------------------stack|
|new guard|----------------------------stack|
And for _STACK_GROWS_UP:
|stack---------------------|guard-------|---|
|stack------------------------|new guard|---|
For ALLOCATE_GUARD_MADV_GUARD it means remove the slack area
(disjointed region of guard and new guard), while for
ALLOCATE_GUARD_PROT_NONE it requires to mprotect it with the stack
protection flags. */
else if (pd->guardsize > guardsize)
{
size_t slacksize = pd->guardsize - guardsize;
if (pd->stack_mode == ALLOCATE_GUARD_MADV_GUARD)
{
void *slack =
#if _STACK_GROWS_DOWN
mem + guardsize;
#else
guard_position (mem, size, pd->guardsize, pd, pagesize_m1);
#endif
return __madvise (slack, slacksize, MADV_GUARD_REMOVE) == 0;
}
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
{
const int prot = stack_prot ();
#if _STACK_GROWS_DOWN
return __mprotect (mem + guardsize, slacksize, prot) == 0;
#else
char *new_guard = (char *)(((uintptr_t) pd - guardsize)
& ~pagesize_m1);
char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize)
& ~pagesize_m1);
/* The guard size difference might be > 0, but once rounded
to the nearest page the size difference might be zero. */
if (new_guard > old_guard
&& __mprotect (old_guard, new_guard - old_guard, prot) != 0)
return false;
#endif
}
}
return true;
}
/* Mark the memory of the stack as usable to the kernel. It frees everything
@ -291,7 +422,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
/* This is a user-provided stack. It will not be queued in the
stack cache nor will the memory (except the TLS memory) be freed. */
pd->user_stack = true;
pd->stack_mode = ALLOCATE_GUARD_USER;
/* This is at least the second thread. */
pd->header.multiple_threads = 1;
@ -325,10 +456,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
/* Allocate some anonymous memory. If possible use the cache. */
size_t guardsize;
size_t reported_guardsize;
size_t reqsize;
void *mem;
const int prot = (PROT_READ | PROT_WRITE
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
/* Adjust the stack size for alignment. */
size &= ~tls_static_align_m1;
@ -358,16 +486,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
return EINVAL;
/* Try to get a stack from the cache. */
reqsize = size;
pd = get_cached_stack (&size, &mem);
if (pd == NULL)
{
/* If a guard page is required, avoid committing memory by first
allocate with PROT_NONE and then reserve with required permission
excluding the guard page. */
mem = __mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
mem = allocate_thread_stack (size, guardsize);
if (__glibc_unlikely (mem == MAP_FAILED))
return errno;
@ -394,15 +516,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
#endif
/* Now mprotect the required region excluding the guard area. */
if (__glibc_likely (guardsize > 0))
if (!setup_stack_prot (mem, size, pd, guardsize, pagesize_m1))
{
char *guard = guard_position (mem, size, guardsize, pd,
pagesize_m1);
if (setup_stack_prot (mem, size, guard, guardsize, prot) != 0)
{
__munmap (mem, size);
return errno;
}
__munmap (mem, size);
return errno;
}
/* Remember the stack-related values. */
@ -456,59 +573,31 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
which will be read next. */
}
/* Create or resize the guard area if necessary. */
if (__glibc_unlikely (guardsize > pd->guardsize))
/* Create or resize the guard area if necessary on an already
allocated stack. */
if (!adjust_stack_prot (mem, size, pd, guardsize, pagesize_m1))
{
char *guard = guard_position (mem, size, guardsize, pd,
pagesize_m1);
if (__mprotect (guard, guardsize, PROT_NONE) != 0)
{
mprot_error:
lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
/* Remove the thread from the list. */
__nptl_stack_list_del (&pd->list);
/* Remove the thread from the list. */
__nptl_stack_list_del (&pd->list);
lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
/* Get rid of the TLS block we allocated. */
_dl_deallocate_tls (TLS_TPADJ (pd), false);
/* Get rid of the TLS block we allocated. */
_dl_deallocate_tls (TLS_TPADJ (pd), false);
/* Free the stack memory regardless of whether the size
of the cache is over the limit or not. If this piece
of memory caused problems we better do not use it
anymore. Uh, and we ignore possible errors. There
is nothing we could do. */
(void) __munmap (mem, size);
/* Free the stack memory regardless of whether the size
of the cache is over the limit or not. If this piece
of memory caused problems we better do not use it
anymore. Uh, and we ignore possible errors. There
is nothing we could do. */
(void) __munmap (mem, size);
return errno;
}
pd->guardsize = guardsize;
return errno;
}
else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize,
0))
{
/* The old guard area is too large. */
#if _STACK_GROWS_DOWN
if (__mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
prot) != 0)
goto mprot_error;
#elif _STACK_GROWS_UP
char *new_guard = (char *)(((uintptr_t) pd - guardsize)
& ~pagesize_m1);
char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize)
& ~pagesize_m1);
/* The guard size difference might be > 0, but once rounded
to the nearest page the size difference might be zero. */
if (new_guard > old_guard
&& __mprotect (old_guard, new_guard - old_guard, prot) != 0)
goto mprot_error;
#endif
pd->guardsize = guardsize;
}
pd->guardsize = guardsize;
/* The pthread_getattr_np() calls need to get passed the size
requested in the attribute, regardless of how large the
actually used guardsize is. */
@ -549,10 +638,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
return 0;
}
/* Maximum supported name from initial kernel support, not exported
by user API. */
#define ANON_VMA_NAME_MAX_LEN 80
#define SET_STACK_NAME(__prefix, __stack, __stacksize, __tid) \
({ \
char __stack_name[sizeof (__prefix) + \
@ -568,19 +653,21 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
static void
name_stack_maps (struct pthread *pd, bool set)
{
size_t adjust = pd->stack_mode == ALLOCATE_GUARD_PROT_NONE ?
pd->guardsize : 0;
#if _STACK_GROWS_DOWN
void *stack = pd->stackblock + pd->guardsize;
void *stack = pd->stackblock + adjust;
#else
void *stack = pd->stackblock;
#endif
size_t stacksize = pd->stackblock_size - pd->guardsize;
size_t stacksize = pd->stackblock_size - adjust;
if (!set)
__set_vma_name (stack, stacksize, NULL);
__set_vma_name (stack, stacksize, " glibc: unused stack");
else
{
unsigned int tid = pd->tid;
if (pd->user_stack)
if (pd->stack_mode == ALLOCATE_GUARD_USER)
SET_STACK_NAME (" glibc: pthread user stack: ", stack, stacksize, tid);
else
SET_STACK_NAME (" glibc: pthread stack: ", stack, stacksize, tid);

View file

@ -125,6 +125,12 @@ struct priority_protection_data
unsigned int priomap[];
};
enum allocate_stack_mode_t
{
ALLOCATE_GUARD_MADV_GUARD = 0,
ALLOCATE_GUARD_PROT_NONE = 1,
ALLOCATE_GUARD_USER = 2,
};
/* Thread descriptor data structure. */
struct pthread
@ -324,7 +330,7 @@ struct pthread
bool report_events;
/* True if the user provided the stack. */
bool user_stack;
enum allocate_stack_mode_t stack_mode;
/* True if thread must stop at startup time. */
bool stopped_start;

View file

@ -120,7 +120,7 @@ __nptl_deallocate_stack (struct pthread *pd)
not reset the 'used' flag in the 'tid' field. This is done by
the kernel. If no thread has been created yet this field is
still zero. */
if (__glibc_likely (! pd->user_stack))
if (__glibc_likely (pd->stack_mode != ALLOCATE_GUARD_USER))
(void) queue_stack (pd);
else
/* Free the memory associated with the ELF TLS. */

View file

@ -273,11 +273,6 @@ __condvar_cleanup_waiting (void *arg)
(If the format of __wrefs is changed, update nptl_lock_constants.pysym
and the pretty printers.)
For each of the two groups, we have:
__g_refs: Futex waiter reference count.
* LSB is true if waiters should run futex_wake when they remove the
last reference.
* Reference count used by waiters concurrently with signalers that have
acquired the condvar-internal lock.
__g_signals: The number of signals that can still be consumed, relative to
the current g1_start. (i.e. g1_start with the signal count added)
* Used as a futex word by waiters. Used concurrently by waiters and

View file

@ -554,7 +554,7 @@ start_thread (void *arg)
to avoid creating a new free-state block during thread release. */
__getrandom_vdso_release (pd);
if (!pd->user_stack)
if (pd->stack_mode != ALLOCATE_GUARD_USER)
advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd,
pd->guardsize);

View file

@ -145,9 +145,9 @@ __pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
> (size_t) iattr->stackaddr - last_to)
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
#else
/* The limit might be too high. */
/* The limit might be too low. */
if ((size_t) iattr->stacksize
> to - (size_t) iattr->stackaddr)
< to - (size_t) iattr->stackaddr)
iattr->stacksize = to - (size_t) iattr->stackaddr;
#endif
/* We succeed and no need to look further. */

369
nptl/tst-guard1.c Normal file
View file

@ -0,0 +1,369 @@
/* Basic tests for pthread guard area.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <array_length.h>
#include <pthreaddef.h>
#include <setjmp.h>
#include <stackinfo.h>
#include <stdio.h>
#include <support/check.h>
#include <support/test-driver.h>
#include <support/xsignal.h>
#include <support/xthread.h>
#include <support/xunistd.h>
#include <sys/mman.h>
#include <stdlib.h>
static long int pagesz;
/* To check if the guard region is inaccessible, the thread tries read/writes
on it and checks if a SIGSEGV is generated. */
static volatile sig_atomic_t signal_jump_set;
static sigjmp_buf signal_jmp_buf;
static void
sigsegv_handler (int sig)
{
if (signal_jump_set == 0)
return;
siglongjmp (signal_jmp_buf, sig);
}
static bool
try_access_buf (char *ptr, bool write)
{
signal_jump_set = true;
bool failed = sigsetjmp (signal_jmp_buf, 0) != 0;
if (!failed)
{
if (write)
*(volatile char *)(ptr) = 'x';
else
*(volatile char *)(ptr);
}
signal_jump_set = false;
return !failed;
}
static bool
try_read_buf (char *ptr)
{
return try_access_buf (ptr, false);
}
static bool
try_write_buf (char *ptr)
{
return try_access_buf (ptr, true);
}
static bool
try_read_write_buf (char *ptr)
{
return try_read_buf (ptr) && try_write_buf(ptr);
}
/* Return the guard region of the current thread (it only makes sense on
a thread created by pthread_created). */
struct stack_t
{
char *stack;
size_t stacksize;
char *guard;
size_t guardsize;
};
static inline size_t
adjust_stacksize (size_t stacksize)
{
/* For some ABIs, The guard page depends of the thread descriptor, which in
turn rely on the require static TLS. The only supported _STACK_GROWS_UP
ABI, hppa, defines TLS_DTV_AT_TP and it is not straightforward to
calculate the guard region with current pthread APIs. So to get a
correct stack size assumes an extra page after the guard area. */
#if _STACK_GROWS_DOWN
return stacksize;
#elif _STACK_GROWS_UP
return stacksize - pagesz;
#endif
}
struct stack_t
get_current_stack_info (void)
{
pthread_attr_t attr;
TEST_VERIFY_EXIT (pthread_getattr_np (pthread_self (), &attr) == 0);
void *stack;
size_t stacksize;
TEST_VERIFY_EXIT (pthread_attr_getstack (&attr, &stack, &stacksize) == 0);
size_t guardsize;
TEST_VERIFY_EXIT (pthread_attr_getguardsize (&attr, &guardsize) == 0);
/* The guardsize is reported as the current page size, although it might
be adjusted to a larger value (aarch64 for instance). */
if (guardsize != 0 && guardsize < ARCH_MIN_GUARD_SIZE)
guardsize = ARCH_MIN_GUARD_SIZE;
#if _STACK_GROWS_DOWN
void *guard = guardsize ? stack - guardsize : 0;
#elif _STACK_GROWS_UP
stacksize = adjust_stacksize (stacksize);
void *guard = guardsize ? stack + stacksize : 0;
#endif
pthread_attr_destroy (&attr);
return (struct stack_t) { stack, stacksize, guard, guardsize };
}
struct thread_args_t
{
size_t stacksize;
size_t guardsize;
};
struct thread_args_t
get_thread_args (const pthread_attr_t *attr)
{
size_t stacksize;
size_t guardsize;
TEST_COMPARE (pthread_attr_getstacksize (attr, &stacksize), 0);
TEST_COMPARE (pthread_attr_getguardsize (attr, &guardsize), 0);
if (guardsize < ARCH_MIN_GUARD_SIZE)
guardsize = ARCH_MIN_GUARD_SIZE;
return (struct thread_args_t) { stacksize, guardsize };
}
static void
set_thread_args (pthread_attr_t *attr, const struct thread_args_t *args)
{
xpthread_attr_setstacksize (attr, args->stacksize);
xpthread_attr_setguardsize (attr, args->guardsize);
}
static void *
tf (void *closure)
{
struct thread_args_t *args = closure;
struct stack_t s = get_current_stack_info ();
if (test_verbose)
printf ("debug: [tid=%jd] stack = { .stack=%p, stacksize=%#zx, guard=%p, "
"guardsize=%#zx }\n",
(intmax_t) gettid (),
s.stack,
s.stacksize,
s.guard,
s.guardsize);
if (args != NULL)
{
TEST_COMPARE (adjust_stacksize (args->stacksize), s.stacksize);
TEST_COMPARE (args->guardsize, s.guardsize);
}
/* Ensure we can access the stack area. */
TEST_COMPARE (try_read_buf (s.stack), true);
TEST_COMPARE (try_read_buf (&s.stack[s.stacksize / 2]), true);
TEST_COMPARE (try_read_buf (&s.stack[s.stacksize - 1]), true);
/* Check if accessing the guard area results in SIGSEGV. */
if (s.guardsize > 0)
{
TEST_COMPARE (try_read_write_buf (s.guard), false);
TEST_COMPARE (try_read_write_buf (&s.guard[s.guardsize / 2]), false);
TEST_COMPARE (try_read_write_buf (&s.guard[s.guardsize] - 1), false);
}
return NULL;
}
/* Test 1: caller provided stack without guard. */
static void
do_test1 (void)
{
pthread_attr_t attr;
xpthread_attr_init (&attr);
size_t stacksize = support_small_thread_stack_size ();
void *stack = xmmap (0,
stacksize,
PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
-1);
xpthread_attr_setstack (&attr, stack, stacksize);
xpthread_attr_setguardsize (&attr, 0);
struct thread_args_t args = { stacksize, 0 };
pthread_t t = xpthread_create (&attr, tf, &args);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
xpthread_attr_destroy (&attr);
xmunmap (stack, stacksize);
}
/* Test 2: same as 1., but with a guard area. */
static void
do_test2 (void)
{
pthread_attr_t attr;
xpthread_attr_init (&attr);
size_t stacksize = support_small_thread_stack_size ();
void *stack = xmmap (0,
stacksize,
PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
-1);
xpthread_attr_setstack (&attr, stack, stacksize);
xpthread_attr_setguardsize (&attr, pagesz);
struct thread_args_t args = { stacksize, 0 };
pthread_t t = xpthread_create (&attr, tf, &args);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
xpthread_attr_destroy (&attr);
xmunmap (stack, stacksize);
}
/* Test 3: pthread_create with default values. */
static void
do_test3 (void)
{
pthread_t t = xpthread_create (NULL, tf, NULL);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
}
/* Test 4: pthread_create without a guard area. */
static void
do_test4 (void)
{
pthread_attr_t attr;
xpthread_attr_init (&attr);
struct thread_args_t args = get_thread_args (&attr);
args.stacksize += args.guardsize;
args.guardsize = 0;
set_thread_args (&attr, &args);
pthread_t t = xpthread_create (&attr, tf, &args);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
xpthread_attr_destroy (&attr);
}
/* Test 5: pthread_create with non default stack and guard size value. */
static void
do_test5 (void)
{
pthread_attr_t attr;
xpthread_attr_init (&attr);
struct thread_args_t args = get_thread_args (&attr);
args.guardsize += pagesz;
args.stacksize += pagesz;
set_thread_args (&attr, &args);
pthread_t t = xpthread_create (&attr, tf, &args);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
xpthread_attr_destroy (&attr);
}
/* Test 6: thread with the required size (stack + guard) that matches the
test 3, but with a larger guard area. The pthread_create will need to
increase the guard area. */
static void
do_test6 (void)
{
pthread_attr_t attr;
xpthread_attr_init (&attr);
struct thread_args_t args = get_thread_args (&attr);
args.guardsize += pagesz;
args.stacksize -= pagesz;
set_thread_args (&attr, &args);
pthread_t t = xpthread_create (&attr, tf, &args);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
xpthread_attr_destroy (&attr);
}
/* Test 7: pthread_create with default values, the requires size matches the
one from test 3 and 6 (but with a reduced guard ares). The
pthread_create should use the cached stack from previous tests, but it
would require to reduce the guard area. */
static void
do_test7 (void)
{
pthread_t t = xpthread_create (NULL, tf, NULL);
void *status = xpthread_join (t);
TEST_VERIFY (status == 0);
}
static int
do_test (void)
{
pagesz = sysconf (_SC_PAGESIZE);
{
struct sigaction sa = {
.sa_handler = sigsegv_handler,
.sa_flags = SA_NODEFER,
};
sigemptyset (&sa.sa_mask);
xsigaction (SIGSEGV, &sa, NULL);
/* Some system generates SIGBUS accessing the guard area when it is
setup with madvise. */
xsigaction (SIGBUS, &sa, NULL);
}
static const struct {
const char *descr;
void (*test)(void);
} tests[] = {
{ "user provided stack without guard", do_test1 },
{ "user provided stack with guard", do_test2 },
{ "default attribute", do_test3 },
{ "default attribute without guard", do_test4 },
{ "non default stack and guard sizes", do_test5 },
{ "reused stack with larger guard", do_test6 },
{ "reused stack with smaller guard", do_test7 },
};
for (int i = 0; i < array_length (tests); i++)
{
printf ("debug: test%01d: %s\n", i, tests[i].descr);
tests[i].test();
}
return 0;
}
#include <support/test-driver.c>

View file

@ -367,6 +367,7 @@ tests += tst-nss-files-hosts-multi
tests += tst-nss-files-hosts-getent
tests += tst-nss-files-alias-leak
tests += tst-nss-files-alias-truncated
tests += tst-nss-files-network
# tst_fgetgrent currently only works with shared libraries
test-srcs := tst_fgetgrent
ifeq ($(run-built-tests),yes)

View file

@ -42,7 +42,8 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* 'inet_network' does not add zeroes at the end if the network number
does not four byte values. We add them ourselves if necessary. */
does not contain four byte values. We shift result ourselves if
necessary. */
cp = strchr (addr, '.');
if (cp != NULL)
{
@ -56,20 +57,11 @@ LINE_PARSER
++n;
}
}
if (n < 4)
{
char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1);
cp = stpcpy (newp, addr);
do
{
*cp++ = '.';
*cp++ = '0';
}
while (++n < 4);
*cp = '\0';
addr = newp;
}
result->n_net = __inet_network (addr);
if (result->n_net == INADDR_NONE)
return 0;
if (n < 4)
result->n_net <<= 8 * (4 - n);
result->n_addrtype = AF_INET;
})

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