Compare commits

...
Author SHA1 Message Date
Sunil K Pandey 2ca3505153 nptl: Optimize trylock for high cache contention workloads (BZ #33704)
Check lock availability before acquisition to reduce cache line
bouncing.  Significantly improves trylock throughput on multi-core
systems under heavy contention.

Tested on x86_64.

Fixes BZ #33704.

Co-authored-by: Alex M Wells <alex.m.wells@intel.com>
Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
(cherry picked from commit 63716823db)
2025-12-18 11:06:59 -08:00
Alex Butler 92d25389c2 aarch64: MTE compatible strncmp
Add support for MTE to strncmp. Regression tested with xcheck and benchmarked
with glibc's benchtests on the Cortex-A53, Cortex-A72, and Neoverse N1.

The existing implementation assumes that any access to the pages in which the
string resides is safe. This assumption is not true when MTE is enabled. This
patch updates the algorithm to ensure that accesses remain within the bounds
of an MTE tag (16-byte chunks) and improves overall performance.

Co-authored-by: Branislav Rankov <branislav.rankov@arm.com>
Co-authored-by: Wilco Dijkstra <wilco.dijkstra@arm.com>
(cherry picked from commit 03e1378f94)
2024-11-04 16:36:14 +00:00
H.J. Lu c32bd29854 Force DT_RPATH for --enable-hardcoded-path-in-tests
On Fedora 40/x86-64, linker enables --enable-new-dtags by default which
generates DT_RUNPATH instead of DT_RPATH.  Unlike DT_RPATH, DT_RUNPATH
only applies to DT_NEEDED entries in the executable and doesn't applies
to DT_NEEDED entries in shared libraries which are loaded via DT_NEEDED
entries in the executable.  Some glibc tests have libstdc++.so.6 in
DT_NEEDED, which has libm.so.6 in DT_NEEDED.  When DT_RUNPATH is generated,
/lib64/libm.so.6 is loaded for such tests.  If the newly built glibc is
older than glibc 2.36, these tests fail with

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

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

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 2dcaf70643)
2024-05-10 06:17:30 -07:00
H.J. Lu 3362604df4 Don't make errlist.o[s].d depend on errlist-compat.h
stdio-common/errlist.o.d and stdio-common/errlist.os.d aren't generated
alongside with stdio-common/errlist-compat.h.  Don't make them depend on
stdio-common/errlist-compat.h to avoid infinite loop with make-4.4.  This
fixes BZ #31330.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
2024-05-09 20:14:33 -07:00
Sergei Trofimovich a13b358cfb Makerules: fix MAKEFLAGS assignment for upcoming make-4.4 [BZ# 29564]
make-4.4 will add long flags to MAKEFLAGS variable:

    * WARNING: Backward-incompatibility!
      Previously only simple (one-letter) options were added to the MAKEFLAGS
      variable that was visible while parsing makefiles.  Now, all options
      are available in MAKEFLAGS.

This causes locale builds to fail when long options are used:

    $ make --shuffle
    ...
    make  -C localedata install-locales
    make: invalid shuffle mode: '1662724426r'

The change fixes it by passing eash option via whitespace and dashes.
That way option is appended to both single-word form and whitespace
separated form.

While at it fixed --silent mode detection in $(MAKEFLAGS) by filtering
out --long-options. Otherwise options like --shuffle flag enable silent
mode unintentionally. $(silent-make) variable consolidates the checks.

Resolves: BZ# 29564

CC: Paul Smith <psmith@gnu.org>
CC: Siddhesh Poyarekar <siddhesh@gotplt.org>
Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 2d7ed98add)
2024-05-09 20:14:31 -07:00
Florian Weimer 0976774b75 elf: Disable some subtests of ifuncmain1, ifuncmain5 for !PIE
(cherry picked from commit 9cc9d61ee1)
2024-05-09 19:11:58 -07:00
Aurelien Jarno c0a523f13b testsuite: stdlib/isomac.c: add missing include
When running the testsuite, building stdlib/isomac.c outputs the
following warning:

  gcc -O   -D_GNU_SOURCE -DIS_IN_build -include /home/aurel32/glibc-build/config.h isomac.c -o /home/aurel32/glibc-build/stdlib/isomac
  isomac.c: In function ‘get_null_defines’:
  isomac.c:260:3: warning: implicit declaration of function ‘close’; did you mean ‘pclose’? [-Wimplicit-function-declaration]
     close (fd);
     ^~~~~
     pclose

Fix that by adding the <unistd.h> include.

Changelog:
	* stdlib/isomac.c: Include <unistd.h>.
(cherry picked from commit 11f382ee78)
2024-05-09 19:11:00 -07:00
Florian Weimer 13f1198286 resolv/tst-idna_name_classify: Isolate from system libraries
Loading NSS modules from static binaries uses installed system
libraries if LD_LIBRARY_PATH is not set.

(cherry picked from commit 8dddf0bd5a)
2024-05-09 15:33:29 -07:00
Wilco Dijkstra f3095d3eb6 aarch64: Use memcpy_simd as the default memcpy
Since __memcpy_simd is the fastest memcpy on almost all cores, replace
the generic memcpy with it.

(cherry picked from commit 531717afbc)
2024-04-11 13:47:20 +01:00
Sunil K Pandey 47f69077d5 x86_64: Optimize ffsll function code size.
Ffsll function randomly regress by ~20%, depending on how code gets
aligned in memory.  Ffsll function code size is 17 bytes.  Since default
function alignment is 16 bytes, it can load on 16, 32, 48 or 64 bytes
aligned memory.  When ffsll function load at 16, 32 or 64 bytes aligned
memory, entire code fits in single 64 bytes cache line.  When ffsll
function load at 48 bytes aligned memory, it splits in two cache line,
hence random regression.

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

This patch fixes ffsll function random performance regression.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 9d94997b5f)
2024-02-08 10:34:19 -08:00
Noah Goldstein 29f401e05d x86: Fix incorrect scope of setting shared_per_thread [BZ# 30745]
The:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 23ee92deea)
2023-07-21 16:41:28 +02:00
Noah Goldstein c9e58ae234 x86: Fix wcsnlen-avx2 page cross length comparison [BZ #29591]
Previous implementation was adjusting length (rsi) to match
bytes (eax), but since there is no bound to length this can cause
overflow.

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

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

(cherry picked from commit b0969fa53a)
2022-11-24 18:06:14 -08:00
Sunil K Pandey 2b05bbfd35 x86-64: Require BMI2 for avx2 functions [BZ #29611]
This patch fixes BZ #29611
2022-09-28 19:37:12 -07:00
H.J. Lu 956cda8d9f x86-64: Require BMI2 for strchr-avx2.S [BZ #29611]
Since strchr-avx2.S updated by

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

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

uses sarx:

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

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

This fixes BZ #29611.

(cherry picked from commit 83c5b36822)
2022-09-28 19:37:01 -07:00
Andreas Schwab 8b915921fb Add test for bug 29530
This tests for a bug that was introduced in commit edc1686af0 ("vfprintf:
Reuse work_buffer in group_number") and fixed as a side effect of commit
6caddd34bd ("Remove most vfprintf width/precision-dependent allocations
(bug 14231, bug 26211).").

(cherry picked from commit ca6466e8be)
2022-08-30 12:42:19 +02:00
Arjun Shankar bbb0692779 support: Add xsetlocale function
(cherry picked from commit cce35a50c1)
2022-08-30 12:42:19 +02:00
Florian Weimer 839405a350 support: Implement TEST_COMPARE_STRING
(cherry picked from commit 1df872fd74)
2022-08-30 12:42:19 +02:00
Joseph Myers 211a30a92b Fix memmove call in vfprintf-internal.c:group_number
A recent GCC mainline change introduces errors of the form:

vfprintf-internal.c: In function 'group_number':
vfprintf-internal.c:2093:15: error: 'memmove' specified bound between 9223372036854775808 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
 2093 |               memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is a genuine bug in the glibc code: s > front_ptr is always true
at this point in the code, and the intent is clearly for the
subtraction to be the other way round.  The other arguments to the
memmove call here also appear to be wrong; w and s point just *after*
the destination and source for copying the rest of the number, so the
size needs to be subtracted to get appropriate pointers for the
copying.  Adjust the memmove call to conform to the apparent intent of
the code, so fixing the -Wstringop-overflow error.

Now, if the original code were ever executed, a buffer overrun would
result.  However, I believe this code (introduced in commit
edc1686af0, "vfprintf: Reuse work_buffer
in group_number", so in glibc 2.26) is unreachable in prior glibc
releases (so there is no need for a bug in Bugzilla, no need to
consider any backports unless someone wants to build older glibc
releases with GCC 12 and no possibility of this buffer overrun
resulting in a security issue).

work_buffer is 1000 bytes / 250 wide characters.  This case is only
reachable if an initial part of the number, plus a grouped copy of the
rest of the number, fail to fit in that space; that is, if the grouped
number fails to fit in the space.  In the wide character case,
grouping is always one wide character, so even with a locale (of which
there aren't any in glibc) grouping every digit, a number would need
to occupy at least 125 wide characters to overflow, and a 64-bit
integer occupies at most 23 characters in octal including a leading 0.
In the narrow character case, the multibyte encoding of the grouping
separator would need to be at least 42 bytes to overflow, again
supposing grouping every digit, but MB_LEN_MAX is 16.  So even if we
admit the case of artificially constructed locales not shipped with
glibc, given that such a locale would need to use one of the character
sets supported by glibc, this code cannot be reached at present.  (And
POSIX only actually specifies the ' flag for grouping for decimal
output, though glibc acts on it for other bases as well.)

With binary output (if you consider use of grouping there to be
valid), you'd need a 15-byte multibyte character for overflow; I don't
know if any supported character set has such a character (if, again,
we admit constructed locales using grouping every digit and a grouping
separator chosen to have a multibyte encoding as long as possible, as
well as accepting use of grouping with binary), but given that we have
this code at all (clearly it's not *correct*, or in accordance with
the principle of avoiding arbitrary limits, to skip grouping on
running out of internal space like that), I don't think it should need
any further changes for binary printf support to go in.

On the other hand, support for large sizes of _BitInt in printf (see
the N2858 proposal) *would* require something to be done about such
arbitrary limits (presumably using dynamic allocation in printf again,
for sufficiently large _BitInt arguments only - currently only
floating-point uses dynamic allocation, and, as previously discussed,
that could actually be replaced by bounded allocation given smarter
code).

Tested with build-many-glibcs.py for aarch64-linux-gnu (GCC mainline).
Also tested natively for x86_64.

(cherry picked from commit db6c4935fa)
2022-08-30 12:35:30 +02:00
Joseph Myers e1c0c00cc2 Remove most vfprintf width/precision-dependent allocations (bug 14231, bug 26211).
The vfprintf implementation (used for all printf-family functions)
contains complicated logic to allocate internal buffers of a size
depending on the width and precision used for a format, using either
malloc or alloca depending on that size, and with consequent checks
for size overflow and allocation failure.

As noted in bug 26211, the version of that logic used when '$' plus
argument number formats are in use is missing the overflow checks,
which can result in segfaults (quite possibly exploitable, I didn't
try to work that out) when the width or precision is in the range
0x7fffffe0 through 0x7fffffff (maybe smaller values as well in the
wprintf case on 32-bit systems, when the multiplication by sizeof
(CHAR_T) can overflow).

All that complicated logic in fact appears to be useless.  As far as I
can tell, there has been no need (outside the floating-point printf
code, which does its own allocations) for allocations depending on
width or precision since commit
3e95f6602b ("Remove limitation on size
of precision for integers", Sun Sep 12 21:23:32 1999 +0000).  Thus,
this patch removes that logic completely, thereby fixing both problems
with excessive allocations for large width and precision for
non-floating-point formats, and the problem with missing overflow
checks with such allocations.  Note that this does have the
consequence that width and precision up to INT_MAX are now allowed
where previously INT_MAX / sizeof (CHAR_T) - EXTSIZ or more would have
been rejected, so could potentially expose any other overflows where
the value would previously have been rejected by those removed checks.

I believe this completely fixes bugs 14231 and 26211.

Excessive allocations are still possible in the floating-point case
(bug 21127), as are other integer or buffer overflows (see bug 26201).
This does not address the cases where a precision larger than INT_MAX
(embedded in the format string) would be meaningful without printf's
return value overflowing (when it's used with a string format, or %g
without the '#' flag, so the actual output will be much smaller), as
mentioned in bug 17829 comment 8; using size_t internally for
precision to handle that case would be complicated by struct
printf_info being a public ABI.  Nor does it address the matter of an
INT_MIN width being negated (bug 17829 comment 7; the same logic
appears a second time in the file as well, in the form of multiplying
by -1).  There may be other sources of memory allocations with malloc
in printf functions as well (bug 24988, bug 16060).  From inspection,
I think there are also integer overflows in two copies of "if ((width
-= len) < 0)" logic (where width is int, len is size_t and a very long
string could result in spurious padding being output on a 32-bit
system before printf overflows the count of output characters).

Tested for x86-64 and x86.

(cherry picked from commit 6caddd34bd)
2022-08-30 12:20:01 +02:00
Adhemerval Zanella 29b12753b5 stdio: Add tests for printf multibyte convertion leak [BZ#25691]
Checked on x86_64-linux-gnu and i686-linux-gnu.

(cherry picked from commit 910a835dc9)
2022-08-30 12:14:03 +02:00
Florian Weimer c6fad4fa14 stdio: Remove memory leak from multibyte convertion [BZ#25691]
This is an updated version of a previous patch [1] with the
following changes:

  - Use compiler overflow builtins on done_add_func function.
  - Define the scratch +utstring_converted_wide_string using
    CHAR_T.
  - Added a testcase and mention the bug report.

Both default and wide printf functions might leak memory when
manipulate multibyte characters conversion depending of the size
of the input (whether __libc_use_alloca trigger or not the fallback
heap allocation).

This patch fixes it by removing the extra memory allocation on
string formatting with conversion parts.

The testcase uses input argument size that trigger memory leaks
on unpatched code (using a scratch buffer the threashold to use
heap allocation is lower).

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

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

[1] https://sourceware.org/pipermail/libc-alpha/2017-June/082098.html

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

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

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

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

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

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

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

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

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

and

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

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

This is for BZ #28755.

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

(cherry picked from commit aa5a720056)
2022-02-17 11:48:18 -08:00
H.J. Lu 55194992ea x86-64: Test strlen and wcslen with 0 in the RSI register [BZ #28064]
commit 6f573a27b6
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date:   Wed Jun 23 01:19:34 2021 -0400

    x86-64: Add wcslen optimize for sse4.1

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

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

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

    x86-64: Add wcslen optimize for sse4.1

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

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

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 0679442def)
2022-02-01 13:07:59 -08:00
H.J. Lu 5219747d67 x86: Black list more Intel CPUs for TSX [BZ #27398]
Disable TSX and enable RTM_ALWAYS_ABORT for Intel CPUs listed in:

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

This fixes BZ #27398.

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

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

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

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

This fixes BZ #28033.

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

These tests show the following implementations failing on x86_64:

wcsnlen-sse4_1
wcsnlen-avx2

wmemchr-sse2
wmemchr-avx2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit acfd088a19)
2022-01-27 16:31:45 -08:00
H.J. Lu 1cbbc82c09 test-strnlen.c: Check that strnlen won't go beyond the maximum length
Place strings ending at page boundary without the null byte.  If an
implementation goes beyond EXP_LEN, it will trigger the segfault.

(cherry picked from commit cb882b21b6)
2022-01-27 16:31:39 -08:00
H.J. Lu 2449016af5 test-strnlen.c: Initialize wchar_t string with wmemset [BZ #27655]
Use wmemset to initialize wchar_t string.

(cherry picked from commit 86859b7e58)
2022-01-27 16:31:33 -08:00
H.J. Lu 208e34a700 x86-64: Require BMI2 for __strlen_evex and __strnlen_evex
Since __strlen_evex and __strnlen_evex added by

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

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

use sarx:

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

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

(cherry picked from commit 55bf411b45)
2022-01-27 16:31:28 -08:00
H.J. Lu 2baf5616d5 NEWS: Add a bug fix entry for BZ #27457 2022-01-27 12:49:55 -08:00
Sunil K Pandey 29c42b8d68 x86-64: Fix ifdef indentation in strlen-evex.S
Fix some indentations of ifdef in file strlen-evex.S which are off by 1
and confusing to read.

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

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

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

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

	xtest
	jz	1f
	vzeroall
	ret
1:
	vzeroupper
	ret

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

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

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

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

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

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

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

(cherry picked from commit 1fd8c163a8)
2022-01-27 12:47:19 -08:00
H.J. Lu e8078d2ac5 x86: Add AVX512VL_Usable and AVX512BW_Usable
Add AVX512VL_Usable and AVX512BW_Usable for backporting string/memory
functions optimized with 256-bit EVEX.
2022-01-27 12:47:19 -08:00
H.J. Lu b2e59f87ae x86: Set Prefer_No_VZEROUPPER and add Prefer_AVX2_STRCMP
1. Set Prefer_No_VZEROUPPER if RTM is usable to avoid RTM abort triggered
by VZEROUPPER inside a transactionally executing RTM region.
2. Since to compare 2 32-byte strings, 256-bit EVEX strcmp requires 2
loads, 3 VPCMPs and 2 KORDs while AVX2 strcmp requires 1 load, 2 VPCMPEQs,
1 VPMINU and 1 VPMOVMSKB, AVX2 strcmp is faster than EVEX strcmp.  Add
Prefer_AVX2_STRCMP to prefer AVX2 strcmp family functions.

(cherry picked from commit 1da50d4bda)
2022-01-27 12:47:19 -08:00
H.J. Lu 43c27a754b NEWS: Add a bug fix entry for BZ #28755 2022-01-27 07:30:10 -08:00
Noah Goldstein 65df4053a4 x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]
Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to
__wcscmp_avx2. For x86_64 this covers the entire address range so any
length larger could not possibly be used to bound `s1` or `s2`.

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

Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
(cherry picked from commit ddf0992cf5)
2022-01-27 07:29:40 -08:00
Siddhesh Poyarekar 83d6f50313 Fix SXID_ERASE behavior in setuid programs (BZ #27471)
When parse_tunables tries to erase a tunable marked as SXID_ERASE for
setuid programs, it ends up setting the envvar string iterator
incorrectly, because of which it may parse the next tunable
incorrectly.  Given that currently the implementation allows malformed
and unrecognized tunables pass through, it may even allow SXID_ERASE
tunables to go through.

This change revamps the SXID_ERASE implementation so that:

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

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

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

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

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

(cherry picked from commit 061fe3f8ad)

Also add intprops.h from 2.29 from commit 8e6fd2bdb2
2021-04-14 11:49:23 +05:30
Siddhesh Poyarekar c43e69db62 tst-env-setuid: Use support_capture_subprogram_self_sgid
Use the support_capture_subprogram_self_sgid to spawn an sgid child.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

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

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

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

(cherry picked from commit 716a3bdc41)
2021-04-14 11:21:49 +05:30
Siddhesh Poyarekar d79d7e13ba support: Typo and formatting fixes
- Add a newline to the end of error messages in transfer().
- Fixed the name of support_subprocess_init().

(cherry picked from commit 95c68080a3)
2021-04-14 11:21:14 +05:30
Siddhesh Poyarekar 7e3b1e71ab support: Pass environ to child process
Pass environ to posix_spawn so that the child process can inherit
environment of the test.

(cherry picked from commit e958490f8c)
2021-04-14 11:21:14 +05:30
Adhemerval Zanella e23cdedb6b support: Add support_capture_subprogram
Its API is similar to support_capture_subprocess, but rather creates a
new process based on the input path and arguments.  Under the hoods it
uses posix_spawn to create the new process.

It also allows the use of other support_capture_* functions to check
for expected results and free the resources.

Checked on x86_64-linux-gnu.

	* support/Makefile (libsupport-routines): Add support_subprocess,
	xposix_spawn, xposix_spawn_file_actions_addclose, and
	xposix_spawn_file_actions_adddup2.
	(tst-support_capture_subprocess-ARGS): New rule.
	* support/capture_subprocess.h (support_capture_subprogram): New
	prototype.
	* support/support_capture_subprocess.c (support_capture_subprocess):
	Refactor to use support_subprocess and support_capture_poll.
	(support_capture_subprogram): New function.
	* support/tst-support_capture_subprocess.c (write_mode_to_str,
	str_to_write_mode, test_common, parse_int, handle_restart,
	do_subprocess, do_subprogram, do_multiple_tests): New functions.
	(do_test): Add support_capture_subprogram tests.
	* support/subprocess.h: New file.
	* support/support_subprocess.c: Likewise.
	* support/xposix_spawn.c: Likewise.
	* support/xposix_spawn_file_actions_addclose.c: Likewise.
	* support/xposix_spawn_file_actions_adddup2.c: Likewise.
	* support/xspawn.h: Likewise.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 0e16969129)
2021-04-14 11:20:55 +05:30
DJ Delorie 4352eb4e5d nscd: Fix double free in netgroupcache [BZ #27462]
In commit 745664bd79 a use-after-free
was fixed, but this led to an occasional double-free.  This patch
tracks the "live" allocation better.

Tested manually by a third party.

Related: RHBZ 1927877

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit dca565886b)
2021-03-08 15:42:28 +05:30
Florian Weimer e9db77683e gconv: Fix assertion failure in ISO-2022-JP-3 module (bug 27256)
The conversion loop to the internal encoding does not follow
the interface contract that __GCONV_FULL_OUTPUT is only returned
after the internal wchar_t buffer has been filled completely.  This
is enforced by the first of the two asserts in iconv/skeleton.c:

	      /* We must run out of output buffer space in this
		 rerun.  */
	      assert (outbuf == outerr);
	      assert (nstatus == __GCONV_FULL_OUTPUT);

This commit solves this issue by queuing a second wide character
which cannot be written immediately in the state variable, like
other converters already do (e.g., BIG5-HKSCS or TSCII).

Reported-by: Tavis Ormandy <taviso@gmail.com>
(cherry picked from commit 7d88c6142c)
2021-01-27 15:51:17 +01:00
H.J. Lu 44fd8887d0 x86: Check IFUNC definition in unrelocated executable [BZ #20019]
Calling an IFUNC function defined in unrelocated executable also leads to
segfault.  Issue a fatal error message when calling IFUNC function defined
in the unrelocated executable from a shared library.

On x86, ifuncmain6pie failed with:

[hjl@gnu-cfl-2 build-i686-linux]$ ./elf/ifuncmain6pie --direct
./elf/ifuncmain6pie: IFUNC symbol 'foo' referenced in '/export/build/gnu/tools-build/glibc-32bit/build-i686-linux/elf/ifuncmod6.so' is defined in the executable and creates an unsatisfiable circular dependency.
[hjl@gnu-cfl-2 build-i686-linux]$ readelf -rW elf/ifuncmod6.so | grep foo
00003ff4  00000706 R_386_GLOB_DAT         0000400c   foo_ptr
00003ff8  00000406 R_386_GLOB_DAT         00000000   foo
0000400c  00000401 R_386_32               00000000   foo
[hjl@gnu-cfl-2 build-i686-linux]$

Remove non-JUMP_SLOT relocations against foo in ifuncmod6.so, which
trigger the circular IFUNC dependency, and build ifuncmain6pie with
-Wl,-z,lazy.

(cherry picked from commits 6ea5b57afa
 and 7137d682eb)
2021-01-13 15:17:05 -08:00
H.J. Lu 4a68828e37 x86: Set header.feature_1 in TCB for always-on CET [BZ #27177]
Update dl_cet_check() to set header.feature_1 in TCB when both IBT and
SHSTK are always on.

(cherry picked from commit 2ef23b5205)
2021-01-13 09:27:48 -08:00
H.J. Lu 56fbd0ba21 x86-64: Avoid rep movsb with short distance [BZ #27130]
When copying with "rep movsb", if the distance between source and
destination is N*4GB + [1..63] with N >= 0, performance may be very
slow.  This patch updates memmove-vec-unaligned-erms.S for AVX and
AVX512 versions with the distance in RCX:

	cmpl	$63, %ecx
	// Don't use "rep movsb" if ECX <= 63
	jbe	L(Don't use rep movsb")
	Use "rep movsb"

Benchtests data with bench-memcpy, bench-memcpy-large, bench-memcpy-random
and bench-memcpy-walk on Skylake, Ice Lake and Tiger Lake show that its
performance impact is within noise range as "rep movsb" is only used for
data size >= 4KB.

(cherry picked from commit 3ec5d83d2a)
2021-01-12 07:04:55 -08:00
Szabolcs Nagy d81114e0aa aarch64: Fix DT_AARCH64_VARIANT_PCS handling [BZ #26798]
The variant PCS support was ineffective because in the common case
linkmap->l_mach.plt == 0 but then the symbol table flags were ignored
and normal lazy binding was used instead of resolving the relocs early.
(This was a misunderstanding about how GOT[1] is setup by the linker.)

In practice this mainly affects SVE calls when the vector length is
more than 128 bits, then the top bits of the argument registers get
clobbered during lazy binding.

Fixes bug 26798.

(cherry picked from commit 558251bd87)
2020-11-04 12:29:39 +00:00
Wilco Dijkstra e5dac996b9 AArch64: Use __memcpy_simd on Neoverse N2/V1
Add CPU detection of Neoverse N2 and Neoverse V1, and select __memcpy_simd as
the memcpy/memmove ifunc.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit e11ed9d2b4)
2020-10-14 17:29:12 +01:00
Wilco Dijkstra 98979f62b8 AArch64: Rename IS_ARES to IS_NEOVERSE_N1
Rename IS_ARES to IS_NEOVERSE_N1 since that is a bit clearer.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 0f6278a879)
2020-10-14 17:29:12 +01:00
Wilco Dijkstra fe09348c4e [AArch64] Improve integer memcpy
Further optimize integer memcpy.  Small cases now include copies up
to 32 bytes.  64-128 byte copies are split into two cases to improve
performance of 64-96 byte copies.  Comments have been rewritten.

(cherry picked from commit 7000651327)
2020-10-14 17:29:12 +01:00
Krzysztof Koch 722c93572e aarch64: Increase small and medium cases for __memcpy_generic
Increase the upper bound on medium cases from 96 to 128 bytes.
Now, up to 128 bytes are copied unrolled.

Increase the upper bound on small cases from 16 to 32 bytes so that
copies of 17-32 bytes are not impacted by the larger medium case.

Benchmarking:
The attached figures show relative timing difference with respect
to 'memcpy_generic', which is the existing implementation.
'memcpy_med_128' denotes the the version of memcpy_generic with
only the medium case enlarged. The 'memcpy_med_128_small_32' numbers
are for the version of memcpy_generic submitted in this patch, which
has both medium and small cases enlarged. The figures were generated
using the script from:
https://www.sourceware.org/ml/libc-alpha/2019-10/msg00563.html

Depending on the platform, the performance improvement in the
bench-memcpy-random.c benchmark ranges from 6% to 20% between
the original and final version of memcpy.S

Tested against GLIBC testsuite and randomized tests.

(cherry picked from commit b9f145df85)
2020-10-14 17:29:12 +01:00
Wilco Dijkstra b915da29da AArch64: Improve backwards memmove performance
On some microarchitectures performance of the backwards memmove improves if
the stores use STR with decreasing addresses.  So change the memmove loop
in memcpy_advsimd.S to use 2x STR rather than STP.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit bd394d131c)
2020-10-14 17:29:12 +01:00
Wilco Dijkstra 4bd28df0b0 AArch64: Add optimized Q-register memcpy
Add a new memcpy using 128-bit Q registers - this is faster on modern
cores and reduces codesize.  Similar to the generic memcpy, small cases
include copies up to 32 bytes.  64-128 byte copies are split into two
cases to improve performance of 64-96 byte copies.  Large copies align
the source rather than the destination.

bench-memcpy-random is ~9% faster than memcpy_falkor on Neoverse N1,
so make this memcpy the default on N1 (on Centriq it is 15% faster than
memcpy_falkor).

Passes GLIBC regression tests.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
(cherry picked from commit 4a733bf375)
2020-10-14 17:29:12 +01:00
Wilco Dijkstra 118fbee7a0 AArch64: Align ENTRY to a cacheline
Given almost all uses of ENTRY are for string/memory functions,
align ENTRY to a cacheline to simplify things.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 34f0d01d5e)
2020-10-14 17:29:12 +01:00
H.J. Lu f82072183a NEWS: Mention BZ 25933 fix 2020-07-04 10:06:38 -07:00
Sunil K Pandey 23db5555eb Fix avx2 strncmp offset compare condition check [BZ #25933]
strcmp-avx2.S: In avx2 strncmp function, strings are compared in
chunks of 4 vector size(i.e. 32x4=128 byte for avx2). After first 4
vector size comparison, code must check whether it already passed
the given offset. This patch implement avx2 offset check condition
for strncmp function, if both string compare same for first 4 vector
size.

(cherry picked from commit 75870237ff)
2020-07-04 10:05:03 -07:00
Andreas Schwab 21344a3d62 Fix use-after-free in glob when expanding ~user (bug 25414)
The value of `end_name' points into the value of `dirname', thus don't
deallocate the latter before the last use of the former.

(cherry picked from commit ddc650e9b3)
2020-03-20 15:23:11 -03:00
Andreas Schwab 0478174d1e Fix array overflow in backtrace on PowerPC (bug 25423)
When unwinding through a signal frame the backtrace function on PowerPC
didn't check array bounds when storing the frame address.  Fixes commit
d400dcac5e ("PowerPC: fix backtrace to handle signal trampolines").

(cherry picked from commit d937694059)
2020-03-20 15:23:11 -03:00
Florian Weimer 9ff61e9159 riscv: Do not use __has_include__
The user-visible preprocessor construct is called __has_include.

(cherry picked from commit 28dd393922)
2020-01-21 13:44:35 +01:00
Florian Weimer 6578d89c17 misc/test-errno-linux: Handle EINVAL from quotactl
In commit 3dd4d40b420846dd35869ccc8f8627feef2cff32 ("xfs: Sanity check
flags of Q_XQUOTARM call"), Linux 5.4 added checking for the flags
argument, causing the test to fail due to too restrictive test
expectations.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 1f7525d924)
2019-12-05 17:31:10 +01:00
Kamlesh Kumar ef0051070f <string.h>: Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang [BZ #25232]
Without the asm redirects, strchr et al. are not const-correct.

libc++ has a wrapper header that works with and without
__CORRECT_ISO_CPP_STRING_H_PROTO (using a Clang extension).  But when
Clang is used with libstdc++ or just C headers, the overloaded functions
with the correct types are not declared.

This change does not impact current GCC (with libstdc++ or libc++).

(cherry picked from commit 953ceff17a)
2019-12-05 16:56:04 +01:00
Florian Weimer 9f917f7b41 x86: Assume --enable-cet if GCC defaults to CET [BZ #25225]
This links in CET support if GCC defaults to CET.  Otherwise, __CET__
is defined, yet CET functionality is not compiled and linked into the
dynamic loader, resulting in a linker failure due to undefined
references to _dl_cet_check and _dl_open_check.

(cherry picked from commit 9fb8139079)
2019-12-03 21:11:32 +01:00
Florian Weimer f55e312bcd libio: Disable vtable validation for pre-2.1 interposed handles [BZ #25203]
Commit c402355dfa ("libio: Disable
vtable validation in case of interposition [BZ #23313]") only covered
the interposable glibc 2.1 handles, in libio/stdfiles.c.  The
parallel code in libio/oldstdfiles.c needs similar detection logic.

Fixes (again) commit db3476aff1
("libio: Implement vtable verification [BZ #20191]").

Change-Id: Ief6f9f17e91d1f7263421c56a7dc018f4f595c21
(cherry picked from commit cb61630ed7)
2019-11-28 14:42:11 +01:00
Marcin Kościelnicki 7966ce07e8 rtld: Check __libc_enable_secure before honoring LD_PREFER_MAP_32BIT_EXEC (CVE-2019-19126) [BZ #25204]
The problem was introduced in glibc 2.23, in commit
b9eb92ab05
("Add Prefer_MAP_32BIT_EXEC to map executable pages with MAP_32BIT").

(cherry picked from commit d5dfad4326)
2019-11-22 13:46:54 +01:00
Stefan Liebler cedb3e47c6 Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP [BZ #23403]
The alignment of TLS variables is wrong if accessed from within a thread
for architectures with tls variant TLS_TCB_AT_TP.
For the main thread the static tls data is properly aligned.
For other threads the alignment depends on the alignment of the thread
pointer as the static tls data is located relative to this pointer.

This patch adds this alignment for TLS_TCB_AT_TP variants in the same way
as it is already done for TLS_DTV_AT_TP. The thread pointer is also already
properly aligned if the user provides its own stack for the new thread.

This patch extends the testcase nptl/tst-tls1.c in order to check the
alignment of the tls variables and it adds a pthread_create invocation
with a user provided stack.
The test itself is migrated from test-skeleton.c to test-driver.c
and the missing support functions xpthread_attr_setstack and xposix_memalign
are added.

ChangeLog:

	[BZ #23403]
	* nptl/allocatestack.c (allocate_stack): Align pointer pd for
	TLS_TCB_AT_TP tls variant.
	* nptl/tst-tls1.c: Migrate to support/test-driver.c.
	Add alignment checks.
	* support/Makefile (libsupport-routines): Add xposix_memalign and
	xpthread_setstack.
	* support/support.h: Add xposix_memalign.
	* support/xthread.h: Add xpthread_attr_setstack.
	* support/xposix_memalign.c: New File.
	* support/xpthread_attr_setstack.c: Likewise.

(cherry picked from commit bc79db3fd4)
2019-11-06 17:40:18 -05:00
Dragan Mladjenovic fe7c01cb14 mips: Force RWX stack for hard-float builds that can run on pre-4.8 kernels
Linux/Mips kernels prior to 4.8 could potentially crash the user
process when doing FPU emulation while running on non-executable
user stack.

Currently, gcc doesn't emit .note.GNU-stack for mips, but that will
change in the future. To ensure that glibc can be used with such
future gcc, without silently resulting in binaries that might crash
in runtime, this patch forces RWX stack for all built objects if
configured to run against minimum kernel version less than 4.8.

	* sysdeps/unix/sysv/linux/mips/Makefile
	(test-xfail-check-execstack):
	Move under mips-has-gnustack != yes.
	(CFLAGS-.o*, ASFLAGS-.o*): New rules.
	Apply -Wa,-execstack if mips-force-execstack == yes.
	* sysdeps/unix/sysv/linux/mips/configure: Regenerated.
	* sysdeps/unix/sysv/linux/mips/configure.ac
	(mips-force-execstack): New var.
	Set to yes for hard-float builds with minimum_kernel < 4.8.0
	or minimum_kernel not set at all.
	(mips-has-gnustack): New var.
	Use value of libc_cv_as_noexecstack
	if mips-force-execstack != yes, otherwise set to no.

(cherry picked from commit 33bc9efd91)
2019-11-05 14:36:40 -03:00
Florian Weimer 59991bf48a elf: Refuse to dlopen PIE objects [BZ #24323]
Another executable has already been mapped, so the dynamic linker
cannot perform relocations correctly for the second executable.

(cherry picked from commit 2c75b545de)
(test omitted due to indirect dependency on test-in-container)
2019-11-01 15:41:30 -04:00
DJ Delorie cef4c840a8 nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696]
nss_db allows for getpwent et al to be called without a set*ent,
but it only works once.  After the last get*ent a set*ent is
required to restart, because the end*ent did not properly reset
the module.  Resetting it to NULL allows for a proper restart.

If the database doesn't exist, however, end*ent erroniously called
munmap which set errno.

The test case runs "makedb" inside the testroot, so needs selinux
DSOs installed.

(cherry picked from commit 99135114ba)
(note: tests excluded as test-in-container infrastructure missing)
2019-10-31 17:55:49 -04:00
H.J. Lu 0d3905b110 Call _dl_open_check after relocation [BZ #24259]
This is a workaround for [BZ #20839] which doesn't remove the NODELETE
object when _dl_open_check throws an exception.  Move it after relocation
in dl_open_worker to avoid leaving the NODELETE object mapped without
relocation.

	[BZ #24259]
	* elf/dl-open.c (dl_open_worker): Call _dl_open_check after
	relocation.
	* sysdeps/x86/Makefile (tests): Add tst-cet-legacy-5a,
	tst-cet-legacy-5b, tst-cet-legacy-6a and tst-cet-legacy-6b.
	(modules-names): Add tst-cet-legacy-mod-5a, tst-cet-legacy-mod-5b,
	tst-cet-legacy-mod-5c, tst-cet-legacy-mod-6a, tst-cet-legacy-mod-6b
	and tst-cet-legacy-mod-6c.
	(CFLAGS-tst-cet-legacy-5a.c): New.
	(CFLAGS-tst-cet-legacy-5b.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-5a.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-5b.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-5c.c): Likewise.
	(CFLAGS-tst-cet-legacy-6a.c): Likewise.
	(CFLAGS-tst-cet-legacy-6b.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-6a.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-6b.c): Likewise.
	(CFLAGS-tst-cet-legacy-mod-6c.c): Likewise.
	($(objpfx)tst-cet-legacy-5a): Likewise.
	($(objpfx)tst-cet-legacy-5a.out): Likewise.
	($(objpfx)tst-cet-legacy-mod-5a.so): Likewise.
	($(objpfx)tst-cet-legacy-mod-5b.so): Likewise.
	($(objpfx)tst-cet-legacy-5b): Likewise.
	($(objpfx)tst-cet-legacy-5b.out): Likewise.
	(tst-cet-legacy-5b-ENV): Likewise.
	($(objpfx)tst-cet-legacy-6a): Likewise.
	($(objpfx)tst-cet-legacy-6a.out): Likewise.
	($(objpfx)tst-cet-legacy-mod-6a.so): Likewise.
	($(objpfx)tst-cet-legacy-mod-6b.so): Likewise.
	($(objpfx)tst-cet-legacy-6b): Likewise.
	($(objpfx)tst-cet-legacy-6b.out): Likewise.
	(tst-cet-legacy-6b-ENV): Likewise.
	* sysdeps/x86/tst-cet-legacy-5.c: New file.
	* sysdeps/x86/tst-cet-legacy-5a.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-5b.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-6.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-6a.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-6b.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-5.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-5a.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-5b.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-5c.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-6.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-6a.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-6b.c: Likewise.
	* sysdeps/x86/tst-cet-legacy-mod-6c.c: Likewise.

(cherry picked from commit d0093c5cef)
2019-10-31 16:53:14 -04:00
DJ Delorie f144981490 Base max_fast on alignment, not width, of bins (Bug 24903)
set_max_fast sets the "impossibly small" value based on,
eventually, MALLOC_ALIGNMENT.  The comparisons for the smallest
chunk used is, eventually, MIN_CHUNK_SIZE.  Note that i386
is the only platform where these are the same, so a smallest
chunk *would* be put in a no-fastbins fastbin.

This change calculates the "impossibly small" value
based on MIN_CHUNK_SIZE instead, so that we can know it will
always be impossibly small.

(cherry picked from commit ff12e0fb91)
2019-10-31 16:48:04 +01:00
Niklas Hambüchen 91d5989356 malloc: Fix missing accounting of top chunk in malloc_info [BZ #24026]
Fixes `<total type="rest" size="..."> incorrectly showing as 0 most
of the time.

The rest value being wrong is significant because to compute the
actual amount of memory handed out via malloc, the user must subtract
it from <system type="current" size="...">. That result being wrong
makes investigating memory fragmentation issues like
<https://bugzilla.redhat.com/show_bug.cgi?id=843478> close to
impossible.

(cherry picked from commit b6d2c4475d)
2019-10-30 19:35:19 +01:00
Florian Weimer 6d750b1899 malloc: Remove unwanted leading whitespace in malloc_info [BZ #24867]
It was introduced in commit 6c8dbf00f5
("Reformat malloc to gnu style.").

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit b0f6679bcd)
2019-10-30 19:32:56 +01:00
Florian Weimer 5dab5eafb3 malloc: Various cleanups for malloc/tst-mxfast
(cherry picked from commit f9769a2397)
2019-10-30 19:03:40 +01:00
DJ Delorie cb89ba9c72 Add glibc.malloc.mxfast tunable
* elf/dl-tunables.list: Add glibc.malloc.mxfast.
* manual/tunables.texi: Document it.
* malloc/malloc.c (do_set_mxfast): New.
(__libc_mallopt): Call it.
* malloc/arena.c: Add mxfast tunable.
* malloc/tst-mxfast.c: New.
* malloc/Makefile: Add it.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit c48d92b430)
2019-10-30 19:03:40 +01:00
Andreas Schwab a645c48756 nscd: avoid assertion failure during persistent db check
nscd should not abort when it finds inconsistencies in the persistent db.

(cherry picked from commit 61595e3d36)
2019-10-30 13:59:26 +01:00
Wilco Dijkstra f88c59f465 Small tcache improvements
Change the tcache->counts[] entries to uint16_t - this removes
the limit set by char and allows a larger tcache.  Remove a few
redundant asserts.

bench-malloc-thread with 4 threads is ~15% faster on Cortex-A72.

Reviewed-by: DJ Delorie <dj@redhat.com>

	* malloc/malloc.c (MAX_TCACHE_COUNT): Increase to UINT16_MAX.
	(tcache_put): Remove redundant assert.
	(tcache_get): Remove redundant asserts.
	(__libc_malloc): Check tcache count is not zero.
	* manual/tunables.texi (glibc.malloc.tcache_count): Update maximum.

(cherry picked from commit 1f50f2ad85)
2019-10-30 12:01:42 +01:00
Joseph Myers 3640758943 Fix assertion in malloc.c:tcache_get.
One of the warnings that appears with -Wextra is "ordered comparison
of pointer with integer zero" in malloc.c:tcache_get, for the
assertion:

  assert (tcache->entries[tc_idx] > 0);

Indeed, a "> 0" comparison does not make sense for
tcache->entries[tc_idx], which is a pointer.  My guess is that
tcache->counts[tc_idx] is what's intended here, and this patch changes
the assertion accordingly.

Tested for x86_64.

	* malloc/malloc.c (tcache_get): Compare tcache->counts[tc_idx]
	with 0, not tcache->entries[tc_idx].

(cherry picked from commit 77dc0d8643)
2019-10-30 11:56:49 +01:00
Wilco Dijkstra b58bace7ce Improve performance of memmem
This patch significantly improves performance of memmem using a novel
modified Horspool algorithm.  Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.

By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.

Small needles up to size 2 use a dedicated linear search.  Very long needles
use the Two-Way algorithm (to avoid increasing stack size or slowing down
the common case, inlining is disabled).

The performance gain is 6.6 times on English text on AArch64 using random
needles with average size 8.

Tested against GLIBC testsuite and randomized tests.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>

	* string/memmem.c (__memmem): Rewrite to improve performance.

(cherry picked from commit 680942b016)
2019-09-13 15:19:26 +01:00
Wilco Dijkstra 354f52e984 Improve performance of strstr
This patch significantly improves performance of strstr using a novel
modified Horspool algorithm.  Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.

By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.

Small needles up to size 3 use a dedicated linear search.  Very long needles
use the Two-Way algorithm.

The performance gain using the improved bench-strstr on Cortex-A72 is 5.8
times basic_strstr and 3.7 times twoway_strstr.

Tested against GLIBC testsuite, randomized tests and the GNULIB strstr test
(https://git.savannah.gnu.org/cgit/gnulib.git/tree/tests/test-strstr.c).

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>

	* string/str-two-way.h (two_way_short_needle): Add inline to avoid
	warning.
	(two_way_long_needle): Block inlining.
	* string/strstr.c (strstr2): Add new function.
	(strstr3): Likewise.
	(STRSTR): Completely rewrite strstr to improve performance.

(cherry picked from commit 5e0a7ecb66)
2019-09-13 15:19:19 +01:00
Rajalakshmi Srinivasaraghavan d6ccf2f45c Speedup first memmem match
As done in commit 284f42bc77, memcmp
can be used after memchr to avoid the initialization overhead of the
two-way algorithm for the first match.  This has shown improvement
>40% for first match.

(cherry picked from commit c8dd67e7c9)
2019-09-13 15:17:56 +01:00
Wilco Dijkstra 1def6a34ae Simplify and speedup strstr/strcasestr first match
Looking at the benchtests, both strstr and strcasestr spend a lot of time
in a slow initialization loop handling one character per iteration.
This can be simplified and use the much faster strlen/strnlen/strchr/memcmp.
Read ahead a few cachelines to reduce the number of strnlen calls, which
improves performance by ~3-4%.  This patch improves the time taken for the
full strstr benchtest by >40%.

	* string/strcasestr.c (STRCASESTR): Simplify and speedup first match.
	* string/strstr.c (AVAILABLE): Likewise.

(cherry picked from commit 284f42bc77)
2019-09-13 15:15:36 +01:00
Wilco Dijkstra 1533274d5f [AArch64] Add ifunc support for Ares
Add Ares to the midr_el0 list and support ifunc dispatch.  Since Ares
supports 2 128-bit loads/stores, use Neon registers for memcpy by
selecting __memcpy_falkor by default (we should rename this to
__memcpy_simd or similar).

	* manual/tunables.texi (glibc.cpu.name): Add ares tunable.
	* sysdeps/aarch64/multiarch/memcpy.c (__libc_memcpy): Use
	__memcpy_falkor for ares.
	* sysdeps/unix/sysv/linux/aarch64/cpu-features.h (IS_ARES):
	Add new define.
	* sysdeps/unix/sysv/linux/aarch64/cpu-features.c (cpu_list):
	Add ares cpu.

(cherry picked from commit 02f440c1ef)
2019-09-06 18:49:02 +01:00
Adhemerval Zanella 57922433fa posix: Fix large mmap64 offset for mips64n32 (BZ#24699)
The fix for BZ#21270 (commit 158d5fa0e1) added a mask to avoid offset larger
than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
as mips64n64, but still defines off_t as old non-LFS type (other ILP32, such
x32, defines off_t being equal to off64_t).  This leads to use the same
mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the maximum
offset it can use with mmap64.

This patch fixes by setting the high mask only for __NR_mmap2 usage. The
posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
patch also change the test to check for an arch-specific header that defines
the maximum supported offset.

Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests tst-mmap-offset
on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu and
mips64-n32-linux-gnu.

	[BZ #24699]
	* posix/tst-mmap-offset.c: Mention BZ #24699.
	(do_test_bz21270): Rename to do_test_large_offset and use
	mmap64_maximum_offset to check for maximum expected offset value.
	* sysdeps/generic/mmap_info.h: New file.
	* sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
	* sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
	__NR_mmap2 is used.

(cherry picked from commit a008c76b56)
2019-07-12 20:59:32 +00:00
Szabolcs Nagy 298e659172 aarch64: handle STO_AARCH64_VARIANT_PCS
Backport of commit 82bc69c012
and commit 30ba037546
without using DT_AARCH64_VARIANT_PCS for optimizing the symbol table check.
This is needed so the internal abi between ld.so and libc.so is unchanged.

Avoid lazy binding of symbols that may follow a variant PCS with different
register usage convention from the base PCS.

Currently the lazy binding entry code does not preserve all the registers
required for AdvSIMD and SVE vector calls.  Saving and restoring all
registers unconditionally may break existing binaries, even if they never
use vector calls, because of the larger stack requirement for lazy
resolution, which can be significant on an SVE system.

The solution is to mark all symbols in the symbol table that may follow
a variant PCS so the dynamic linker can handle them specially.  In this
patch such symbols are always resolved at load time, not lazily.

So currently LD_AUDIT for variant PCS symbols are not supported, for that
the _dl_runtime_profile entry needs to be changed e.g. to unconditionally
save/restore all registers (but pass down arg and retval registers to
pltentry/exit callbacks according to the base PCS).

This patch also removes a __builtin_expect from the modified code because
the branch prediction hint did not seem useful.

	* sysdeps/aarch64/dl-machine.h (elf_machine_lazy_rel): Check
	STO_AARCH64_VARIANT_PCS and bind such symbols at load time.
2019-07-12 10:37:56 +01:00
Szabolcs Nagy b95c8a3150 aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS
STO_AARCH64_VARIANT_PCS is a non-visibility st_other flag for marking
symbols that reference functions that may follow a variant PCS with
different register usage convention from the base PCS.

DT_AARCH64_VARIANT_PCS is a dynamic tag that marks ELF modules that
have R_*_JUMP_SLOT relocations for symbols marked with
STO_AARCH64_VARIANT_PCS (i.e. have variant PCS calls via a PLT).

	* elf/elf.h (STO_AARCH64_VARIANT_PCS): Define.
	(DT_AARCH64_VARIANT_PCS): Define.
2019-07-10 15:49:37 +01:00
Florian Weimer 5f7fa9ac30 io: Remove copy_file_range emulation [BZ #24744]
The kernel is evolving this interface (e.g., removal of the
restriction on cross-device copies), and keeping up with that
is difficult.  Applications which need the function should
run kernels which support the system call instead of relying on
the imperfect glibc emulation.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 5a659ccc0e)
2019-07-09 10:33:10 +02:00
Dmitry V. Levin 91b02c5b4d libio: do not attempt to free wide buffers of legacy streams [BZ #24228]
Commit a601b74d31 aka glibc-2.23~693
("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem
when _G_HAVE_MMAP is turned off.") introduced a regression:
_IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all
files, including legacy standard files which are small statically
allocated objects that do not have wide buffers and the _mode member,
causing memory corruption.

Another memory corruption in _IO_unbuffer_all happens when -1
is assigned to the _mode member of legacy standard files that
do not have it.

[BZ #24228]
* libio/genops.c (_IO_unbuffer_all)
[SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
buffers and access _IO_FILE_complete members of legacy libio streams.
* libio/tst-bz24228.c: New file.
* libio/tst-bz24228.map: Likewise.
* libio/Makefile [build-shared] (tests): Add tst-bz24228.
[build-shared] (generated): Add tst-bz24228.mtrace and
tst-bz24228.check.
[run-built-tests && build-shared] (tests-special): Add
$(objpfx)tst-bz24228-mem.out.
(LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
($(objpfx)tst-bz24228-mem.out): New rule.

(cherry picked from commit 21cc130b78)
2019-06-20 17:32:07 +00:00
Wilco Dijkstra 58d2672f64 Fix tcache count maximum (BZ #24531)
The tcache counts[] array is a char, which has a very small range and thus
may overflow.  When setting tcache_count tunable, there is no overflow check.
However the tunable must not be larger than the maximum value of the tcache
counts[] array, otherwise it can overflow when filling the tcache.

	[BZ #24531]
	* malloc/malloc.c (MAX_TCACHE_COUNT): New define.
	(do_set_tcache_count): Only update if count is small enough.
	* manual/tunables.texi (glibc.malloc.tcache_count): Document max value.

(cherry picked from commit 5ad533e8e6)
2019-05-22 14:37:54 +01:00
Mark Wielaard 059d6750f9 dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) [BZ#24476]
dlerror.c (__dlerror_main_freeres) will try to free resources which only
have been initialized when init () has been called. That function is
called when resources are needed using __libc_once (once, init) where
once is a __libc_once_define (static, once) in the dlerror.c file.
Trying to free those resources if init () hasn't been called will
produce errors under valgrind memcheck. So guard the freeing of those
resources using __libc_once_get (once) and make sure we have a valid
key. Also add a similar guard to __dlerror ().

	* dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
	__libc_once_get (once) and static_bug == NULL.
	(__dlerror): Check we have a valid key, set result to static_buf
	otherwise.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 11b451c886)
2019-05-16 15:19:44 +02:00
Andreas Schwab d948478bc5 Fix crash in _IO_wfile_sync (bug 20568)
When computing the length of the converted part of the stdio buffer, use
the number of consumed wide characters, not the (negative) distance to the
end of the wide buffer.

(cherry picked from commit 32ff397533)
2019-05-15 17:08:48 +02:00
Adam Maris 4a5e58827f malloc: Check for large bin list corruption when inserting unsorted chunk
Fixes bug 24216. This patch adds security checks for bk and bk_nextsize pointers
of chunks in large bin when inserting chunk from unsorted bin. It was possible
to write the pointer to victim (newly inserted chunk) to arbitrary memory
locations if bk or bk_nextsize pointers of the next large bin chunk
got corrupted.

(cherry picked from commit 5b06f538c5)
2019-05-02 14:29:11 +02:00
Istvan Kurucsai 38e8981833 malloc: Check the alignment of mmapped chunks before unmapping.
* malloc/malloc.c (munmap_chunk): Verify chunk alignment.

(cherry picked from commit c0e82f1173)
2019-05-02 14:28:59 +02:00
Istvan Kurucsai b9054d6602 malloc: Add more integrity checks to mremap_chunk.
* malloc/malloc.c (mremap_chunk): Additional checks.

(cherry picked from commit ebe544bf6e)
2019-05-02 14:28:48 +02:00
Florian Weimer 4d24775292 malloc: Add ChangeLog for accidentally committed change
Commit b90ddd08f6 ("malloc: Additional
checks for unsorted bin integrity I.") was committed without a
whitespace fix, so it is adjusted here as well.

(cherry picked from commit 35cfefd960)
2019-05-02 14:27:51 +02:00
Adhemerval Zanella 5cbb73004b elf: Fix pldd (BZ#18035)
Since 9182aa6799 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:

 elf/dl-object.c

 95   new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;

Since newname->name points to new->l_libname->name.

This leads to pldd to an infinite call at:

 elf/pldd-xx.c

203     again:
204       while (1)
205         {
206           ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);

228           /* Try the l_libname element.  */
229           struct E(libname_list) ln;
230           if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231             {
232               name_offset = ln.name;
233               goto again;
234             }

Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.

I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.

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

	[BZ #18035]
	* elf/Makefile (tests-container): Add tst-pldd.
	* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
	(E(find_maps)): Avoid use alloca, use default read file operations
	instead of explicit LFS names, and fix infinite	loop.
	* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
	(get_process_info): Use _Static_assert instead of assert, use default
	directory operations instead of explicit LFS names, and free some
	leadek pointers.
	* elf/tst-pldd.c: New file.

(cherry picked from commit 1a4c27355e)
(Backported without the test case due to lack of test-in-container
support.)
2019-04-26 14:08:20 +02:00
Florian Weimer 9b3aac5869 Revert "memusagestat: use local glibc when linking [BZ #18465]"
This reverts commit 630d7201ce.

The position of the -Wl,-rpath-link= options on the linker command
line is not correct, so the new way of linking memusagestat does not
always work.
2019-04-25 14:59:42 +02:00
Mike Frysinger 630d7201ce memusagestat: use local glibc when linking [BZ #18465]
The memusagestat is the only binary that has its own link line which
causes it to be linked against the existing installed C library.  It
has been this way since it was originally committed in 1999, but I
don't see any reason as to why.  Since we want all the programs we
build locally to be against the new copy of glibc, change the build
to be like all other programs.

(cherry picked from commit f9b645b4b0)
2019-04-24 19:30:53 +02:00
TAMUKI Shoichi 7423da211d ja_JP locale: Add entry for the new Japanese era [BZ #22964]
The Japanese era name will be changed on May 1, 2019.  The Japanese
government made a preliminary announcement on April 1, 2019.

The glibc ja_JP locale must be updated to include the new era name for
strftime's alternative year format support.

This is a minimal cherry pick of just the required locale changes.

(cherry picked from commit 466afec308)
2019-04-03 18:23:14 -04:00
Stefan Liebler 4aeff335ca S390: Mark vx and vxe as important hwcap.
This patch adds vx and vxe as important hwcaps
which allows one to provide shared libraries
tuned for platforms with non-vx/-vxe, vx or vxe.

ChangeLog:

	* sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
	Add HWCAP_S390_VX and HWCAP_S390_VXE.

(cherry picked from commit 61f5e9470f)

Conflicts:
	ChangeLog
2019-03-21 09:29:57 +01:00
Aurelien Jarno 54e725e39d Record CVE-2019-9169 in NEWS and ChangeLog [BZ #24114]
(cherry picked from commit b626c5aa5d)
2019-03-16 23:34:23 +01:00
Paul Eggert 2aee101ff6 regex: fix read overrun [BZ #24114]
Problem found by AddressSanitizer, reported by Hongxu Chen in:
https://debbugs.gnu.org/34140
* posix/regexec.c (proceed_next_node):
Do not read past end of input buffer.

(cherry picked from commit 583dd860d5)
2019-03-16 23:32:36 +01:00
Andreas Schwab 4bf5ab3196 RISC-V: don't assume PI mutexes and robust futexes before 4.20 (bug 23864)
Support for futex_cmpxchg as only been added to 4.20-rc1.

(cherry picked from commit 295132ff05)
2019-03-14 22:59:06 +01:00
Adhemerval Zanella e5366c12d0 powerpc: Only enable TLE with PPC_FEATURE2_HTM_NOSC
Linux from 3.9 through 4.2 does not abort HTM transaction on syscalls,
instead it suspend and resume it when leaving the kernel.  The
side-effects of the syscall will always remain visible, even if the
transaction is aborted.  This is an issue when transaction is used along
with futex syscall, on pthread_cond_wait for instance, where the futex
call might succeed but the transaction is rolled back leading the
pthread_cond object in an inconsistent state.

Glibc used to prevent it by always aborting a transaction before issuing
a syscall.  Linux 4.2 also decided to abort active transaction in
syscalls which makes the glibc workaround superfluous.  Worse, glibc
transaction abortion leads to a performance issue on recent kernels
where the HTM state is saved/restore lazily (v4.9).  By aborting a
transaction on every syscalls, regardless whether a transaction has being
initiated before, GLIBS makes the kernel always save/restore HTM state
(it can not even lazily disable it after a certain number of syscall
iterations).

Because of this shortcoming, Transactional Lock Elision is just enabled
when it has been explicitly set (either by tunables of by a configure
switch) and if kernel aborts HTM transactions on syscalls
(PPC_FEATURE2_HTM_NOSC).  It is reported that using simple benchmark [1],
the context-switch is about 5% faster by not issuing a tabort in every
syscall in newer kernels.

Checked on powerpc64le-linux-gnu with 4.4.0 kernel (Ubuntu 16.04).

	* NEWS: Add note about new TLE support on powerpc64le.
	* sysdeps/powerpc/nptl/tcb-offsets.sym (TM_CAPABLE): Remove.
	* sysdeps/powerpc/nptl/tls.h (tcbhead_t): Rename tm_capable to
	__ununsed1.
	(TLS_INIT_TP, TLS_DEFINE_INIT_TP): Remove tm_capable setup.
	(THREAD_GET_TM_CAPABLE, THREAD_SET_TM_CAPABLE): Remove macros.
	* sysdeps/powerpc/powerpc32/sysdep.h,
	sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION_IMPL,
	ABORT_TRANSACTION): Remove macros.
	* sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/elision-conf.c (elision_init): Set
	__pthread_force_elision iff PPC_FEATURE2_HTM_NOSC is set.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h,
	sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
	sysdeps/unix/sysv/linux/powerpc/syscall.S (ABORT_TRANSACTION): Remove
	usage.
	* sysdeps/unix/sysv/linux/powerpc/not-errno.h: Remove file.

Reported-by: Breno Leitão <leitao@debian.org>
(cherry picked from commit f0458cf4f9)
2019-02-27 17:36:47 +01:00
Jim Wilson 384113d1c0 RISC-V: Fix elfutils testsuite unwind failures.
The clone.S patch fixes 2 elfutils testsuite unwind failures, where the
backtrace gets stuck repeating __thread_start until we hit the backtrace
limit.  This was confirmed by building and installing a patched glibc and
then building elfutils and running its testsuite.

Unfortunately, the testcase isn't working as expected and I don't know why.
The testcase passes even when my clone.S patch is not installed.  The testcase
looks logically similarly to the elfutils testcases that are failing.  Maybe
there is a subtle difference in how the glibc unwinding works versus the
elfutils unwinding?  I don't have good gdb pthread support yet, so I haven't
found a way to debug this.  Anyways, I don't know if the testcase is useful or
not.  If the testcase isn't useful then maybe the clone.S patch is OK without
a testcase?

Jim

	[BZ #24040]
	* elf/Makefile (CFLAGS-tst-unwind-main.c): Add -DUSE_PTHREADS=0.
	* elf/tst-unwind-main.c: If USE_PTHEADS, include pthread.h and error.h
	(func): New.
	(main): If USE_PTHREADS, call pthread_create to run func.  Otherwise
	call func directly.
	* nptl/Makefile (tests): Add tst-unwind-thread.
	(CFLAGS-tst-unwind-thread.c): Define.
	* nptl/tst-unwind-thread.c: New file.
	* sysdeps/unix/sysv/linux/riscv/clone.S (__thread_start): Mark ra
	as undefined.

(cherry picked from commit 85bd1ddbdf)
2019-02-19 06:38:23 +01:00
Carlos O'Donell e8c13d5f7a nptl: Fix pthread_rwlock_try*lock stalls (Bug 23844)
For a full analysis of both the pthread_rwlock_tryrdlock() stall
and the pthread_rwlock_trywrlock() stall see:
https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14

In the pthread_rwlock_trydlock() function we fail to inspect for
PTHREAD_RWLOCK_FUTEX_USED in __wrphase_futex and wake the waiting
readers.

In the pthread_rwlock_trywrlock() function we write 1 to
__wrphase_futex and loose the setting of the PTHREAD_RWLOCK_FUTEX_USED
bit, again failing to wake waiting readers during unlock.

The fix in the case of pthread_rwlock_trydlock() is to check for
PTHREAD_RWLOCK_FUTEX_USED and wake the readers.

The fix in the case of pthread_rwlock_trywrlock() is to only write
1 to __wrphase_futex if we installed the write phase, since all other
readers would be spinning waiting for this step.

We add two new tests, one exercises the stall for
pthread_rwlock_trywrlock() which is easy to exercise, and one exercises
the stall for pthread_rwlock_trydlock() which is harder to exercise.

The pthread_rwlock_trywrlock() test fails consistently without the fix,
and passes after. The pthread_rwlock_tryrdlock() test fails roughly
5-10% of the time without the fix, and passes all the time after.

Signed-off-by: Carlos O'Donell <carlos@redhat.com>
Signed-off-by: Torvald Riegel <triegel@redhat.com>
Signed-off-by: Rik Prohaska <prohaska7@gmail.com>
Co-authored-by: Torvald Riegel <triegel@redhat.com>
Co-authored-by: Rik Prohaska <prohaska7@gmail.com>
(cherry picked from commit 5fc9ed4c40)
2019-02-17 11:44:19 +01:00
Florian Weimer 60f8062425 nptl: Avoid fork handler lock for async-signal-safe fork [BZ #24161]
Commit 27761a1042 ("Refactor atfork
handlers") introduced a lock, atfork_lock, around fork handler list
accesses.  It turns out that this lock occasionally results in
self-deadlocks in malloc/tst-mallocfork2:

(gdb) bt
#0  __lll_lock_wait_private ()
    at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:63
#1  0x00007f160c6f927a in __run_fork_handlers (who=(unknown: 209394016),
    who@entry=atfork_run_prepare) at register-atfork.c:116
#2  0x00007f160c6b7897 in __libc_fork () at ../sysdeps/nptl/fork.c:58
#3  0x00000000004027d6 in sigusr1_handler (signo=<optimized out>)
    at tst-mallocfork2.c:80
#4  sigusr1_handler (signo=<optimized out>) at tst-mallocfork2.c:64
#5  <signal handler called>
#6  0x00007f160c6f92e4 in __run_fork_handlers (who=who@entry=atfork_run_parent)
    at register-atfork.c:136
#7  0x00007f160c6b79a2 in __libc_fork () at ../sysdeps/nptl/fork.c:152
#8  0x0000000000402567 in do_test () at tst-mallocfork2.c:156
#9  0x0000000000402dd2 in support_test_main (argc=1, argv=0x7ffc81ef1ab0,
    config=config@entry=0x7ffc81ef1970) at support_test_main.c:350
#10 0x0000000000402362 in main (argc=<optimized out>, argv=<optimized out>)
    at ../support/test-driver.c:168

If no locking happens in the single-threaded case (where fork is
expected to be async-signal-safe), this deadlock is avoided.
(pthread_atfork is not required to be async-signal-safe, so a fork
call from a signal handler interrupting pthread_atfork is not
a problem.)

(cherry picked from commit 669ff911e2)
2019-02-08 12:55:21 +01:00
Stefan Liebler a9f60b1571 Add compiler barriers around modifications of the robust mutex list for pthread_mutex_trylock. [BZ #24180]
While debugging a kernel warning, Thomas Gleixner, Sebastian Sewior and
Heiko Carstens found a bug in pthread_mutex_trylock due to misordered
instructions:
140:   a5 1b 00 01             oill    %r1,1
144:   e5 48 a0 f0 00 00       mvghi   240(%r10),0   <--- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
14a:   e3 10 a0 e0 00 24       stg     %r1,224(%r10) <--- last THREAD_SETMEM of ENQUEUE_MUTEX_PI

vs (with compiler barriers):
140:   a5 1b 00 01             oill    %r1,1
144:   e3 10 a0 e0 00 24       stg     %r1,224(%r10)
14a:   e5 48 a0 f0 00 00       mvghi   240(%r10),0

Please have a look at the discussion:
"Re: WARN_ON_ONCE(!new_owner) within wake_futex_pi() triggerede"
(https://lore.kernel.org/lkml/20190202112006.GB3381@osiris/)

This patch is introducing the same compiler barriers and comments
for pthread_mutex_trylock as introduced for pthread_mutex_lock and
pthread_mutex_timedlock by commit 8f9450a0b7
"Add compiler barriers around modifications of the robust mutex list."

ChangeLog:

	[BZ #24180]
	* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
	Add compiler barriers and comments.

(cherry picked from commit 823624bdc4)
2019-02-07 15:39:15 +01:00
Aurelien Jarno 85224b0290 NEWS: Mention bug 24112.
The fix has been backported in the commit
37edf1d3f8.
2019-02-04 22:35:41 +01:00
Florian Weimer c533244b8e nscd: Do not use __inet_aton_exact@GLIBC_PRIVATE [BZ #20018]
This commit avoids referencing the __inet_aton_exact@GLIBC_PRIVATE
symbol from nscd.  In master, the separately-compiled getaddrinfo
implementation in nscd needs it, however such an internal ABI change
is not desirable on a release branch if it can be avoided.
2019-02-04 21:36:38 +01:00
Florian Weimer 2373941bd7 CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018]
The IPv4 address parser in the getaddrinfo function is changed so that
it does not ignore trailing whitespace and all characters after it.
For backwards compatibility, the getaddrinfo function still recognizes
legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8
(octal).

This commit does not change the behavior of inet_addr and inet_aton.
gethostbyname already had additional sanity checks (but is switched
over to the new __inet_aton_exact function for completeness as well).

To avoid sending the problematic query names over DNS, commit
6ca53a2453 ("resolv: Do not send queries
for non-host-names in nss_dns [BZ #24112]") is needed.

(cherry picked from commit 108bc4049f)
2019-02-04 21:36:37 +01:00
Florian Weimer 37edf1d3f8 resolv: Do not send queries for non-host-names in nss_dns [BZ #24112]
Before this commit, nss_dns would send a query which did not contain a
host name as the query name (such as invalid\032name.example.com) and
then reject the answer in getanswer_r and gaih_getanswer_slice, using
a check based on res_hnok.  With this commit, no query is sent, and a
host-not-found error is returned to NSS without network interaction.

(cherry picked from commit 6ca53a2453)
2019-02-04 21:35:01 +01:00
Florian Weimer 8e92ca5dd7 resolv: Reformat inet_addr, inet_aton to GNU style
(cherry picked from commit 5e30b8ef07)
2019-02-04 21:35:01 +01:00
H.J. Lu 9aaa083387 x86-64 memcmp: Use unsigned Jcc instructions on size [BZ #24155]
Since the size argument is unsigned. we should use unsigned Jcc
instructions, instead of signed, to check size.

Tested on x86-64 and x32, with and without --disable-multi-arch.

	[BZ #24155]
	CVE-2019-7309
	* NEWS: Updated for CVE-2019-7309.
	* sysdeps/x86_64/memcmp.S: Use RDX_LP for size.  Clear the
	upper 32 bits of RDX register for x32.  Use unsigned Jcc
	instructions, instead of signed.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
	* sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.

(cherry picked from commit 3f635fb433)
2019-02-04 08:56:04 -08:00
H.J. Lu d09b11cbe5 x86-64 strnlen/wcsnlen: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes strnlen/wcsnlen for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strlen-avx2.S: Use RSI_LP for length.
	Clear the upper 32 bits of RSI register.
	* sysdeps/x86_64/strlen.S: Use RSI_LP for length.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strnlen
	and tst-size_t-wcsnlen.
	* sysdeps/x86_64/x32/tst-size_t-strnlen.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wcsnlen.c: Likewise.

(cherry picked from commit 5165de69c0)
2019-02-01 12:24:16 -08:00
H.J. Lu 07a42c0eff x86-64 strncpy: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes strncpy for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: Use RDX_LP
	for length.
	* sysdeps/x86_64/multiarch/strcpy-ssse3.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncpy.
	* sysdeps/x86_64/x32/tst-size_t-strncpy.c: New file.

(cherry picked from commit c7c54f65b0)
2019-02-01 12:23:34 -08:00
H.J. Lu c678b80233 x86-64 strncmp family: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes the strncmp family for x32.  Tested on x86-64 and x32.
On x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strcmp-avx2.S: Use RDX_LP for length.
	* sysdeps/x86_64/multiarch/strcmp-sse42.S: Likewise.
	* sysdeps/x86_64/strcmp.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncasecmp,
	tst-size_t-strncmp and tst-size_t-wcsncmp.
	* sysdeps/x86_64/x32/tst-size_t-strncasecmp.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-strncmp.c: Likewise.
	* sysdeps/x86_64/x32/tst-size_t-wcsncmp.c: Likewise.

(cherry picked from commit ee915088a0)
2019-02-01 12:22:42 -08:00
H.J. Lu 17fc7debcc x86-64 memset/wmemset: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memset/wmemset for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S: Use
	RDX_LP for length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-wmemset.
	* sysdeps/x86_64/x32/tst-size_t-memset.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wmemset.c: Likewise.

(cherry picked from commit 82d0b4a4d7)
2019-02-01 12:21:50 -08:00
H.J. Lu eee0a3d04b x86-64 memrchr: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memrchr for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/memrchr.S: Use RDX_LP for length.
	* sysdeps/x86_64/multiarch/memrchr-avx2.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memrchr.
	* sysdeps/x86_64/x32/tst-size_t-memrchr.c: New file.

(cherry picked from commit ecd8b842cf)
2019-02-01 12:21:03 -08:00
H.J. Lu 781403407b x86-64 memcpy: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memcpy for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memcpy-ssse3-back.S: Use RDX_LP for
	length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memcpy-ssse3.S: Likewise.
	* sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S:
	Likewise.
	* sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:
	Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcpy.
	tst-size_t-wmemchr.
	* sysdeps/x86_64/x32/tst-size_t-memcpy.c: New file.

(cherry picked from commit 231c56760c)
2019-02-01 12:20:16 -08:00
H.J. Lu f57666aa30 x86-64 memcmp/wmemcmp: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memcmp/wmemcmp for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S: Use RDX_LP for
	length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memcmp-sse4.S: Likewise.
	* sysdeps/x86_64/multiarch/memcmp-ssse3.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp and
	tst-size_t-wmemcmp.
	* sysdeps/x86_64/x32/tst-size_t-memcmp.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wmemcmp.c: Likewise.

(cherry picked from commit b304fc201d)
2019-02-01 12:19:20 -08:00
H.J. Lu 492524a691 x86-64 memchr/wmemchr: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memchr/wmemchr for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/memchr.S: Use RDX_LP for length.  Clear the
	upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memchr-avx2.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memchr and
	tst-size_t-wmemchr.
	* sysdeps/x86_64/x32/test-size_t.h: New file.
	* sysdeps/x86_64/x32/tst-size_t-memchr.c: Likewise.
	* sysdeps/x86_64/x32/tst-size_t-wmemchr.c: Likewise.

(cherry picked from commit 97700a34f3)
2019-02-01 12:17:27 -08:00
Tulio Magno Quites Machado Filho b297581acb Add XFAIL_ROUNDING_IBM128_LIBGCC to more fma() tests
Ignore 16 errors in math/test-ldouble-fma and 4 errors in
math/test-ildouble-fma when IBM 128-bit long double used.
These errors are caused by spurious overflows from libgcc.

	* math/libm-test-fma.inc (fma_test_data): Set
	XFAIL_ROUNDING_IBM128_LIBGCC to more tests.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
(cherry picked from commit ecdacd34a2)
2019-01-16 15:55:23 -02:00
Aurelien Jarno 198bfee808 Only build libm with -fno-math-errno (bug 24024)
Commit 1294b1892e ("Add support for sqrt asm redirects") added the
-fno-math-errno flag to build most of the glibc in order to enable GCC
to inline math functions. Due to GCC bug #88576, saving and restoring
errno around calls to malloc are optimized-out. In turn this causes
strerror to set errno to ENOMEM if it get passed an invalid error number
and if malloc sets errno to ENOMEM (which might happen even if it
succeeds). This is not allowed by POSIX.

This patch changes the build flags, building only libm with
-fno-math-errno and all the remaining code with -fno-math-errno. This
should be safe as libm doesn't contain any code saving and restoring
errno around malloc. This patch can probably be reverted once the GCC
bug is fixed and available in stable releases.

Tested on x86-64, no regression in the testsuite.

Changelog:
	[BZ #24024]
	* Makeconfig: Build libm with -fno-math-errno but build the remaining
	code with -fmath-errno.
	* string/Makefile [$(build-shared)] (tests): Add test-strerror-errno.
	[$(build-shared)] (LDLIBS-test-strerror-errno): New variable.
	* string/test-strerror-errno.c: New file.

(cherry picked from commit 2ef4271688)
2019-01-08 21:06:25 +01:00
Martin Jansa 1e5c5303a5 sysdeps/ieee754/soft-fp: ignore maybe-uninitialized with -O [BZ #19444]
* with -O, -O1, -Os it fails with:

In file included from ../soft-fp/soft-fp.h:318,
                 from ../sysdeps/ieee754/soft-fp/s_fdiv.c:28:
../sysdeps/ieee754/soft-fp/s_fdiv.c: In function '__fdiv':
../soft-fp/op-2.h:98:25: error: 'R_f1' may be used uninitialized in this function [-Werror=maybe-uninitialized]
        X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) \
                         ^~
../sysdeps/ieee754/soft-fp/s_fdiv.c:38:14: note: 'R_f1' was declared here
   FP_DECL_D (R);
              ^
../soft-fp/op-2.h:37:36: note: in definition of macro '_FP_FRAC_DECL_2'
   _FP_W_TYPE X##_f0 _FP_ZERO_INIT, X##_f1 _FP_ZERO_INIT
                                    ^
../soft-fp/double.h:95:24: note: in expansion of macro '_FP_DECL'
 # define FP_DECL_D(X)  _FP_DECL (2, X)
                        ^~~~~~~~
../sysdeps/ieee754/soft-fp/s_fdiv.c:38:3: note: in expansion of macro 'FP_DECL_D'
   FP_DECL_D (R);
   ^~~~~~~~~
../soft-fp/op-2.h:101:17: error: 'R_f0' may be used uninitialized in this function [-Werror=maybe-uninitialized]
       : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
                 ^~
../sysdeps/ieee754/soft-fp/s_fdiv.c:38:14: note: 'R_f0' was declared here
   FP_DECL_D (R);
              ^
../soft-fp/op-2.h:37:14: note: in definition of macro '_FP_FRAC_DECL_2'
   _FP_W_TYPE X##_f0 _FP_ZERO_INIT, X##_f1 _FP_ZERO_INIT
              ^
../soft-fp/double.h:95:24: note: in expansion of macro '_FP_DECL'
 # define FP_DECL_D(X)  _FP_DECL (2, X)
                        ^~~~~~~~
../sysdeps/ieee754/soft-fp/s_fdiv.c:38:3: note: in expansion of macro 'FP_DECL_D'
   FP_DECL_D (R);
   ^~~~~~~~~

Build tested with Yocto for ARM, AARCH64, X86, X86_64, PPC, MIPS, MIPS64
with -O, -O1, -Os.
For AARCH64 it needs one more fix in locale for -Os.

	[BZ #19444]
	* sysdeps/ieee754/soft-fp/s_fdiv.c: Include <libc-diag.h> and use
	DIAG_PUSH_NEEDS_COMMENT, DIAG_IGNORE_NEEDS_COMMENT and
	DIAG_POP_NEEDS_COMMENT to disable -Wmaybe-uninitialized.

(cherry picked from commit 4a06ceea33)
2019-01-03 15:13:10 -02:00
Aurelien Jarno 2a8612b278 ARM: fix kernel assisted atomics with GCC 8 (bug 24034)
The pre-ARMv7 CPUs are missing atomic compare and exchange and/or
barrier instructions. Therefore those are implemented using kernel
assistance, calling a kernel function at a specific address, and passing
the arguments in the r0 to r4 registers. This is done by specifying
registers for local variables. The a_ptr variable is placed in the r2
register and declared with __typeof (mem). According to the GCC
documentation on local register variables, if mem is a constant pointer,
the compiler may substitute the variable with its initializer in asm
statements, which may cause the corresponding operand to appear in a
different register.

This happens in __libc_start_main with the pointer to the thread counter
for static binaries (but not the shared ones):

  # ifdef SHARED
        unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
  #  ifdef PTR_DEMANGLE
        PTR_DEMANGLE (ptr);
  #  endif
  # else
        extern unsigned int __nptl_nthreads __attribute ((weak));
        unsigned int *const ptr = &__nptl_nthreads;
  # endif

This causes static binaries using threads to crash when the GNU libc is
built with GCC 8 and most notably tst-cancel21-static.

To fix that, use the same trick than for the volatile qualifier,
defining a_ptr as a union.

Changelog:
	[BZ #24034]
	* sysdeps/unix/sysv/linux/arm/atomic-machine.h
	(__arm_assisted_compare_and_exchange_val_32_acq): Use uint32_t rather
	than __typeof (...) for the a_ptr variable.
(cherry picked from commit fe20bb1d60)
2019-01-03 15:59:14 +01:00
H.J. Lu be62bbb621 riscv: Use __has_include__ to include <asm/syscalls.h> [BZ #24022]
<asm/syscalls.h> has been removed by

commit 27f8899d6002e11a6e2d995e29b8deab5aa9cc25
Author: David Abdurachmanov <david.abdurachmanov@gmail.com>
Date:   Thu Nov 8 20:02:39 2018 +0100

    riscv: add asm/unistd.h UAPI header

    Marcin Juszkiewicz reported issues while generating syscall table for riscv
    using 4.20-rc1. The patch refactors our unistd.h files to match some other
    architectures.

    - Add asm/unistd.h UAPI header, which has __ARCH_WANT_NEW_STAT only for 64-bit
    - Remove asm/syscalls.h UAPI header and merge to asm/unistd.h
    - Adjust kernel asm/unistd.h

    So now asm/unistd.h UAPI header should show all syscalls for riscv.

<asm/syscalls.h> may be restored by

Subject: [PATCH] riscv: restore asm/syscalls.h UAPI header
Date: Tue, 11 Dec 2018 09:09:35 +0100

UAPI header asm/syscalls.h was merged into UAPI asm/unistd.h header,
which did resolve issue with missing syscalls macros resulting in
glibc (2.28) build failure. It also broke glibc in a different way:
asm/syscalls.h is being used by glibc. I noticed this while doing
Fedora 30/Rawhide mass rebuild.

The patch returns asm/syscalls.h header and incl. it into asm/unistd.h.
I plan to send a patch to glibc to use asm/unistd.h instead of
asm/syscalls.h

In the meantime, we use __has_include__, which was added to GCC 5, to
check if <asm/syscalls.h> exists before including it.  Tested with
build-many-glibcs.py for riscv against kernel 4.19.12 and 4.20-rc7.

	[BZ #24022]
	* sysdeps/unix/sysv/linux/riscv/flush-icache.c: Check if
	<asm/syscalls.h> exists with __has_include__ before including it.

(cherry picked from commit 0b9c84906f)
2019-01-03 14:13:32 +01:00
Florian Weimer bee4baf6d7 intl: Do not return NULL on asprintf failure in gettext [BZ #24018]
Fixes commit 9695dd0c93 ("DCIGETTEXT:
Use getcwd, asprintf to construct absolute pathname").

(cherry picked from commit 8c1aafc1f3)
2019-01-02 16:46:12 +01:00
Florian Weimer 8f83d095fa malloc: Always call memcpy in _int_realloc [BZ #24027]
This commit removes the custom memcpy implementation from _int_realloc
for small chunk sizes.  The ncopies variable has the wrong type, and
an integer wraparound could cause the existing code to copy too few
elements (leaving the new memory region mostly uninitialized).
Therefore, removing this code fixes bug 24027.

(cherry picked from commit b50dd3bc8c)
2019-01-01 10:46:55 +01:00
Aurelien Jarno 69b914a99e Update Alpha libm-test-ulps
Changelog:
	* sysdeps/alpha/fpu/libm-test-ulps: Regenerated.
2018-12-28 11:24:48 +01:00
Adhemerval Zanella 27e039455d m68k: Fix sigaction kernel definition (BZ #23967)
Commit b4a5d26d88 (linux: Consolidate sigaction implementation) added
a wrong kernel_sigaction definition for m68k, meant for __NR_sigaction
instead of __NR_rt_sigaction as used on generic Linux sigaction
implementation.  This patch fixes it by using the Linux generic
definition meant for the RT kernel ABI.

Checked the signal tests on emulated m68-linux-gnu (Aranym).  It fixes
the faulty signal/tst-sigaction and man works as expected.

	Adhemerval Zanella  <adhemerval.zanella@linaro.org>
	James Clarke  <jrtc27@jrtc27.com>

	[BZ #23967]
	* sysdeps/unix/sysv/linux/kernel_sigaction.h (HAS_SA_RESTORER):
	Define if SA_RESTORER is defined.
	(kernel_sigaction): Define sa_restorer if HAS_SA_RESTORER is defined.
	(SET_SA_RESTORER, RESET_SA_RESTORER): Define iff the macro are not
	already defined.
	* sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h (SA_RESTORER,
	kernel_sigaction, SET_SA_RESTORER, RESET_SA_RESTORER): Remove
	definitions.
	(HAS_SA_RESTORER): Define.
	* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h (SA_RESTORER,
	SET_SA_RESTORER, RESET_SA_RESTORER): Remove definition.
	(HAS_SA_RESTORER): Define.
	* sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h: Include generic
	kernel_sigaction after define SET_SA_RESTORER and RESET_SA_RESTORER.
	* sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise.

(cherry picked from commit 43a45c2d82)
2018-12-19 08:52:43 -02:00
Andreas Schwab b4ce4476fc RISC-V: properly terminate call chain (bug 23125)
Mark the ra register as undefined in _start, so that unwinding through
main works correctly.  Also, don't use a tail call so that ra points after
the call to __libc_start_main, not after the previous call.

(cherry picked from commit 2dd12baa04)
2018-12-15 21:57:43 +01:00
Florian Weimer 1a8db070fa support: Do not require overflow builtin in support/blob_repeat.c
It is only available in GCC 5 and later.

Tested-by: Romain Naour <romain.naour@gmail.com>
(cherry picked from commit 0c1719e65b)
2018-12-15 19:09:25 +01:00
Andreas Schwab 4d7af7815a Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (bug 23861)
In the read lock function (__pthread_rwlock_rdlock_full) there was a
code path which would fail to reload __readers while waiting for
PTHREAD_RWLOCK_RWAITING to change. This failure to reload __readers
into a local value meant that various conditionals used the old value
of __readers and with only two threads left it could result in an
indefinite stall of one of the readers (waiting for PTHREAD_RWLOCK_RWAITING
to go to zero, but it never would).

(cherry picked from commit f21e8f8ca4)
2018-12-13 11:58:04 -05:00
Tulio Magno Quites Machado Filho 852620258d powerpc: Add missing CFI register information (bug #23614)
Add CFI information about the offset of registers stored in the stack
frame.

	[BZ #23614]
	* sysdeps/powerpc/powerpc64/addmul_1.S (FUNC): Add CFI offset for
	registers saved in the stack frame.
	* sysdeps/powerpc/powerpc64/lshift.S (__mpn_lshift): Likewise.
	* sysdeps/powerpc/powerpc64/mul_1.S (__mpn_mul_1): Likewise.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Reviewed-by: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
(cherry picked from commit 1d880d4a9b)
2018-12-13 09:42:22 +01:00
DJ Delorie ea16a6938d malloc: Add another test for tcache double free check.
This one tests for BZ#23907 where the double free
test didn't check the tcache bin bounds before dereferencing
the bin.

[BZ #23907]
* malloc/tst-tcfree3.c: New.
* malloc/Makefile: Add it.

(cherry picked from commit 7c9a7c6836)
2018-12-12 12:04:12 +01:00
Florian Weimer b5a9a19b82 inet/tst-if_index-long: New test case for CVE-2018-19591 [BZ #23927]
(cherry picked from commit 899478c2bf)
2018-12-12 12:04:12 +01:00
Florian Weimer 4c2dada507 support: Implement <support/descriptors.h> to track file descriptors
(cherry picked from commit f255336a93)
2018-12-12 12:04:10 +01:00
Florian Weimer 874c28c9f5 support: Close original descriptors in support_capture_subprocess
(cherry picked from commit 02cd5c1a8d)
2018-12-12 12:03:36 +01:00
Florian Weimer 9dd07a91db support_quote_string: Do not use str parameter name
This avoids a build failure if this identifier is used as a macro
in a test.

(cherry picked from commit 47d8d9a217)
2018-12-12 12:03:36 +01:00
Florian Weimer 4718b053df support: Implement support_quote_string
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
(cherry picked from commit c74a91deaa)
2018-12-12 12:03:26 +01:00
Florian Weimer 5f1ae50a78 compat getdents64: Use correct offset for retry [BZ #23972]
d_off is the offset of the *next* entry, not the offset of the current
entry.

(cherry picked from commit 8d20a2f414)
2018-12-10 16:50:37 +01:00
Tulio Magno Quites Machado Filho 8c89e6b02d Fix _dl_profile_fixup data-dependency issue (Bug 23690)
There is a data-dependency between the fields of struct l_reloc_result
and the field used as the initialization guard. Users of the guard
expect writes to the structure to be observable when they also observe
the guard initialized. The solution for this problem is to use an acquire
and release load and store to ensure previous writes to the structure are
observable if the guard is initialized.

The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr)
as the initialization guard, making it impossible for some architectures
to load and store it atomically, i.e. hppa and ia64, due to its larger size.

This commit adds an unsigned int to l_reloc_result to be used as the new
initialization guard of the struct, making it possible to load and store
it atomically in all architectures. The fix ensures that the values
observed in l_reloc_result are consistent and do not lead to crashes.
The algorithm is documented in the code in elf/dl-runtime.c
(_dl_profile_fixup). Not all data races have been eliminated.

Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le.

	[BZ #23690]
	* elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory
	modification order when accessing reloc_result->addr.
	* include/link.h (reloc_result): Add field init.
	* nptl/Makefile (tests): Add tst-audit-threads.
	(modules-names): Add tst-audit-threads-mod1 and
	tst-audit-threads-mod2.
	Add rules to build tst-audit-threads.
	* nptl/tst-audit-threads-mod1.c: New file.
	* nptl/tst-audit-threads-mod2.c: Likewise.
	* nptl/tst-audit-threads.c: Likewise.
	* nptl/tst-audit-threads.h: Likewise.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e5d262effe)
2018-12-07 09:05:49 -05:00
DJ Delorie b8dd0f4278 malloc: tcache double free check
* malloc/malloc.c (tcache_entry): Add key field.
(tcache_put): Set it.
(tcache_get): Likewise.
(_int_free): Check for double free in tcache.
* malloc/tst-tcfree1.c: New.
* malloc/tst-tcfree2.c: New.
* malloc/Makefile: Run the new tests.
* manual/probes.texi: Document memory_tcache_double_free probe.

* dlfcn/dlerror.c (check_free): Prevent double frees.

(cherry picked from commit bcdaad21d4)

malloc: tcache: Validate tc_idx before checking for double-frees [BZ #23907]

The previous check could read beyond the end of the tcache entry
array.  If the e->key == tcache cookie check happened to pass, this
would result in crashes.

(cherry picked from commit affec03b71)
2018-11-28 15:45:42 -05:00
Florian Weimer ce6ba630db CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927]
(cherry picked from commit d527c860f5)
2018-11-27 18:40:56 +01:00
Florian Weimer f5cc21eaee Revert "malloc: tcache double free check" [BZ #23907]
This reverts commit 481a6cf0c2, the
backport of commit bcdaad21d4 on the
master branch.
2018-11-22 22:05:57 +01:00
DJ Delorie 481a6cf0c2 malloc: tcache double free check
* malloc/malloc.c (tcache_entry): Add key field.
(tcache_put): Set it.
(tcache_get): Likewise.
(_int_free): Check for double free in tcache.
* malloc/tst-tcfree1.c: New.
* malloc/tst-tcfree2.c: New.
* malloc/Makefile: Run the new tests.
* manual/probes.texi: Document memory_tcache_double_free probe.

* dlfcn/dlerror.c (check_free): Prevent double frees.
2018-11-20 14:01:18 -05:00
Florian Weimer 2c7078bfb9 support: Print timestamps in timeout handler
This is sometimes useful to determine if a test truly got stuck, or if
it was making progress (logging information to standard output) and
was merely slow to finish.

(cherry picked from commit 35e3fbc451)
2018-11-19 15:42:03 +01:00
Szabolcs Nagy 10f1519f6a Increase timeout of libio/tst-readline
Increase timeout from the default 20s to 100s. This test makes close to
20 million syscalls with distribution:

12327675 read
 4143204 lseek
  929475 close
  929471 openat
   92817 fstat
    1431 write
...

The default timeout assumes each can finish in 1us on average which
is not true on slow machines.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

	* libio/tst-readline.c (TIMEOUT): Define.

(cherry picked from commit ed643089cd)
2018-11-19 14:21:24 +01:00
Joseph Myers f44c2ca5ea Update kernel version in syscall-names.list to 4.19.
Linux 4.19 does not add any new syscalls (some existing ones are added
to more architectures); this patch updates the version number in
syscall-names.list to reflect that it's still current for 4.19.

Tested with build-many-glibcs.py.

	* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
	version to 4.19.

(cherry picked from commit 029ad711b8)
2018-11-09 10:17:19 -05:00
Paul Eggert e7388e5134 Fix tzfile low-memory assertion failure
[BZ #21716]
* time/tzfile.c (__tzfile_read): Check for memory exhaustion
when registering time zone abbreviations.

(cherry picked from commit e4e4fde51a)
2018-11-09 10:17:13 -05:00
Paul Pluzhnikov 9071be6b3f [BZ #20271] Add newlines in __libc_fatal calls.
(cherry picked from commit a6e8926f8d)
2018-11-09 10:17:07 -05:00
Florian Weimer 7d174f5353 nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
addinnetgrX may use the heap-allocated buffer, so free the buffer
in this function.

(cherry picked from commit 745664bd79)
2018-11-09 10:17:00 -05:00
Istvan Kurucsai 53a7e59405 malloc: Additional checks for unsorted bin integrity I.
On Thu, Jan 11, 2018 at 3:50 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 11/07/2017 04:27 PM, Istvan Kurucsai wrote:
>>
>> +          next = chunk_at_offset (victim, size);
>
>
> For new code, we prefer declarations with initializers.

Noted.

>> +          if (__glibc_unlikely (chunksize_nomask (victim) <= 2 * SIZE_SZ)
>> +              || __glibc_unlikely (chunksize_nomask (victim) >
>> av->system_mem))
>> +            malloc_printerr("malloc(): invalid size (unsorted)");
>> +          if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
>> +              || __glibc_unlikely (chunksize_nomask (next) >
>> av->system_mem))
>> +            malloc_printerr("malloc(): invalid next size (unsorted)");
>> +          if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) !=
>> size))
>> +            malloc_printerr("malloc(): mismatching next->prev_size
>> (unsorted)");
>
>
> I think this check is redundant because prev_size (next) and chunksize
> (victim) are loaded from the same memory location.

I'm fairly certain that it compares mchunk_size of victim against
mchunk_prev_size of the next chunk, i.e. the size of victim in its
header and footer.

>> +          if (__glibc_unlikely (bck->fd != victim)
>> +              || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
>> +            malloc_printerr("malloc(): unsorted double linked list
>> corrupted");
>> +          if (__glibc_unlikely (prev_inuse(next)))
>> +            malloc_printerr("malloc(): invalid next->prev_inuse
>> (unsorted)");
>
>
> There's a missing space after malloc_printerr.

Noted.

> Why do you keep using chunksize_nomask?  We never investigated why the
> original code uses it.  It may have been an accident.

You are right, I don't think it makes a difference in these checks. So
the size local can be reused for the checks against victim. For next,
leaving it as such avoids the masking operation.

> Again, for non-main arenas, the checks against av->system_mem could be made
> tighter (against the heap size).  Maybe you could put the condition into a
> separate inline function?

We could also do a chunk boundary check similar to what I proposed in
the thread for the first patch in the series to be even more strict.
I'll gladly try to implement either but believe that refining these
checks would bring less benefits than in the case of the top chunk.
Intra-arena or intra-heap overlaps would still be doable here with
unsorted chunks and I don't see any way to counter that besides more
generic measures like randomizing allocations and your metadata
encoding patches.

I've attached a revised version with the above comments incorporated
but without the refined checks.

Thanks,
Istvan

From a12d5d40fd7aed5fa10fc444dcb819947b72b315 Mon Sep 17 00:00:00 2001
From: Istvan Kurucsai <pistukem@gmail.com>
Date: Tue, 16 Jan 2018 14:48:16 +0100
Subject: [PATCH v2 1/1] malloc: Additional checks for unsorted bin integrity
 I.

Ensure the following properties of chunks encountered during binning:
- victim chunk has reasonable size
- next chunk has reasonable size
- next->prev_size == victim->size
- valid double linked list
- PREV_INUSE of next chunk is unset

    * malloc/malloc.c (_int_malloc): Additional binning code checks.

(cherry picked from commit b90ddd08f6)
2018-11-09 10:16:51 -05:00
Moritz Eckert 7e40c3f804 malloc: Mitigate null-byte overflow attacks
* malloc/malloc.c (_int_free): Check for corrupt prev_size vs size.
(malloc_consolidate): Likewise.

(cherry picked from commit d6db68e66d)
2018-11-09 10:16:43 -05:00
Pochang Chen 510a25f2d2 malloc: Verify size of top chunk.
The House of Force is a well-known technique to exploit heap
overflow. In essence, this exploit takes three steps:
1. Overwrite the size of top chunk with very large value (e.g. -1).
2. Request x bytes from top chunk. As the size of top chunk
   is corrupted, x can be arbitrarily large and top chunk will
   still be offset by x.
3. The next allocation from top chunk will thus be controllable.

If we verify the size of top chunk at step 2, we can stop such attack.

(cherry picked from commit 30a17d8c95)
2018-11-09 10:16:35 -05:00
Joseph Myers 168035056e Update syscall-names.list for Linux 4.18.
This patch updates sysdeps/unix/sysv/linux/syscall-names.list for
Linux 4.18.  The io_pgetevents and rseq syscalls are added to the
kernel on various architectures, so need to be mentioned in this file.

Tested with build-many-glibcs.py.

	* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
	version to 4.18.
	(io_pgetevents): New syscall.
	(rseq): Likewise.

(cherry picked from commit 17b26500f9)
2018-11-09 10:16:19 -05:00
Alexandra Hájková b21abc069f Add an additional test to resolv/tst-resolv-network.c
Test for the infinite loop in getnetbyname, bug #17630.

(cherry picked from commit ac8060265b)
2018-11-09 14:38:21 +01:00
H.J. Lu 3e8d8dd5af Check multiple NT_GNU_PROPERTY_TYPE_0 notes [BZ #23509]
Linkers group input note sections with the same name into one output
note section with the same name.  One output note section is placed in
one PT_NOTE segment.  Since new linkers merge input .note.gnu.property
sections into one output .note.gnu.property section, there is only
one NT_GNU_PROPERTY_TYPE_0 note in one PT_NOTE segment with new linkers.
Since older linkers treat input .note.gnu.property section as a generic
note section and just concatenate all input .note.gnu.property sections
into one output .note.gnu.property section without merging them, we may
see multiple NT_GNU_PROPERTY_TYPE_0 notes in one PT_NOTE segment with
older linkers.

When an older linker is used to created the program on CET-enabled OS,
the linker output has a single .note.gnu.property section with multiple
NT_GNU_PROPERTY_TYPE_0 notes, some of which have IBT and SHSTK enable
bits set even if the program isn't CET enabled.  Such programs will
crash on CET-enabled machines.  This patch updates the note parser:

1. Skip note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
2. Check multiple NT_GNU_PROPERTY_TYPE_0 notes.

	[BZ #23509]
	* sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip
	note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
	Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note.
	Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
	* sysdeps/x86/link_map.h (l_cet): Expand to 3 bits,  Add
	lc_unknown.

(cherry picked from commit d524fa6c35)
2018-11-08 10:52:32 -08:00
Andreas Schwab fc0e3393ff libanl: properly cleanup if first helper thread creation failed (bug 22927)
(cherry picked from commit bd3b0fbae3)
2018-11-06 16:12:07 +01:00
Adhemerval Zanella 65010329f2 x86: Fix Haswell CPU string flags (BZ#23709)
Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the
default flags for Haswell models.  Previously, new models were handled by the
default switch path, which assumed a Core i3/i5/i7 if AVX is available. After
the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags
Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and
Prefer_PMINUB_for_stringop (only the TSX one).

This patch fixes it by disentangle the TSX flag handling from the memory
optimization ones.  The strstr case cited on patch now selects the
__strstr_sse2_unaligned as expected for the Haswell cpu.

Checked on x86_64-linux-gnu.

	[BZ #23709]
	* sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits
	independently of other flags.

(cherry picked from commit c3d8dc45c9)
2018-11-02 10:56:00 +01:00
Florian Weimer e1af1df694 stdlib/tst-strtod-overflow: Switch to support_blob_repeat
This is another test with an avoidable large memory allocation.

(cherry picked from commit 07da99aad9)
2018-11-02 10:47:16 +01:00
Florian Weimer 6c2b6e9e27 support_blob_repeat: Call mkstemp directory for the backing file
This avoids a warning during post-test cleanup.

(cherry picked from commit a91e9301c4)
2018-11-02 10:47:16 +01:00
Florian Weimer 69dcd992a0 stdlib/test-bz22786: Avoid memory leaks in the test itself
(cherry picked from commit 6070803053)
2018-11-02 10:47:16 +01:00
Florian Weimer dcd52b94bf stdlib/test-bz22786: Avoid spurious test failures using alias mappings
On systems without enough random-access memory, stdlib/test-bz22786
will go deeply into swap and time out, even with a substantial
TIMEOUTFACTOR.  This commit adds a facility to construct repeating
strings with alias mappings, so that the requirement for physical
memory, and uses it in stdlib/test-bz22786.

(cherry picked from commit f5e7e95921)
2018-11-02 10:47:16 +01:00
Stefan Liebler d0b6db4acf Test stdlib/test-bz22786 exits now with unsupported if malloc fails.
The test tries to allocate more than 2^31 bytes which will always fail on s390
as it has maximum 2^31bit of memory.
Before commit 6c3a8a9d86, this test returned
unsupported if malloc fails.  This patch re enables this behaviour.

Furthermore support_delete_temp_files() failed to remove the temp directory
in this case as it is not empty due to the created symlink.
Thus the creation of the symlink is moved behind malloc.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

ChangeLog:

	* stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED
	if malloc fails.

(cherry picked from commit 3bad2358d6)
2018-11-02 10:47:16 +01:00
Paul Pluzhnikov df11de9193 Fix BZ#23400 (creating temporary files in source tree), and undefined behavior in test.
(cherry picked from commit 6c3a8a9d86)
2018-11-02 10:47:07 +01:00
Szabolcs Nagy 5256ffc51e i64: fix missing exp2f, log2f and powf symbols in libm.a [BZ #23822]
When new symbol versions were introduced without SVID compatible
error handling the exp2f, log2f and powf symbols were accidentally
removed from the ia64 lim.a.  The regression was introduced by
the commits

f5f0f52651
New expf and exp2f version without SVID compat wrapper

72d3d28108
New symbol version for logf, log2f and powf without SVID compat

With WEAK_LIBM_ENTRY(foo), there is a hidden __foo and weak foo
symbol definition in both SHARED and !SHARED build.

	[BZ #23822]
	* sysdeps/ia64/fpu/e_exp2f.S (exp2f): Use WEAK_LIBM_ENTRY.
	* sysdeps/ia64/fpu/e_log2f.S (log2f): Likewise.
	* sysdeps/ia64/fpu/e_exp2f.S (powf): Likewise.

(cherry picked from commit ba5b14c761)
2018-10-26 15:49:30 +01:00
Florian Weimer aff9b37712 conform: XFAIL siginfo_t si_band test on sparc64
We can use long int on sparcv9, but on sparc64, we must match the int
type used by the kernel (and not long int, as in POSIX).

(cherry picked from commit 7c5e34d7f1)
2018-10-26 09:19:40 +02:00
Ilya Yu. Malakhov 69d1e73d99 signal: Use correct type for si_band in siginfo_t [BZ #23562]
(cherry picked from commit f997b4be18)
2018-10-22 13:03:57 +02:00
Stefan Liebler 314e181dc9 Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275]
The race leads either to pthread_mutex_destroy returning EBUSY
or triggering an assertion (See description in bugzilla).

This patch is fixing the race by ensuring that the elision path is
used in all cases if elision is enabled by the GLIBC_TUNABLES framework.

The __kind variable in struct __pthread_mutex_s is accessed concurrently.
Therefore we are now using the atomic macros.

The new testcase tst-mutex10 is triggering the race on s390x and intel.
Presumably also on power, but I don't have access to a power machine
with lock-elision. At least the code for power is the same as on the other
two architectures.

ChangeLog:

	[BZ #23275]
	* nptl/tst-mutex10.c: New File.
	* nptl/Makefile (tests): Add tst-mutex10.
	(tst-mutex10-ENV): New variable.
	* sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION):
	Ensure that elision path is used if elision is available.
	* sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION):
	Likewise.
	* sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION):
	Likewise.
	* nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION)
	(PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed.
	* nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise.
	* nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling):
	Likewise.
	* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full)
	(__pthread_mutex_cond_lock_adjust): Likewise.
	* nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling):
	Likewise.
	* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise.
	* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
	* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
	* sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s):
	Add comments.
	* nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy):
	Use atomic_load_relaxed and atomic_store_relaxed.
	* nptl/pthread_mutex_init.c (__pthread_mutex_init):
	Use atomic_store_relaxed.

(cherry picked from commit 403b4feb22)
2018-10-18 12:36:15 +02:00
H.J. Lu 5a74abda20 i386: Use _dl_runtime_[resolve|profile]_shstk for SHSTK [BZ #23716]
When elf_machine_runtime_setup is called to set up resolver, it should
use _dl_runtime_resolve_shstk or _dl_runtime_profile_shstk if SHSTK is
enabled by kernel.

Tested on i686 with and without --enable-cet as well as on CET emulator
with --enable-cet.

	[BZ #23716]
	* sysdeps/i386/dl-cet.c: Removed.
	* sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New
	prototype.
	(_dl_runtime_profile_shstk): Likewise.
	(elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or
	_dl_runtime_resolve_shstk if SHSTK is enabled by kernel.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 7b1f940676)
2018-10-09 19:35:50 -07:00
Rafal Luzynski 5473739a7b kl_GL: Fix spelling of Sunday, should be "sapaat" (bug 20209).
Although CLDR says otherwise, it is confirmed by Oqaasileriffik, the
official Greenlandic language regulator, that this change is correct.

	[BZ #20209]
	* localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday),
	should be "sap" rather than "sab".
	(day): Fix spelling of Sunday, should be "sapaat" rather than
	"sabaat".

(cherry picked from commit dae3ed958c)
2018-10-09 00:50:20 +02:00
Adhemerval Zanella 044c96f0d5 Fix misreported errno on preadv2/pwritev2 (BZ#23579)
The fallback code of Linux wrapper for preadv2/pwritev2 executes
regardless of the errno code for preadv2, instead of the case where
the syscall is not supported.

This fixes it by calling the fallback code iff errno is ENOSYS. The
patch also adds tests for both invalid file descriptor and invalid
iov_len and vector count.

The only discrepancy between preadv2 and fallback code regarding
error reporting is when an invalid flags are used.  The fallback code
bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall
is used.

Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel.

	[BZ #23579]
	* misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New
	test.
	* misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test):
	Call do_test_with_invalid_fd.
	* sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff
	errno is ENOSYS.
	* sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise.
	* sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise.
	* sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise.

(cherry picked from commit 7a16bdbb9f)
2018-09-28 15:32:43 -03:00
Andreas Schwab 3a67c72c15 Fix stack overflow in tst-setcontext9 (bug 23717)
The function f1a, executed on a stack of size 32k, allocates an object of
size 32k on the stack.  Make the stack variables static to reduce
excessive stack usage.

(cherry picked from commit f841c97e51)
2018-09-27 12:37:06 +02:00
H.J. Lu 2339d6a55e i386: Use ENTRY and END in start.S [BZ #23606]
Wrapping the _start function with ENTRY and END to insert ENDBR32 at
function entry when CET is enabled.  Since _start now includes CFI,
without "cfi_undefined (eip)", unwinder may not terminate at _start
and we will get

Program received signal SIGSEGV, Segmentation fault.
0xf7dc661e in ?? () from /lib/libgcc_s.so.1
Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-3.0.fc28.i686
(gdb) bt
 #0  0xf7dc661e in ?? () from /lib/libgcc_s.so.1
 #1  0xf7dc7c18 in _Unwind_Backtrace () from /lib/libgcc_s.so.1
 #2  0xf7f0d809 in __GI___backtrace (array=array@entry=0xffffc7d0,
    size=size@entry=20) at ../sysdeps/i386/backtrace.c:127
 #3  0x08049254 in compare (p1=p1@entry=0xffffcad0, p2=p2@entry=0xffffcad4)
    at backtrace-tst.c:12
 #4  0xf7e2a28c in msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0,
    n=n@entry=2) at msort.c:65
 #5  0xf7e29f64 in msort_with_tmp (n=2, b=0xffffcad0, p=0xffffca5c)
    at msort.c:53
 #6  msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=5)
    at msort.c:53
 #7  0xf7e29f64 in msort_with_tmp (n=5, b=0xffffcad0, p=0xffffca5c)
    at msort.c:53
 #8  msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=10)
    at msort.c:53
 #9  0xf7e29f64 in msort_with_tmp (n=10, b=0xffffcad0, p=0xffffca5c)
    at msort.c:53
 #10 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=20)
    at msort.c:53
 #11 0xf7e2a5b6 in msort_with_tmp (n=20, b=0xffffcad0, p=0xffffca5c)
    at msort.c:297
 #12 __GI___qsort_r (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
    cmp=cmp@entry=0x8049230 <compare>, arg=arg@entry=0x0) at msort.c:297
 #13 0xf7e2a84d in __GI_qsort (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
    cmp=cmp@entry=0x8049230 <compare>) at msort.c:308
 #14 0x080490f6 in main (argc=2, argv=0xffffcbd4) at backtrace-tst.c:39

FAIL: debug/backtrace-tst

	[BZ #23606]
	* sysdeps/i386/start.S: Include <sysdep.h>
	(_start): Use ENTRY/END to insert ENDBR32 at entry when CET is
	enabled.  Add cfi_undefined (eip).

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>

(cherry picked from commit 5a274db4ea)
2018-09-21 04:32:22 -07:00
Wilco Dijkstra 0ef2f4400c Fix strstr bug with huge needles (bug 23637)
The generic strstr in GLIBC 2.28 fails to match huge needles.  The optimized
AVAILABLE macro reads ahead a large fixed amount to reduce the overhead of
repeatedly checking for the end of the string.  However if the needle length
is larger than this, two_way_long_needle may confuse this as meaning the end
of the string and return NULL.  This is fixed by adding the needle length to
the amount to read ahead.

	[BZ #23637]
	* string/test-strstr.c (pr23637): New function.
	(test_main): Add tests with longer needles.
	* string/strcasestr.c (AVAILABLE): Fix readahead distance.
	* string/strstr.c (AVAILABLE): Likewise.

    (cherry picked from commit 83a552b0bb)
2018-09-21 12:09:38 +01:00
Carlos O'Donell a55e109709 Fix tst-setcontext9 for optimized small stacks.
If the compiler reduces the stack usage in function f1 before calling
into function f2, then when we swapcontext back to f1 and continue
execution we may overwrite registers that were spilled to the stack
while f2 was executing.  Later when we return to f2 the corrupt
registers will be reloaded from the stack and the test will crash.  This
was most commonly observed on i686 with __x86.get_pc_thunk.dx and
needing to save and restore $edx.  Overall i686 has few registers and
the spilling to the stack is bound to happen, therefore the solution to
making this test robust is to split function f1 into two parts f1a and
f1b, and allocate f1b it's own stack such that subsequent execution does
not overwrite the stack in use by function f2.

Tested on i686 and x86_64.

Signed-off-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 791b350dc7)
2018-09-20 17:03:28 +02:00
Florian Weimer 307d04334d misc: New test misc/tst-gethostid
The empty /etc/hosts file used to trigger bug 23679.

(cherry picked from commit db9a8ad4ff)
2018-09-20 12:41:17 +02:00
Mingli Yu e7d22db29c Linux gethostid: Check for NULL value from gethostbyname_r [BZ #23679]
A NULL value can happen with certain gethostbyname_r failures.

(cherry picked from commit 1214ba06e6)
2018-09-20 12:41:13 +02:00
Stefan Liebler 1fe2b9ca8a Fix segfault in maybe_script_execute.
If glibc is built with gcc 8 and -march=z900,
the testcase posix/tst-spawn4-compat crashes with a segfault.

In function maybe_script_execute, the new_argv array is dynamically
initialized on stack with (argc + 1) elements.
The function wants to add _PATH_BSHELL as the first argument
and writes out of bounds of new_argv.
There is an off-by-one because maybe_script_execute fails to count
the terminating NULL when sizing new_argv.

ChangeLog:

	* sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
	Increment size of new_argv by one.

(cherry picked from commit 28669f86f6)
2018-09-10 14:22:52 +02:00
Florian Weimer 0b79004569 regex: Add test tst-regcomp-truncated [BZ #23578]
(cherry picked from commit 761404b74d)
2018-08-28 21:55:13 +02:00
Paul Eggert 58559f1443 regex: fix uninitialized memory access
I introduced this bug into gnulib in commit
8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10;
eventually it was merged into glibc.  The bug was found by
project-repo <bugs@feusi.co> and reported here:
https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html
Diagnosis and draft fix reported by Assaf Gordon here:
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html
* posix/regex_internal.c (build_wcs_upper_buffer):
Fix bug when mbrtowc returns 0.

(cherry picked from commit bc680b3369)
2018-08-28 21:54:28 +02:00
Martin Kuchta aa8a3e4cde pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538]
(cherry picked from commit 99ea93ca31)
2018-08-27 18:54:46 +02:00
DJ Delorie c87b5bab24 Improve ChangeLog message.
(cherry picked from commit e5721f45f6)
2018-08-22 18:56:05 +02:00
DJ Delorie 66fdfd57fe Regen RISC-V rvd ULPs
* sysdeps/riscv/rv64/rvd/libm-test-ulps: Update.

Note: I regen'd these from scratch, but I'm only committing the
increases, as I only tested on hardware.  There were a few 2->1
decreases that I omitted, possibly "for now".

(cherry picked from commit bb17621ab8)
2018-08-22 18:55:44 +02:00
DJ Delorie b0aa03dfff RISC-V: Fix rounding save/restore bug.
* sysdeps/riscv/rvf/math_private.h (libc_feholdexcept_setround_riscv):
Fix rounding save-restore bug.

Fixes about a hundred off-by-ULP failures in the math testsuite.

(cherry picked from commit bf41818787)
2018-08-22 18:55:30 +02:00
Florian Weimer 2f498f3d14 nss_files: Fix file stream leak in aliases lookup [BZ #23521]
In order to get a clean test case, it was necessary to fix partially
fixed bug 23522 as well.

(cherry picked from commit e95c6f6192)
2018-08-14 10:57:48 +02:00
Florian Weimer bfcfa22589 nscd: Deallocate existing user names in file parser
This avoids a theoretical memory leak (theoretical because it depends on
multiple server-user/stat-user directives in the configuration file).

(cherry picked from commit 2d7acfac3e)
2018-08-14 10:57:05 +02:00
Florian Weimer d05b05d157 error, error_at_line: Add missing va_end calls
(cherry picked from commit b7b52b9dec)
2018-08-14 10:41:04 +02:00
Florian Weimer 4b25485f03 Linux: Rewrite __old_getdents64 [BZ #23497]
Commit 298d0e3129 ("Consolidate Linux
getdents{64} implementation") broke the implementation because it does
not take into account struct offset differences.

The new implementation is close to the old one, before the
consolidation, but has been cleaned up slightly.

(cherry picked from commit 690652882b)
2018-08-10 11:19:26 +02:00
Samuel Thibault 726e1554ce hurd: Avoid PLTs for __pthread_get/setspecific
* sysdeps/htl/pthreadP.h [IS_IN (libpthread)] (__pthread_getspecific,
__pthread_setspecific): Add hidden proto.
* sysdeps/htl/pt-getspecific.c (__pthread_getspecific): Add hidden def.
* sysdeps/htl/pt-setspecific.c (__pthread_setspecific): Add hidden def.
2018-08-09 01:30:13 +02:00
Samuel Thibault 7f11842e74 hurd: Add missing symbols for proper libc_get/setspecific
* htl/Versions (__pthread_getspecific, __pthread_setspecific): Add
	symbols.
2018-08-08 02:17:39 +02:00
435 changed files with 18886 additions and 4025 deletions
+1107
View File
File diff suppressed because it is too large Load Diff
+27 -4
View File
@@ -42,6 +42,22 @@ else
objdir must be defined by the build-directory Makefile.
endif
# Did we request 'make -s' run? "yes" or "no".
# Starting from make-4.4 MAKEFLAGS now contains long
# options like '--shuffle'. To detect presence of 's'
# we pick first word with short options. Long options
# are guaranteed to come after whitespace. We use '-'
# prefix to always have a word before long options
# even if no short options were passed.
# Typical MAKEFLAGS values to watch for:
# "rs --shuffle=42" (silent)
# " --shuffle" (not silent)
ifeq ($(findstring s, $(firstword -$(MAKEFLAGS))),)
silent-make := no
else
silent-make := yes
endif
# Root of the sysdeps tree.
sysdep_dir := $(..)sysdeps
export sysdep_dir := $(sysdep_dir)
@@ -546,8 +562,13 @@ ifeq (yes,$(build-shared))
link-libc-rpath = -Wl,-rpath=$(rpath-link)
link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
# build-hardcoded-path-in-tests. Add -Wl,--disable-new-dtags to force
# DT_RPATH instead of DT_RUNPATH which only applies to DT_NEEDED entries
# in the executable and doesn't applies to DT_NEEDED entries in shared
# libraries which are loaded via DT_NEEDED entries in the executable.
ifeq (yes,$(build-hardcoded-path-in-tests))
link-libc-tests-rpath-link = $(link-libc-rpath)
link-libc-tests-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
else
link-libc-tests-rpath-link = $(link-libc-rpath-link)
endif # build-hardcoded-path-in-tests
@@ -831,8 +852,10 @@ endif
# disable any optimization that assume default rounding mode.
+math-flags = -frounding-math
# Build libc/libm using -fno-math-errno, but run testsuite with -fmath-errno.
+extra-math-flags = $(if $(filter libnldbl nonlib testsuite,$(in-module)),-fmath-errno,-fno-math-errno)
# Logically only "libnldbl", "nonlib" and "testsuite" should be using
# -fno-math-errno. However due to GCC bug #88576, only "libm" can use
# -fno-math-errno.
+extra-math-flags = $(if $(filter libm,$(in-module)),-fno-math-errno,-fmath-errno)
# We might want to compile with some stack-protection flag.
ifneq ($(stack-protector),)
@@ -878,7 +901,7 @@ endif
# umpteen zillion filenames along with it (we use `...' instead)
# but we don't want this echoing done when the user has said
# he doesn't want to see commands echoed by using -s.
ifneq "$(findstring s,$(MAKEFLAGS))" "" # if -s
ifeq ($(silent-make),yes) # if -s
+cmdecho := echo >/dev/null
else # not -s
+cmdecho := echo
+2 -2
View File
@@ -875,7 +875,7 @@ endif
# Maximize efficiency by minimizing the number of rules.
.SUFFIXES: # Clear the suffix list. We don't use suffix rules.
# Don't define any builtin rules.
MAKEFLAGS := $(MAKEFLAGS)r
MAKEFLAGS := $(MAKEFLAGS) -r
# Generic rule for making directories.
%/:
@@ -892,7 +892,7 @@ MAKEFLAGS := $(MAKEFLAGS)r
.PRECIOUS: $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
# Use the verbose option of ar and tar when not running silently.
ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s
ifeq ($(silent-make),no) # if not -s
verbose := v
else # -s
verbose :=
+124
View File
@@ -4,6 +4,128 @@ 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.28.1
Major new features:
* The entry for the new Japanese era has been added for ja_JP locale.
Deprecated and removed features, and other changes affecting compatibility:
* For powercp64le ABI, Transactional Lock Elision is now enabled iff kernel
indicates that it will abort the transaction prior to entering the kernel
(PPC_FEATURE2_HTM_NOSC on hwcap2). On older kernels the transaction is
suspended, and this caused some undefined side-effects issues by aborting
transactions manually. Glibc avoided it by abort transactions manually on
each syscall, but it lead to performance issues on newer kernels where the
HTM state is saved and restore lazily (the state being saved even when the
process actually does not use HTM).
* The copy_file_range function fails with ENOSYS if the kernel does not
support the system call of the same name. Previously, user space
emulation was performed, but its behavior did not match the kernel
behavior, which was deemed too confusing. Applications which use the
copy_file_range function will have to be run on kernels which implement
the copy_file_range system call. Support for most architectures was added
in version 4.5 of the mainline Linux kernel.
The following bugs are resolved with this release:
[14231] stdio-common tests memory requirements
[18035] Fix pldd hang
[19444] build failures with -O1 due to -Wmaybe-uninitialized
[20018] getaddrinfo should reject IP addresses with trailing characters
[20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT
[20209] localedata: Spelling mistake for Sunday in Greenlandic kl_GL
[20568] Fix crash in _IO_wfile_sync
[22927] libanl: properly cleanup if first helper thread creation failed
[23400] stdlib/test-bz22786.c creates temporary files in glibc source tree
[23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream
[23509] CET enabled glibc is incompatible with the older linker
[23521] nss_files aliases database file stream leak
[23538] pthread_cond_broadcast: Fix waiters-after-spinning case
[23562] signal: Use correct type for si_band in siginfo_t
[23578] regex: Fix memory overread in re_compile_pattern
[23579] libc: Errors misreported in preadv2
[23606] Missing ENDBR32 in sysdeps/i386/start.S
[23614] powerpc: missing CFI register information in __mpn_* functions
[23679] gethostid: Missing NULL check for gethostbyname_r result
[23709] Fix CPU string flags for Haswell-type CPUs
[23717] Fix stack overflow in stdlib/tst-setcontext9
[23821] si_band in siginfo_t has wrong type long int on sparc64
[23822] ia64 static libm.a is missing exp2f, log2f and powf symbols
[23864] libc: [riscv] missing kernel-features.h undefines
[23844] pthread_rwlock_trywrlock results in hang
[23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591)
[23972] __old_getdents64 uses wrong d_off value on overflow
[24018] gettext may return NULL
[24022] riscv may lack <asm/syscalls.h>
[24024] strerror() might set errno to ENOMEM due to -fno-math-error
[24027] malloc: Integer overflow in realloc
[24034] tst-cancel21-static fails with SIGBUS on pre-ARMv7 when using GCC 8
[24040] riscv64: unterminated call chain in __thread_start
[24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488)
[24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
[24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
[24228] old x86 applications that use legacy libio crash on exit
[24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once)
[24744] io: Remove the copy_file_range emulation.
[25203] libio: Disable vtable validation for pre-2.1 interposed handles
[25204] Ignore LD_PREFER_MAP_32BIT_EXEC for SUID programs
[25225] ld.so fails to link on x86 if GCC defaults to -fcf-protection
[25232] No const correctness for strchr et al. for Clang++
[25414] 'glob' use-after-free bug (CVE-2020-1752)
[25423] Array overflow in backtrace on powerpc
[25933] Off by one error in __strncmp_avx2
[25691] stdio: Remove memory leak from multibyte conversion
[26211] printf integer overflow calculating allocation size
[27130] "rep movsb" performance issue
[27177] GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on doesn't work
[27457] vzeroupper use in AVX2 multiarch string functions cause HTM aborts
[27974] Overflow bug in some implementation of wcsnlen, wmemchr, and wcsncat
[28755] overflow bug in wcsncmp_avx2 and wcsncmp_evex
[28896] strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on non-rtm
variants when avoiding overflow
[29530] segfault in printf handling thousands separator
Security related changes:
CVE-2018-19591: A file descriptor leak in if_nametoindex can lead to a
denial of service due to resource exhaustion when processing getaddrinfo
calls with crafted host names. Reported by Guido Vranken.
CVE-2019-6488: On x32, the size_t parameter may be passed in the lower
32 bits of a 64-bit register with with non-zero upper 32 bit. When it
happened, accessing the 32-bit size_t value as the full 64-bit register
in the assembly string/memory functions would cause a buffer overflow.
Reported by H.J. Lu.
CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
size. For x86-64, memcmp on an object size larger than SSIZE_MAX
has undefined behavior. On x32, the size_t argument may be passed
in the lower 32 bits of the 64-bit RDX register with non-zero upper
32 bits. When it happened with the sign bit of RDX register set,
memcmp gave the wrong result since it treated the size argument as
zero. Reported by H.J. Lu.
CVE-2016-10739: The getaddrinfo function could successfully parse IPv4
addresses with arbitrary trailing characters, potentially leading to data
or command injection issues in applications.
CVE-2019-9169: Attempted case-insensitive regular-expression match
via proceed_next_node in posix/regexec.c leads to heap-based buffer
over-read. Reported by Hongxu Chen.
CVE-2019-19126: ld.so failed to ignore the LD_PREFER_MAP_32BIT_EXEC
environment variable during program execution after a security
transition, allowing local attackers to restrict the possible mapping
addresses for loaded libraries and thus bypass ASLR for a setuid
program. Reported by Marcin Kościelnicki.
CVE-2020-1752: A use-after-free vulnerability in the glob function when
expanding ~user has been fixed.
Version 2.28
@@ -422,6 +544,8 @@ The following bugs are resolved with this release:
[23459] libc: COMMON_CPUID_INDEX_80000001 isn't populated for Intel
processors
[23467] dynamic-link: x86/CET: A property note parser bug
[24112] network: Do not send DNS queries for non-host names (where all
answers will be rejected)
Version 2.27
Vendored
+22 -1
View File
@@ -3762,11 +3762,32 @@ else
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
#ifndef __CET__
#error no CET compiler support
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
libc_cv_compiler_default_cet=yes
else
libc_cv_compiler_default_cet=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Check whether --enable-cet was given.
if test "${enable_cet+set}" = set; then :
enableval=$enable_cet; enable_cet=$enableval
else
enable_cet=no
enable_cet=$libc_cv_compiler_default_cet
fi
+8 -1
View File
@@ -464,11 +464,18 @@ AC_ARG_ENABLE([mathvec],
[build_mathvec=$enableval],
[build_mathvec=notset])
AC_TRY_COMPILE([], [
#ifndef __CET__
# error no CET compiler support
#endif],
[libc_cv_compiler_default_cet=yes],
[libc_cv_compiler_default_cet=no])
AC_ARG_ENABLE([cet],
AC_HELP_STRING([--enable-cet],
[enable Intel Control-flow Enforcement Technology (CET), x86 only]),
[enable_cet=$enableval],
[enable_cet=no])
[enable_cet=$libc_cv_compiler_default_cet])
# We keep the original values in `$config_*' and never modify them, so we
# can write them unchanged into config.make. Everything else uses
+2 -1
View File
@@ -172,7 +172,8 @@ element siginfo_t pid_t si_pid
element siginfo_t uid_t si_uid
element siginfo_t {void*} si_addr
element siginfo_t int si_status
element siginfo_t long si_band
// Bug 23821: si_band has type int on sparc64.
xfail[sparc64-linux]-element siginfo_t long si_band
# endif
# ifndef XPG42
element siginfo_t {union sigval} si_value
+2 -1
View File
@@ -46,7 +46,8 @@ element siginfo_t pid_t si_pid
element siginfo_t uid_t si_uid
element siginfo_t {void*} si_addr
element siginfo_t int si_status
element siginfo_t long si_band
// Bug 23821: si_band has type int on sparc64.
xfail[sparc64-linux]-element siginfo_t long si_band
# ifndef XPG42
element siginfo_t {union sigval} si_value
# endif
+2
View File
@@ -168,6 +168,8 @@ extra-libs-others = $(extra-libs)
libSegFault-routines = segfault
libSegFault-inhibit-o = $(filter-out .os,$(object-suffixes))
# libSegFault.so installs a signal handler in its ELF constructor.
LDFLAGS-SegFault.so = -Wl,--enable-new-dtags,-z,nodelete
libpcprofile-routines = pcprofile
libpcprofile-inhibit-o = $(filter-out .os,$(object-suffixes))
+12
View File
@@ -88,6 +88,18 @@ handle_signal (int signum)
}
/* Symbol names are not available for static functions, so we do not
check do_test. */
/* Check that backtrace does not return more than what fits in the array
(bug 25423). */
for (int j = 0; j < NUM_FUNCTIONS; j++)
{
n = backtrace (addresses, j);
if (n > j)
{
FAIL ();
return;
}
}
}
NO_INLINE int
+25 -9
View File
@@ -72,9 +72,16 @@ __dlerror (void)
__libc_once (once, init);
/* Get error string. */
result = (struct dl_action_result *) __libc_getspecific (key);
if (result == NULL)
result = &last_result;
if (static_buf != NULL)
result = static_buf;
else
{
/* init () has been run and we don't use the static buffer.
So we have a valid key. */
result = (struct dl_action_result *) __libc_getspecific (key);
if (result == NULL)
result = &last_result;
}
/* Test whether we already returned the string. */
if (result->returned != 0)
@@ -198,7 +205,10 @@ check_free (struct dl_action_result *rec)
Dl_info info;
if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0)
#endif
free ((char *) rec->errstring);
{
free ((char *) rec->errstring);
rec->errstring = NULL;
}
}
}
@@ -227,13 +237,19 @@ free_key_mem (void *mem)
void
__dlerror_main_freeres (void)
{
void *mem;
/* Free the global memory if used. */
check_free (&last_result);
/* Free the TSD memory if used. */
mem = __libc_getspecific (key);
if (mem != NULL)
free_key_mem (mem);
if (__libc_once_get (once) && static_buf == NULL)
{
/* init () has been run and we don't use the static buffer.
So we have a valid key. */
void *mem;
/* Free the TSD memory if used. */
mem = __libc_getspecific (key);
if (mem != NULL)
free_key_mem (mem);
}
}
struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
+6 -3
View File
@@ -186,7 +186,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
tst-unwind-main
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -1266,6 +1267,8 @@ CFLAGS-ifuncmain5pie.c += $(pie-ccflag)
CFLAGS-ifuncmain6pie.c += $(pie-ccflag)
CFLAGS-ifuncmain7pie.c += $(pie-ccflag)
LDFLAGS-ifuncmain6pie = -Wl,-z,lazy
$(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so
$(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o
$(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so
@@ -1450,8 +1453,6 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \
LD_HWCAP_MASK=0x1
tst-env-setuid-tunables-ENV = \
GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096
$(objpfx)tst-debug1: $(libdl)
$(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so
@@ -1484,3 +1485,5 @@ tst-libc_dlvsym-static-ENV = \
$(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
CFLAGS-tst-unwind-main.c += -funwind-tables -DUSE_PTHREADS=0
+14 -4
View File
@@ -1173,6 +1173,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
goto call_lose;
}
/* dlopen of an executable is not valid because it is not possible
to perform proper relocations, handle static TLS, or run the
ELF constructors. For PIE, the check needs the dynamic
section, so there is another check below. */
if (__glibc_unlikely (type != ET_DYN)
&& __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))
{
@@ -1209,9 +1213,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
elf_get_dynamic_info (l, NULL);
/* Make sure we are not dlopen'ing an object that has the
DF_1_NOOPEN flag set. */
if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
&& (mode & __RTLD_DLOPEN))
DF_1_NOOPEN flag set, or a PIE object. */
if ((__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN)
&& (mode & __RTLD_DLOPEN))
|| (__glibc_unlikely (l->l_flags_1 & DF_1_PIE)
&& __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0)))
{
/* We are not supposed to load this object. Free all resources. */
_dl_unmap_segments (l);
@@ -1222,7 +1228,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
if (l->l_phdr_allocated)
free ((void *) l->l_phdr);
errstring = N_("shared object cannot be dlopen()ed");
if (l->l_flags_1 & DF_1_PIE)
errstring
= N_("cannot dynamically load position-independent executable");
else
errstring = N_("shared object cannot be dlopen()ed");
goto call_lose;
}
+6 -2
View File
@@ -292,8 +292,6 @@ dl_open_worker (void *a)
_dl_debug_state ();
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
_dl_open_check (new);
/* Print scope information. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
_dl_show_scope (new, 0);
@@ -366,6 +364,12 @@ dl_open_worker (void *a)
_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
}
/* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE
object when _dl_open_check throws an exception. Move it after
relocation to avoid leaving the NODELETE object mapped without
relocation. */
_dl_open_check (new);
/* If the file is not loaded now as a dependency, add the search
list of the newly loaded object to the scope. */
bool any_tls = false;
+43 -5
View File
@@ -183,10 +183,36 @@ _dl_profile_fixup (
/* This is the address in the array where we store the result of previous
relocations. */
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
DL_FIXUP_VALUE_TYPE value = *resultp;
if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
/* CONCURRENCY NOTES:
Multiple threads may be calling the same PLT sequence and with
LD_AUDIT enabled they will be calling into _dl_profile_fixup to
update the reloc_result with the result of the lazy resolution.
The reloc_result guard variable is reloc_init, and we use
acquire/release loads and store to it to ensure that the results of
the structure are consistent with the loaded value of the guard.
This does not fix all of the data races that occur when two or more
threads read reloc_result->reloc_init with a value of zero and read
and write to that reloc_result concurrently. The expectation is
generally that while this is a data race it works because the
threads write the same values. Until the data races are fixed
there is a potential for problems to arise from these data races.
The reloc result updates should happen in parallel but there should
be an atomic RMW which does the final update to the real result
entry (see bug 23790).
The following code uses reloc_result->init set to 0 to indicate if it is
the first time this object is being relocated, otherwise 1 which
indicates the object has already been relocated.
Reading/Writing from/to reloc_result->reloc_init must not happen
before previous writes to reloc_result complete as they could
end-up with an incomplete struct. */
DL_FIXUP_VALUE_TYPE value;
unsigned int init = atomic_load_acquire (&reloc_result->init);
if (init == 0)
{
/* This is the first time we have to relocate this object. */
const ElfW(Sym) *const symtab
@@ -346,19 +372,31 @@ _dl_profile_fixup (
/* Store the result for later runs. */
if (__glibc_likely (! GLRO(dl_bind_not)))
*resultp = value;
{
reloc_result->addr = value;
/* Guarantee all previous writes complete before
init is updated. See CONCURRENCY NOTES earlier */
atomic_store_release (&reloc_result->init, 1);
}
init = 1;
}
else
value = reloc_result->addr;
/* By default we do not call the pltexit function. */
long int framesize = -1;
#ifdef SHARED
/* Auditing checkpoint: report the PLT entering and allow the
auditors to change the value. */
if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
if (GLRO(dl_naudit) > 0
/* Don't do anything if no auditor wants to intercept this call. */
&& (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
{
/* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
initialized earlier in this function or in another thread. */
assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB])
+ reloc_result->boundndx);
+26 -30
View File
@@ -178,6 +178,7 @@ parse_tunables (char *tunestr, char *valstring)
return;
char *p = tunestr;
size_t off = 0;
while (true)
{
@@ -191,7 +192,11 @@ parse_tunables (char *tunestr, char *valstring)
/* If we reach the end of the string before getting a valid name-value
pair, bail out. */
if (p[len] == '\0')
return;
{
if (__libc_enable_secure)
tunestr[off] = '\0';
return;
}
/* We did not find a valid name-value pair before encountering the
colon. */
@@ -217,35 +222,28 @@ parse_tunables (char *tunestr, char *valstring)
if (tunable_is_name (cur->name, name))
{
/* If we are in a secure context (AT_SECURE) then ignore the tunable
unless it is explicitly marked as secure. Tunable values take
precendence over their envvar aliases. */
/* If we are in a secure context (AT_SECURE) then ignore the
tunable unless it is explicitly marked as secure. Tunable
values take precedence over their envvar aliases. We write
the tunables that are not SXID_ERASE back to TUNESTR, thus
dropping all SXID_ERASE tunables and any invalid or
unrecognized tunables. */
if (__libc_enable_secure)
{
if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
{
if (p[len] == '\0')
{
/* Last tunable in the valstring. Null-terminate and
return. */
*name = '\0';
return;
}
else
{
/* Remove the current tunable from the string. We do
this by overwriting the string starting from NAME
(which is where the current tunable begins) with
the remainder of the string. We then have P point
to NAME so that we continue in the correct
position in the valstring. */
char *q = &p[len + 1];
p = name;
while (*q != '\0')
*name++ = *q++;
name[0] = '\0';
len = 0;
}
if (off > 0)
tunestr[off++] = ':';
const char *n = cur->name;
while (*n != '\0')
tunestr[off++] = *n++;
tunestr[off++] = '=';
for (size_t j = 0; j < len; j++)
tunestr[off++] = value[j];
}
if (cur->security_level != TUNABLE_SECLEVEL_NONE)
@@ -258,9 +256,7 @@ parse_tunables (char *tunestr, char *valstring)
}
}
if (p[len] == '\0')
return;
else
if (p[len] != '\0')
p += len + 1;
}
}
+5
View File
@@ -85,6 +85,11 @@ glibc {
tcache_unsorted_limit {
type: SIZE_T
}
mxfast {
type: SIZE_T
minval: 0
security_level: SXID_IGNORE
}
}
tune {
hwcap_mask {
+7
View File
@@ -2847,6 +2847,13 @@ enum
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
/* AArch64 specific values for the Dyn d_tag field. */
#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5)
#define DT_AARCH64_NUM 6
/* AArch64 specific values for the st_other field. */
#define STO_AARCH64_VARIANT_PCS 0x80
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
+13
View File
@@ -19,7 +19,14 @@ typedef int (*foo_p) (void);
#endif
foo_p foo_ptr = foo;
/* Address-significant access to protected symbols is not supported in
position-dependent mode on several architectures because GCC
generates relocations that assume that the address is local to the
main program. */
#ifdef __PIE__
foo_p foo_procted_ptr = foo_protected;
#endif
extern foo_p get_foo_p (void);
extern foo_p get_foo_hidden_p (void);
@@ -37,12 +44,16 @@ main (void)
if ((*foo_ptr) () != -1)
abort ();
#ifdef __PIE__
if (foo_procted_ptr != foo_protected)
abort ();
#endif
if (foo_protected () != 0)
abort ();
#ifdef __PIE__
if ((*foo_procted_ptr) () != 0)
abort ();
#endif
p = get_foo_p ();
if (p != foo)
@@ -55,8 +66,10 @@ main (void)
abort ();
p = get_foo_protected_p ();
#ifdef __PIE__
if (p != foo_protected)
abort ();
#endif
if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
abort ();
+9
View File
@@ -14,12 +14,19 @@ get_foo (void)
return foo;
}
/* Address-significant access to protected symbols is not supported in
position-dependent mode on several architectures because GCC
generates relocations that assume that the address is local to the
main program. */
#ifdef __PIE__
foo_p
__attribute__ ((noinline))
get_foo_protected (void)
{
return foo_protected;
}
#endif
int
main (void)
@@ -30,9 +37,11 @@ main (void)
if ((*p) () != -1)
abort ();
#ifdef __PIE__
p = get_foo_protected ();
if ((*p) () != 0)
abort ();
#endif
return 0;
}
+3 -11
View File
@@ -9,7 +9,6 @@
#include "ifunc-sel.h"
typedef int (*foo_p) (void);
extern foo_p foo_ptr;
static int
one (void)
@@ -28,20 +27,17 @@ foo_ifunc (void)
}
extern int foo (void);
extern foo_p get_foo (void);
extern int call_foo (void);
extern foo_p get_foo_p (void);
foo_p my_foo_ptr = foo;
foo_p foo_ptr = foo;
int
main (void)
{
foo_p p;
p = get_foo ();
if (p != foo)
abort ();
if ((*p) () != -30)
if (call_foo () != -30)
abort ();
p = get_foo_p ();
@@ -52,12 +48,8 @@ main (void)
if (foo_ptr != foo)
abort ();
if (my_foo_ptr != foo)
abort ();
if ((*foo_ptr) () != -30)
abort ();
if ((*my_foo_ptr) () != -30)
abort ();
if (foo () != -30)
abort ();
+4 -4
View File
@@ -4,7 +4,7 @@ extern int foo (void);
typedef int (*foo_p) (void);
foo_p foo_ptr = foo;
extern foo_p foo_ptr;
foo_p
get_foo_p (void)
@@ -12,8 +12,8 @@ get_foo_p (void)
return foo_ptr;
}
foo_p
get_foo (void)
int
call_foo (void)
{
return foo;
return foo ();
}
+40 -74
View File
@@ -23,10 +23,6 @@
#define EW_(e, w, t) EW__(e, w, _##t)
#define EW__(e, w, t) e##w##t
#define pldd_assert(name, exp) \
typedef int __assert_##name[((exp) != 0) - 1]
struct E(link_map)
{
EW(Addr) l_addr;
@@ -39,12 +35,12 @@ struct E(link_map)
EW(Addr) l_libname;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr)));
pldd_assert (l_name, (offsetof (struct link_map, l_name)
== offsetof (struct E(link_map), l_name)));
pldd_assert (l_next, (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next)));
_Static_assert (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr), "l_addr");
_Static_assert (offsetof (struct link_map, l_name)
== offsetof (struct E(link_map), l_name), "l_name");
_Static_assert (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next), "l_next");
#endif
@@ -54,10 +50,10 @@ struct E(libname_list)
EW(Addr) next;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (name, (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name)));
pldd_assert (next, (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next)));
_Static_assert (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name), "name");
_Static_assert (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next), "next");
#endif
struct E(r_debug)
@@ -69,16 +65,17 @@ struct E(r_debug)
EW(Addr) r_map;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (r_version, (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version)));
pldd_assert (r_map, (offsetof (struct r_debug, r_map)
== offsetof (struct E(r_debug), r_map)));
_Static_assert (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version), "r_version");
_Static_assert (offsetof (struct r_debug, r_map)
== offsetof (struct E(r_debug), r_map), "r_map");
#endif
static int
E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
size_t auxv_size)
{
EW(Addr) phdr = 0;
unsigned int phnum = 0;
@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (phdr == 0 || phnum == 0 || phent == 0)
error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
EW(Phdr) *p = alloca (phnum * phent);
if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
{
error (0, 0, gettext ("cannot read program header"));
return EXIT_FAILURE;
}
EW(Phdr) *p = xmalloc (phnum * phent);
if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
/* Determine the load offset. We need this for interpreting the
other program header entries so we do this in a separate loop.
@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (p[i].p_type == PT_DYNAMIC)
{
EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
{
error (0, 0, gettext ("cannot read dynamic section"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
/* Search for the DT_DEBUG entry. */
for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
{
struct E(r_debug) r;
if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
!= sizeof (r))
{
error (0, 0, gettext ("cannot read r_debug"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
if (r.r_map != 0)
{
@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
else if (p[i].p_type == PT_INTERP)
{
interp = alloca (p[i].p_filesz);
if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
interp = xmalloc (p[i].p_filesz);
if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
{
error (0, 0, gettext ("cannot read program interpreter"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
}
if (list == 0)
@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (interp == NULL)
{
// XXX check whether the executable itself is the loader
return EXIT_FAILURE;
exit (EXIT_FAILURE);
}
// XXX perhaps try finding ld.so and _r_debug in it
return EXIT_FAILURE;
exit (EXIT_FAILURE);
}
free (p);
free (interp);
/* Print the PID and program name first. */
printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
do
{
struct E(link_map) m;
if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
{
error (0, 0, gettext ("cannot read link map"));
status = EXIT_FAILURE;
goto out;
}
if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
EW(Addr) name_offset = m.l_name;
again:
while (1)
{
ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
if (n == -1)
{
error (0, 0, gettext ("cannot read object name"));
status = EXIT_FAILURE;
goto out;
}
error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
if (memchr (tmpbuf.data, '\0', n) != NULL)
break;
if (!scratch_buffer_grow (&tmpbuf))
{
error (0, 0, gettext ("cannot allocate buffer for object name"));
status = EXIT_FAILURE;
goto out;
}
error (EXIT_FAILURE, 0,
gettext ("cannot allocate buffer for object name"));
}
if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
&& m.l_libname != 0)
{
/* Try the l_libname element. */
struct E(libname_list) ln;
if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
{
name_offset = ln.name;
goto again;
}
}
/* The m.l_name and m.l_libname.name for loader linkmap points to same
values (since BZ#387 fix). Trying to use l_libname name as the
shared object name might lead to an infinite loop (BZ#18035). */
/* Skip over the executable. */
if (((char *)tmpbuf.data)[0] != '\0')
@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
while (list != 0);
out:
scratch_buffer_free (&tmpbuf);
return status;
}
+30 -34
View File
@@ -17,23 +17,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <alloca.h>
#define _FILE_OFFSET_BITS 64
#include <argp.h>
#include <assert.h>
#include <dirent.h>
#include <elf.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <libintl.h>
#include <link.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <scratch_buffer.h>
@@ -76,14 +70,9 @@ static struct argp argp =
options, parse_opt, args_doc, doc, NULL, more_help, NULL
};
// File descriptor of /proc/*/mem file.
static int memfd;
/* Name of the executable */
static char *exe;
/* Local functions. */
static int get_process_info (int dfd, long int pid);
static int get_process_info (const char *exe, int dfd, long int pid);
static void wait_for_ptrace_stop (long int pid);
@@ -102,8 +91,10 @@ main (int argc, char *argv[])
return 1;
}
assert (sizeof (pid_t) == sizeof (int)
|| sizeof (pid_t) == sizeof (long int));
_Static_assert (sizeof (pid_t) == sizeof (int)
|| sizeof (pid_t) == sizeof (long int),
"sizeof (pid_t) != sizeof (int) or sizeof (long int)");
char *endp;
errno = 0;
long int pid = strtol (argv[remaining], &endp, 10);
@@ -119,25 +110,24 @@ main (int argc, char *argv[])
if (dfd == -1)
error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
struct scratch_buffer exebuf;
scratch_buffer_init (&exebuf);
/* Name of the executable */
struct scratch_buffer exe;
scratch_buffer_init (&exe);
ssize_t nexe;
while ((nexe = readlinkat (dfd, "exe",
exebuf.data, exebuf.length)) == exebuf.length)
exe.data, exe.length)) == exe.length)
{
if (!scratch_buffer_grow (&exebuf))
if (!scratch_buffer_grow (&exe))
{
nexe = -1;
break;
}
}
if (nexe == -1)
exe = (char *) "<program name undetermined>";
/* Default stack allocation is at least 1024. */
snprintf (exe.data, exe.length, "<program name undetermined>");
else
{
exe = exebuf.data;
exe[nexe] = '\0';
}
((char*)exe.data)[nexe] = '\0';
/* Stop all threads since otherwise the list of loaded modules might
change while we are reading it. */
@@ -155,8 +145,8 @@ main (int argc, char *argv[])
error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
buf);
struct dirent64 *d;
while ((d = readdir64 (dir)) != NULL)
struct dirent *d;
while ((d = readdir (dir)) != NULL)
{
if (! isdigit (d->d_name[0]))
continue;
@@ -182,7 +172,7 @@ main (int argc, char *argv[])
wait_for_ptrace_stop (tid);
struct thread_list *newp = alloca (sizeof (*newp));
struct thread_list *newp = xmalloc (sizeof (*newp));
newp->tid = tid;
newp->next = thread_list;
thread_list = newp;
@@ -190,17 +180,22 @@ main (int argc, char *argv[])
closedir (dir);
int status = get_process_info (dfd, pid);
if (thread_list == NULL)
error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf);
int status = get_process_info (exe.data, dfd, pid);
assert (thread_list != NULL);
do
{
ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
struct thread_list *prev = thread_list;
thread_list = thread_list->next;
free (prev);
}
while (thread_list != NULL);
close (dfd);
scratch_buffer_free (&exe);
return status;
}
@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
static int
get_process_info (int dfd, long int pid)
get_process_info (const char *exe, int dfd, long int pid)
{
memfd = openat (dfd, "mem", O_RDONLY);
/* File descriptor of /proc/<pid>/mem file. */
int memfd = openat (dfd, "mem", O_RDONLY);
if (memfd == -1)
goto no_info;
@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid)
int retval;
if (e_ident[EI_CLASS] == ELFCLASS32)
retval = find_maps32 (pid, auxv, auxv_size);
retval = find_maps32 (exe, memfd, pid, auxv, auxv_size);
else
retval = find_maps64 (pid, auxv, auxv_size);
retval = find_maps64 (exe, memfd, pid, auxv, auxv_size);
free (auxv);
close (memfd);
+1 -1
View File
@@ -52,7 +52,7 @@ $(objpfx)rtld-libc.a: $(foreach dir,$(rtld-subdirs),\
mv -f $@T $@
# Use the verbose option of ar and tar when not running silently.
ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s
ifeq ($(silent-make),no) # if not -s
verbose := v
else # -s
verbose :=
+93 -19
View File
@@ -25,35 +25,76 @@
#include "config.h"
#undef _LIBC
#define test_parent test_parent_tunables
#define test_child test_child_tunables
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <intprops.h>
#include <array_length.h>
static int test_child_tunables (void);
static int test_parent_tunables (void);
#include <support/check.h>
#include <support/support.h>
#include <support/test-driver.h>
#include <support/capture_subprocess.h>
#include "tst-env-setuid.c"
const char *teststrings[] =
{
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.check=2:glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096:glibc.malloc.check=2",
"glibc.malloc.perturb=0x800",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
"not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
"glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
":glibc.malloc.garbage=2:glibc.malloc.check=1",
"glibc.malloc.check=1:glibc.malloc.check=2",
"not_valid.malloc.check=2",
"glibc.not_valid.check=2",
};
#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096"
#define PARENT_VALSTRING_VALUE \
"glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096"
const char *resultstrings[] =
{
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"glibc.malloc.mmap_threshold=4096",
"",
"",
"",
"",
"",
"",
};
static int
test_child_tunables (void)
test_child (int off)
{
const char *val = getenv ("GLIBC_TUNABLES");
#if HAVE_TUNABLES
if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0)
if (val != NULL && strcmp (val, resultstrings[off]) == 0)
return 0;
if (val != NULL)
printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
return 1;
#else
if (val != NULL)
{
printf ("GLIBC_TUNABLES not cleared\n");
printf ("[%d] GLIBC_TUNABLES not cleared\n", off);
return 1;
}
return 0;
@@ -61,15 +102,48 @@ test_child_tunables (void)
}
static int
test_parent_tunables (void)
do_test (int argc, char **argv)
{
const char *val = getenv ("GLIBC_TUNABLES");
/* Setgid child process. */
if (argc == 2)
{
if (getgid () == getegid ())
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0)
return 0;
int ret = test_child (atoi (argv[1]));
if (val != NULL)
printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val);
if (ret != 0)
exit (1);
return 1;
exit (EXIT_SUCCESS);
}
else
{
int ret = 0;
/* Spawn tests. */
for (int i = 0; i < array_length (teststrings); i++)
{
char buf[INT_BUFSIZE_BOUND (int)];
printf ("Spawned test for %s (%d)\n", teststrings[i], i);
snprintf (buf, sizeof (buf), "%d\n", i);
if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
exit (1);
int status = support_capture_subprogram_self_sgid (buf);
/* Bail out early if unsupported. */
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
ret |= status;
}
return ret;
}
}
#define TEST_FUNCTION_ARGV do_test
#include <support/test-driver.c>
+14 -183
View File
@@ -29,173 +29,12 @@
#include <sys/wait.h>
#include <unistd.h>
#include <support/check.h>
#include <support/support.h>
#include <support/test-driver.h>
#include <support/capture_subprocess.h>
static char SETGID_CHILD[] = "setgid-child";
#define CHILD_STATUS 42
/* Return a GID which is not our current GID, but is present in the
supplementary group list. */
static gid_t
choose_gid (void)
{
const int count = 64;
gid_t groups[count];
int ret = getgroups (count, groups);
if (ret < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t current = getgid ();
for (int i = 0; i < ret; ++i)
{
if (groups[i] != current)
return groups[i];
}
return 0;
}
/* Spawn and execute a program and verify that it returns the CHILD_STATUS. */
static pid_t
do_execve (char **args)
{
pid_t kid = vfork ();
if (kid < 0)
{
printf ("vfork: %m\n");
return -1;
}
if (kid == 0)
{
/* Child process. */
execve (args[0], args, environ);
_exit (-errno);
}
if (kid < 0)
return 1;
int status;
if (waitpid (kid, &status, 0) < 0)
{
printf ("waitpid: %m\n");
return 1;
}
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS)
{
printf ("Unexpected exit status %d from child process\n",
WEXITSTATUS (status));
return 1;
}
return 0;
}
/* Copies the executable into a restricted directory, so that we can
safely make it SGID with the TARGET group ID. Then runs the
executable. */
static int
run_executable_sgid (gid_t target)
{
char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd",
test_dir, (intmax_t) getpid ());
char *execname = xasprintf ("%s/bin", dirname);
int infd = -1;
int outfd = -1;
int ret = 0;
if (mkdir (dirname, 0700) < 0)
{
printf ("mkdir: %m\n");
goto err;
}
infd = open ("/proc/self/exe", O_RDONLY);
if (infd < 0)
{
printf ("open (/proc/self/exe): %m\n");
goto err;
}
outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
if (outfd < 0)
{
printf ("open (%s): %m\n", execname);
goto err;
}
char buf[4096];
for (;;)
{
ssize_t rdcount = read (infd, buf, sizeof (buf));
if (rdcount < 0)
{
printf ("read: %m\n");
goto err;
}
if (rdcount == 0)
break;
char *p = buf;
char *end = buf + rdcount;
while (p != end)
{
ssize_t wrcount = write (outfd, buf, end - p);
if (wrcount == 0)
errno = ENOSPC;
if (wrcount <= 0)
{
printf ("write: %m\n");
goto err;
}
p += wrcount;
}
}
if (fchown (outfd, getuid (), target) < 0)
{
printf ("fchown (%s): %m\n", execname);
goto err;
}
if (fchmod (outfd, 02750) < 0)
{
printf ("fchmod (%s): %m\n", execname);
goto err;
}
if (close (outfd) < 0)
{
printf ("close (outfd): %m\n");
goto err;
}
if (close (infd) < 0)
{
printf ("close (infd): %m\n");
goto err;
}
char *args[] = {execname, SETGID_CHILD, NULL};
ret = do_execve (args);
err:
if (outfd >= 0)
close (outfd);
if (infd >= 0)
close (infd);
if (execname)
{
unlink (execname);
free (execname);
}
if (dirname)
{
rmdir (dirname);
free (dirname);
}
return ret;
}
#ifndef test_child
static int
@@ -256,40 +95,32 @@ do_test (int argc, char **argv)
if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
{
if (getgid () == getegid ())
{
/* This can happen if the file system is mounted nosuid. */
fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
exit (EXIT_UNSUPPORTED);
}
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
int ret = test_child ();
if (ret != 0)
exit (1);
exit (CHILD_STATUS);
exit (EXIT_SUCCESS);
}
else
{
if (test_parent () != 0)
exit (1);
/* Try running a setgid program. */
gid_t target = choose_gid ();
if (target == 0)
{
fprintf (stderr,
"Could not find a suitable GID for user %jd, skipping test\n",
(intmax_t) getuid ());
exit (0);
}
int status = support_capture_subprogram_self_sgid (SETGID_CHILD);
return run_executable_sgid (target);
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status))
FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
return 0;
}
/* Something went wrong and our argv was corrupted. */
_exit (1);
}
#define TEST_FUNCTION_ARGV do_test
+60
View File
@@ -0,0 +1,60 @@
/* Test unwinding through main.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <unwind.h>
#include <unistd.h>
#include <support/test-driver.h>
#if USE_PTHREADS
# include <pthread.h>
# include <error.h>
#endif
static _Unwind_Reason_Code
callback (struct _Unwind_Context *ctx, void *arg)
{
return _URC_NO_REASON;
}
static void *
func (void *a)
{
/* Arrange for this test to be killed if _Unwind_Backtrace runs into an
endless loop. We cannot use the test driver because the complete
call chain needs to be compiled with -funwind-tables so that
_Unwind_Backtrace is able to reach the start routine. */
alarm (DEFAULT_TIMEOUT);
_Unwind_Backtrace (callback, 0);
return a;
}
int
main (void)
{
#if USE_PTHREADS
pthread_t thr;
int rc = pthread_create (&thr, NULL, &func, NULL);
if (rc)
error (1, rc, "pthread_create");
rc = pthread_join (thr, NULL);
if (rc)
error (1, rc, "pthread_join");
#else
func (NULL);
#endif
}
+1 -1
View File
@@ -128,7 +128,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size,
/* This is really only for debugging. */
if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
__libc_fatal ("illegal status in internal_getgrouplist");
__libc_fatal ("Illegal status in internal_getgrouplist.\n");
/* For compatibility reason we will continue to look for more
entries using the next service even though data has already
+2
View File
@@ -150,6 +150,8 @@ libpthread {
__cthread_keycreate;
__cthread_getspecific;
__cthread_setspecific;
__pthread_getspecific;
__pthread_setspecific;
__pthread_getattr_np;
__pthread_attr_getstack;
}
+3 -1
View File
@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules))
ifeq (yes,$(build-shared))
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12
bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv14
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -316,6 +316,8 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so)) \
+127
View File
@@ -0,0 +1,127 @@
/* Assertion in ISO-2022-JP-3 due to two-character sequence (bug 27256).
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <iconv.h>
#include <string.h>
#include <errno.h>
#include <support/check.h>
/* Use an escape sequence to return to the initial state. */
static void
with_escape_sequence (void)
{
iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3");
TEST_VERIFY_EXIT (c != (iconv_t) -1);
char in[] = "\e$(O+D\e(B";
char *inbuf = in;
size_t inleft = strlen (in);
char out[3]; /* Space for one output character. */
char *outbuf;
size_t outleft;
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1);
TEST_COMPARE (errno, E2BIG);
TEST_COMPARE (inleft, 3);
TEST_COMPARE (inbuf - in, strlen (in) - 3);
TEST_COMPARE (outleft, sizeof (out) - 2);
TEST_COMPARE (outbuf - out, 2);
TEST_COMPARE (out[0] & 0xff, 0xc3);
TEST_COMPARE (out[1] & 0xff, 0xa6);
/* Return to the initial shift state, producing the pending
character. */
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), 0);
TEST_COMPARE (inleft, 0);
TEST_COMPARE (inbuf - in, strlen (in));
TEST_COMPARE (outleft, sizeof (out) - 2);
TEST_COMPARE (outbuf - out, 2);
TEST_COMPARE (out[0] & 0xff, 0xcc);
TEST_COMPARE (out[1] & 0xff, 0x80);
/* Nothing should be flushed the second time. */
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0);
TEST_COMPARE (outleft, sizeof (out));
TEST_COMPARE (outbuf - out, 0);
TEST_COMPARE (out[0] & 0xff, 0xcc);
TEST_COMPARE (out[1] & 0xff, 0x80);
TEST_COMPARE (iconv_close (c), 0);
}
/* Use an explicit flush to return to the initial state. */
static void
with_flush (void)
{
iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3");
TEST_VERIFY_EXIT (c != (iconv_t) -1);
char in[] = "\e$(O+D";
char *inbuf = in;
size_t inleft = strlen (in);
char out[3]; /* Space for one output character. */
char *outbuf;
size_t outleft;
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1);
TEST_COMPARE (errno, E2BIG);
TEST_COMPARE (inleft, 0);
TEST_COMPARE (inbuf - in, strlen (in));
TEST_COMPARE (outleft, sizeof (out) - 2);
TEST_COMPARE (outbuf - out, 2);
TEST_COMPARE (out[0] & 0xff, 0xc3);
TEST_COMPARE (out[1] & 0xff, 0xa6);
/* Flush the pending character. */
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0);
TEST_COMPARE (outleft, sizeof (out) - 2);
TEST_COMPARE (outbuf - out, 2);
TEST_COMPARE (out[0] & 0xff, 0xcc);
TEST_COMPARE (out[1] & 0xff, 0x80);
/* Nothing should be flushed the second time. */
outbuf = out;
outleft = sizeof (out);
TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0);
TEST_COMPARE (outleft, sizeof (out));
TEST_COMPARE (outbuf - out, 0);
TEST_COMPARE (out[0] & 0xff, 0xcc);
TEST_COMPARE (out[1] & 0xff, 0x80);
TEST_COMPARE (iconv_close (c), 0);
}
static int
do_test (void)
{
with_escape_sequence ();
with_flush ();
return 0;
}
#include <support/test-driver.c>
+48 -19
View File
@@ -67,23 +67,34 @@ enum
CURRENT_SEL_MASK = 7 << 3
};
/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the state
also contains the last two bytes to be output, shifted by 6 bits, and a
one-bit indicator whether they must be preceded by the shift sequence,
in bit 22. */
/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the
state also contains the last two bytes to be output, shifted by 6
bits, and a one-bit indicator whether they must be preceded by the
shift sequence, in bit 22. During ISO-2022-JP-3 to UCS-4
conversion, COUNT may also contain a non-zero pending wide
character, shifted by six bits. This happens for certain inputs in
JISX0213_1_2004_set and JISX0213_2_set if the second wide character
in a combining sequence cannot be written because the buffer is
full. */
/* Since this is a stateful encoding we have to provide code which resets
the output state to the initial state. This has to be done during the
flushing. */
#define EMIT_SHIFT_TO_INIT \
if ((data->__statep->__count & ~7) != ASCII_set) \
if (data->__statep->__count != ASCII_set) \
{ \
if (FROM_DIRECTION) \
{ \
/* It's easy, we don't have to emit anything, we just reset the \
state for the input. */ \
data->__statep->__count &= 7; \
data->__statep->__count |= ASCII_set; \
if (__glibc_likely (outbuf + 4 <= outend)) \
{ \
/* Write out the last character. */ \
*((uint32_t *) outbuf) = data->__statep->__count >> 6; \
outbuf += sizeof (uint32_t); \
data->__statep->__count = ASCII_set; \
} \
else \
/* We don't have enough room in the output buffer. */ \
status = __GCONV_FULL_OUTPUT; \
} \
else \
{ \
@@ -151,7 +162,21 @@ enum
#define LOOPFCT FROM_LOOP
#define BODY \
{ \
uint32_t ch = *inptr; \
uint32_t ch; \
\
/* Output any pending character. */ \
ch = set >> 6; \
if (__glibc_unlikely (ch != 0)) \
{ \
put32 (outptr, ch); \
outptr += 4; \
/* Remove the pending character, but preserve state bits. */ \
set &= (1 << 6) - 1; \
continue; \
} \
\
/* Otherwise read the next input byte. */ \
ch = *inptr; \
\
/* Recognize escape sequences. */ \
if (__glibc_unlikely (ch == ESC)) \
@@ -297,21 +322,25 @@ enum
uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0]; \
uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1]; \
\
inptr += 2; \
\
put32 (outptr, u1); \
outptr += 4; \
\
/* See whether we have room for two characters. */ \
if (outptr + 8 <= outend) \
if (outptr + 4 <= outend) \
{ \
inptr += 2; \
put32 (outptr, u1); \
outptr += 4; \
put32 (outptr, u2); \
outptr += 4; \
continue; \
} \
else \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
/* Otherwise store only the first character now, and \
put the second one into the queue. */ \
set |= u2 << 6; \
/* Tell the caller why we terminate the loop. */ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
\
inptr += 2; \
+3 -3
View File
@@ -1,10 +1,10 @@
#include <inet/arpa/inet.h>
#ifndef _ISOMAC
extern int __inet_aton (const char *__cp, struct in_addr *__inp);
libc_hidden_proto (__inet_aton)
/* Variant of inet_aton which rejects trailing garbage. */
extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp);
libc_hidden_proto (__inet_aton_exact)
libc_hidden_proto (inet_aton)
libc_hidden_proto (inet_ntop)
libc_hidden_proto (inet_pton)
extern __typeof (inet_pton) __inet_pton;
+1 -1
View File
@@ -23,7 +23,7 @@
# endif
# define DT_1_SUPPORTED_MASK \
(DF_1_NOW | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \
| DF_1_ORIGIN | DF_1_NODEFLIB)
| DF_1_ORIGIN | DF_1_NODEFLIB | DF_1_PIE)
#endif /* !_ISOMAC */
#endif /* elf.h */
+455
View File
@@ -0,0 +1,455 @@
/* intprops.h -- properties of integer types
Copyright (C) 2001-2018 Free Software Foundation, Inc.
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
#ifndef _GL_INTPROPS_H
#define _GL_INTPROPS_H
#include <limits.h>
/* Return a value with the common real type of E and V and the value of V.
Do not evaluate E. */
#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
<https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
/* The extra casts in the following macros work around compiler bugs,
e.g., in Cray C 5.0.3.0. */
/* True if the arithmetic type T is an integer type. bool counts as
an integer. */
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
/* True if the real type T is signed. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* Return 1 if the real expression E, after promotion, has a
signed or floating type. Do not evaluate E. */
#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
/* Minimum and maximum values for integer types and expressions. */
/* The width in bits of the integer type or expression T.
Do not evaluate T.
Padding bits are not supported; this is checked at compile-time below. */
#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
/* The maximum and minimum values for the integer type T. */
#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
#define TYPE_MAXIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) -1 \
: ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
/* The maximum and minimum values for the type of the expression E,
after integer promotion. E is not evaluated. */
#define _GL_INT_MINIMUM(e) \
(EXPR_SIGNED (e) \
? ~ _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_CONVERT (e, 0))
#define _GL_INT_MAXIMUM(e) \
(EXPR_SIGNED (e) \
? _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_NEGATE_CONVERT (e, 1))
#define _GL_SIGNED_INT_MAXIMUM(e) \
(((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
/* Work around OpenVMS incompatibility with C99. */
#if !defined LLONG_MAX && defined __INT64_MAX
# define LLONG_MAX __INT64_MAX
# define LLONG_MIN __INT64_MIN
#endif
/* This include file assumes that signed types are two's complement without
padding bits; the above macros have undefined behavior otherwise.
If this is a problem for you, please let us know how to fix it for your host.
This assumption is tested by the intprops-tests module. */
/* Does the __typeof__ keyword work? This could be done by
'configure', but for now it's easier to do it by hand. */
#if (2 <= __GNUC__ \
|| (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
|| (0x5110 <= __SUNPRO_C && !__STDC__))
# define _GL_HAVE___TYPEOF__ 1
#else
# define _GL_HAVE___TYPEOF__ 0
#endif
/* Return 1 if the integer type or expression T might be signed. Return 0
if it is definitely unsigned. This macro does not evaluate its argument,
and expands to an integer constant expression. */
#if _GL_HAVE___TYPEOF__
# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
#else
# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
#endif
/* Bound on length of the string representing an unsigned integer
value representable in B bits. log10 (2.0) < 146/485. The
smallest value of B where this bound is not tight is 2621. */
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
/* Bound on length of the string representing an integer type or expression T.
Subtract 1 for the sign bit if T is signed, and then add 1 more for
a minus sign if needed.
Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
signed, this macro may overestimate the true bound by one byte when
applied to unsigned types of size 2, 4, 16, ... bytes. */
#define INT_STRLEN_BOUND(t) \
(INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
+ _GL_SIGNED_TYPE_OR_EXPR (t))
/* Bound on buffer size needed to represent an integer type or expression T,
including the terminating null. */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
/* Range overflow checks.
The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
operators might not yield numerically correct answers due to
arithmetic overflow. They do not rely on undefined or
implementation-defined behavior. Their implementations are simple
and straightforward, but they are a bit harder to use than the
INT_<op>_OVERFLOW macros described below.
Example usage:
long int i = ...;
long int j = ...;
if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
printf ("multiply would overflow");
else
printf ("product is %ld", i * j);
Restrictions on *_RANGE_OVERFLOW macros:
These macros do not check for all possible numerical problems or
undefined or unspecified behavior: they do not check for division
by zero, for bad shift counts, or for shifting negative numbers.
These macros may evaluate their arguments zero or multiple times,
so the arguments should not have side effects. The arithmetic
arguments (including the MIN and MAX arguments) must be of the same
integer type after the usual arithmetic conversions, and the type
must have minimum value MIN and maximum MAX. Unsigned types should
use a zero MIN of the proper type.
These macros are tuned for constant MIN and MAX. For commutative
operations such as A + B, they are also tuned for constant B. */
/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? (a) < (min) - (b) \
: (max) - (b) < (a))
/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? (max) + (b) < (a) \
: (a) < (min) + (b))
/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
((min) < 0 \
? (a) < - (max) \
: 0 < (a))
/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Avoid && and || as they tickle
bugs in Sun C 5.11 2010/08/13 and other compilers; see
<https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */
#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? ((a) < 0 \
? (a) < (max) / (b) \
: (b) == -1 \
? 0 \
: (min) / (b) < (a)) \
: (b) == 0 \
? 0 \
: ((a) < 0 \
? (a) < (min) / (b) \
: (max) / (b) < (a)))
/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Do not check for division by zero. */
#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \
((min) < 0 && (b) == -1 && (a) < - (max))
/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Do not check for division by zero.
Mathematically, % should never overflow, but on x86-like hosts
INT_MIN % -1 traps, and the C standard permits this, so treat this
as an overflow too. */
#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \
INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Here, MIN and MAX are for A only, and B need
not be of the same type as the other arguments. The C standard says that
behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
A is negative then A << B has undefined behavior and A >> B has
implementation-defined behavior, but do not check these other
restrictions. */
#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \
((a) < 0 \
? (a) < (min) >> (b) \
: (max) >> (b) < (a))
/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */
#if 5 <= __GNUC__ && !defined __ICC
# define _GL_HAS_BUILTIN_OVERFLOW 1
#else
# define _GL_HAS_BUILTIN_OVERFLOW 0
#endif
/* True if __builtin_add_overflow_p (A, B, C) works. */
#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
/* The _GL*_OVERFLOW macros have the same restrictions as the
*_RANGE_OVERFLOW macros, except that they do not assume that operands
(e.g., A and B) have the same type as MIN and MAX. Instead, they assume
that the result (e.g., A + B) has that type. */
#if _GL_HAS_BUILTIN_OVERFLOW_P
# define _GL_ADD_OVERFLOW(a, b, min, max) \
__builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
__builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0)
# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
__builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0)
#else
# define _GL_ADD_OVERFLOW(a, b, min, max) \
((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \
: (a) < 0 ? (b) <= (a) + (b) \
: (b) < 0 ? (a) <= (a) + (b) \
: (a) + (b) < (b))
# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \
((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \
: (a) < 0 ? 1 \
: (b) < 0 ? (a) - (b) <= (a) \
: (a) < (b))
# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \
(((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \
|| INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
#endif
#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
: (a) < 0 ? (b) <= (a) + (b) - 1 \
: (b) < 0 && (a) + (b) <= (a))
#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \
((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \
: (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \
: (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
/* Return a nonzero value if A is a mathematical multiple of B, where
A is unsigned, B is negative, and MAX is the maximum value of A's
type. A's type must be the same as (A % B)'s type. Normally (A %
-B == 0) suffices, but things get tricky if -B would overflow. */
#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \
(((b) < -_GL_SIGNED_INT_MAXIMUM (b) \
? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \
? (a) \
: (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \
: (a) % - (b)) \
== 0)
/* Check for integer overflow, and report low order bits of answer.
The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
might not yield numerically correct answers due to arithmetic overflow.
The INT_<op>_WRAPV macros also store the low-order bits of the answer.
These macros work correctly on all known practical hosts, and do not rely
on undefined behavior due to signed arithmetic overflow.
Example usage, assuming A and B are long int:
if (INT_MULTIPLY_OVERFLOW (a, b))
printf ("result would overflow\n");
else
printf ("result is %ld (no overflow)\n", a * b);
Example usage with WRAPV flavor:
long int result;
bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
printf ("result is %ld (%s)\n", result,
overflow ? "after overflow" : "no overflow");
Restrictions on these macros:
These macros do not check for all possible numerical problems or
undefined or unspecified behavior: they do not check for division
by zero, for bad shift counts, or for shifting negative numbers.
These macros may evaluate their arguments zero or multiple times, so the
arguments should not have side effects.
The WRAPV macros are not constant expressions. They support only
+, binary -, and *. The result type must be signed.
These macros are tuned for their last argument being a constant.
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
A % B, and A << B would overflow, respectively. */
#define INT_ADD_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
#define INT_SUBTRACT_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
#if _GL_HAS_BUILTIN_OVERFLOW_P
# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a)
#else
# define INT_NEGATE_OVERFLOW(a) \
INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
#endif
#define INT_MULTIPLY_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
#define INT_DIVIDE_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
#define INT_REMAINDER_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
_GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
/* Return 1 if the expression A <op> B would overflow,
where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
assuming MIN and MAX are the minimum and maximum for the result type.
Arguments should be free of side effects. */
#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
op_result_overflow (a, b, \
_GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
_GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))
/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
Return 1 if the result overflows. See above for restrictions. */
#define INT_ADD_WRAPV(a, b, r) \
_GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW)
#define INT_SUBTRACT_WRAPV(a, b, r) \
_GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
#define INT_MULTIPLY_WRAPV(a, b, r) \
_GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
https://llvm.org/bugs/show_bug.cgi?id=25390
For now, assume all versions of GCC-like compilers generate bogus
warnings for _Generic. This matters only for older compilers that
lack __builtin_add_overflow. */
#if __GNUC__
# define _GL__GENERIC_BOGUS 1
#else
# define _GL__GENERIC_BOGUS 0
#endif
/* Store the low-order bits of A <op> B into *R, where OP specifies
the operation. BUILTIN is the builtin operation, and OVERFLOW the
overflow predicate. Return 1 if the result overflows. See above
for restrictions. */
#if _GL_HAS_BUILTIN_OVERFLOW
# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r)
#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
(_Generic \
(*(r), \
signed char: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
signed char, SCHAR_MIN, SCHAR_MAX), \
short int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
short int, SHRT_MIN, SHRT_MAX), \
int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
int, INT_MIN, INT_MAX), \
long int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
long int, LONG_MIN, LONG_MAX), \
long long int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
long long int, LLONG_MIN, LLONG_MAX)))
#else
# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
(sizeof *(r) == sizeof (signed char) \
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
signed char, SCHAR_MIN, SCHAR_MAX) \
: sizeof *(r) == sizeof (short int) \
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
short int, SHRT_MIN, SHRT_MAX) \
: sizeof *(r) == sizeof (int) \
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
int, INT_MIN, INT_MAX) \
: _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
# ifdef LLONG_MAX
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
(sizeof *(r) == sizeof (long int) \
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
long int, LONG_MIN, LONG_MAX) \
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
long long int, LLONG_MIN, LLONG_MAX))
# else
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
long int, LONG_MIN, LONG_MAX)
# endif
#endif
/* Store the low-order bits of A <op> B into *R, where the operation
is given by OP. Use the unsigned type UT for calculation to avoid
overflow problems. *R's type is T, with extrema TMIN and TMAX.
T must be a signed integer type. Return 1 if the result overflows. */
#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
(sizeof ((a) op (b)) < sizeof (t) \
? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \
: _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
((overflow (a, b) \
|| (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
|| (tmax) < ((a) op (b))) \
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
/* Return the low-order bits of A <op> B, where the operation is given
by OP. Use the unsigned type UT for calculation to avoid undefined
behavior on signed integer overflow, and convert the result to type T.
UT is at least as wide as T and is no narrower than unsigned int,
T is two's complement, and there is no padding or trap representations.
Assume that converting UT to T yields the low-order bits, as is
done in all known two's-complement C compilers. E.g., see:
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
According to the C standard, converting UT to T yields an
implementation-defined result or signal for values outside T's
range. However, code that works around this theoretical problem
runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
As the compiler bug is real, don't try to work around the
theoretical problem. */
#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
((t) ((ut) (a) op (ut) (b)))
#endif /* _GL_INTPROPS_H */
+4
View File
@@ -216,6 +216,10 @@ struct link_map
unsigned int boundndx;
uint32_t enterexit;
unsigned int flags;
/* CONCURRENCY NOTE: This is used to guard the concurrent initialization
of the relocation result across multiple threads. See the more
detailed notes in elf/dl-runtime.c. */
unsigned int init;
} *l_reloc_result;
/* Pointer to the version information if available. */
+2 -1
View File
@@ -98,7 +98,8 @@ enum __libc_message_action
do_backtrace = 1 << 1 /* Backtrace. */
};
/* Print out MESSAGE on the error output and abort. */
/* Print out MESSAGE (which should end with a newline) on the error output
and abort. */
extern void __libc_fatal (const char *__message)
__attribute__ ((__noreturn__));
extern void __libc_message (enum __libc_message_action action,
+5 -1
View File
@@ -52,7 +52,7 @@ aux := check_pf check_native ifreq
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \
tst-sockaddr test-hnto-types
tst-sockaddr test-hnto-types tst-if_index-long
# tst-deadline must be linked statically so that we can access
# internal functions.
@@ -112,4 +112,8 @@ ifeq ($(build-static-nss),yes)
CFLAGS += -DSTATIC_NSS
endif
# The test uses dlopen indirectly and would otherwise load system
# objects.
tst-idna_name_classify-ENV = \
LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
$(objpfx)tst-idna_name_classify.out: $(gen-locales)
+61
View File
@@ -0,0 +1,61 @@
/* Check for descriptor leak in if_nametoindex with a long interface name.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test checks for a descriptor leak in case of a long interface
name (CVE-2018-19591, bug 23927). */
#include <errno.h>
#include <net/if.h>
#include <netdb.h>
#include <string.h>
#include <support/check.h>
#include <support/descriptors.h>
#include <support/support.h>
static int
do_test (void)
{
struct support_descriptors *descrs = support_descriptors_list ();
/* Prepare a name which is just as long as required for trigging the
bug. */
char name[IFNAMSIZ + 1];
memset (name, 'A', IFNAMSIZ);
name[IFNAMSIZ] = '\0';
TEST_COMPARE (strlen (name), IFNAMSIZ);
struct ifreq ifr;
TEST_COMPARE (strlen (name), sizeof (ifr.ifr_name));
/* Test directly via if_nametoindex. */
TEST_COMPARE (if_nametoindex (name), 0);
TEST_COMPARE (errno, ENODEV);
support_descriptors_check (descrs);
/* Same test via getaddrinfo. */
char *host = xasprintf ("fea0::%%%s", name);
struct addrinfo hints = { .ai_flags = AI_NUMERICHOST, };
struct addrinfo *ai;
TEST_COMPARE (getaddrinfo (host, NULL, &hints, &ai), EAI_NONAME);
support_descriptors_check (descrs);
support_descriptors_free (descrs);
return 0;
}
#include <support/test-driver.c>
+1 -1
View File
@@ -631,7 +631,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname);
free (cwd);
if (ret < 0)
return NULL;
goto return_untranslated;
dirname = xdirname;
}
#ifndef IN_LIBGLOCALE
-5
View File
@@ -73,11 +73,6 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
tst-fts tst-fts-lfs tst-open-tmpfile \
tst-copy_file_range tst-getcwd-abspath \
# This test includes the compat implementation of copy_file_range,
# which uses internal, unexported libc functions.
tests-static += tst-copy_file_range-compat
tests-internal += tst-copy_file_range-compat
# Likewise for statx, but we do not need static linking here.
tests-internal += tst-statx
-160
View File
@@ -1,160 +0,0 @@
/* Emulation of copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* The following macros should be defined before including this
file:
COPY_FILE_RANGE_DECL Declaration specifiers for the function below.
COPY_FILE_RANGE Name of the function to define. */
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
COPY_FILE_RANGE_DECL
ssize_t
COPY_FILE_RANGE (int infd, __off64_t *pinoff,
int outfd, __off64_t *poutoff,
size_t length, unsigned int flags)
{
if (flags != 0)
{
__set_errno (EINVAL);
return -1;
}
{
struct stat64 instat;
struct stat64 outstat;
if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0)
return -1;
if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode))
{
__set_errno (EISDIR);
return -1;
}
if (!S_ISREG (instat.st_mode) || !S_ISREG (outstat.st_mode))
{
/* We need a regular input file so that the we can seek
backwards in case of a write failure. */
__set_errno (EINVAL);
return -1;
}
if (instat.st_dev != outstat.st_dev)
{
/* Cross-device copies are not supported. */
__set_errno (EXDEV);
return -1;
}
}
/* The output descriptor must not have O_APPEND set. */
{
int flags = __fcntl (outfd, F_GETFL);
if (flags & O_APPEND)
{
__set_errno (EBADF);
return -1;
}
}
/* Avoid an overflow in the result. */
if (length > SSIZE_MAX)
length = SSIZE_MAX;
/* Main copying loop. The buffer size is arbitrary and is a
trade-off between stack size consumption, cache usage, and
amortization of system call overhead. */
size_t copied = 0;
char buf[8192];
while (length > 0)
{
size_t to_read = length;
if (to_read > sizeof (buf))
to_read = sizeof (buf);
/* Fill the buffer. */
ssize_t read_count;
if (pinoff == NULL)
read_count = read (infd, buf, to_read);
else
read_count = __libc_pread64 (infd, buf, to_read, *pinoff);
if (read_count == 0)
/* End of file reached prematurely. */
return copied;
if (read_count < 0)
{
if (copied > 0)
/* Report the number of bytes copied so far. */
return copied;
return -1;
}
if (pinoff != NULL)
*pinoff += read_count;
/* Write the buffer part which was read to the destination. */
char *end = buf + read_count;
for (char *p = buf; p < end; )
{
ssize_t write_count;
if (poutoff == NULL)
write_count = write (outfd, p, end - p);
else
write_count = __libc_pwrite64 (outfd, p, end - p, *poutoff);
if (write_count < 0)
{
/* Adjust the input read position to match what we have
written, so that the caller can pick up after the
error. */
size_t written = p - buf;
/* NB: This needs to be signed so that we can form the
negative value below. */
ssize_t overread = read_count - written;
if (pinoff == NULL)
{
if (overread > 0)
{
/* We are on an error recovery path, so we
cannot deal with failure here. */
int save_errno = errno;
(void) __libc_lseek64 (infd, -overread, SEEK_CUR);
__set_errno (save_errno);
}
}
else /* pinoff != NULL */
*pinoff -= overread;
if (copied + written > 0)
/* Report the number of bytes copied so far. */
return copied + written;
return -1;
}
p += write_count;
if (poutoff != NULL)
*poutoff += write_count;
} /* Write loop. */
copied += read_count;
length -= read_count;
}
return copied;
}
+13 -5
View File
@@ -1,5 +1,5 @@
/* Generic implementation of copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
/* Stub implementation of copy_file_range.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,7 +16,15 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define COPY_FILE_RANGE_DECL
#define COPY_FILE_RANGE copy_file_range
#include <errno.h>
#include <unistd.h>
#include <io/copy_file_range-compat.c>
ssize_t
copy_file_range (int infd, __off64_t *pinoff,
int outfd, __off64_t *poutoff,
size_t length, unsigned int flags)
{
__set_errno (ENOSYS);
return -1;
}
stub_warning (copy_file_range)
+10 -547
View File
@@ -1,5 +1,5 @@
/* Tests for copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
Copyright (C) 2017-2019 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
@@ -20,22 +20,15 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <poll.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <support/xunistd.h>
#ifdef CLONE_NEWNS
# include <sys/mount.h>
#endif
/* Boolean flags which indicate whether to use pointers with explicit
output flags. */
@@ -49,10 +42,6 @@ static int infd;
static char *outfile;
static int outfd;
/* Like the above, but on a different file system. xdevfile can be
NULL if no suitable file system has been found. */
static char *xdevfile;
/* Input and output offsets. Set according to do_inoff and do_outoff
before the test. The offsets themselves are always set to
zero. */
@@ -61,13 +50,10 @@ static off64_t *pinoff;
static off64_t outoff;
static off64_t *poutoff;
/* These are a collection of copy sizes used in tests. The selection
takes into account that the fallback implementation uses an
internal buffer of 8192 bytes. */
/* These are a collection of copy sizes used in tests. */
enum { maximum_size = 99999 };
static const int typical_sizes[] =
{ 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, 16383, 16384, 16385,
maximum_size };
{ 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, maximum_size };
/* The random contents of this array can be used as a pattern to check
for correct write operations. */
@@ -76,101 +62,6 @@ static unsigned char random_data[maximum_size];
/* The size chosen by the test harness. */
static int current_size;
/* Maximum writable file offset. Updated by find_maximum_offset
below. */
static off64_t maximum_offset;
/* Error code when crossing the offset. */
static int maximum_offset_errno;
/* If true: Writes which cross the limit will fail. If false: Writes
which cross the limit will result in a partial write. */
static bool maximum_offset_hard_limit;
/* Fills maximum_offset etc. above. Truncates outfd as a side
effect. */
static void
find_maximum_offset (void)
{
xftruncate (outfd, 0);
if (maximum_offset != 0)
return;
uint64_t upper = -1;
upper >>= 1; /* Maximum of off64_t. */
TEST_VERIFY ((off64_t) upper > 0);
TEST_VERIFY ((off64_t) (upper + 1) < 0);
if (lseek64 (outfd, upper, SEEK_SET) >= 0)
{
if (write (outfd, "", 1) == 1)
FAIL_EXIT1 ("created a file larger than the off64_t range");
}
uint64_t lower = 1024 * 1024; /* A reasonable minimum file size. */
/* Loop invariant: writing at lower succeeds, writing at upper fails. */
while (lower + 1 < upper)
{
uint64_t middle = (lower + upper) / 2;
if (test_verbose > 0)
printf ("info: %s: remaining test range %" PRIu64 " .. %" PRIu64
", probe at %" PRIu64 "\n", __func__, lower, upper, middle);
xftruncate (outfd, 0);
if (lseek64 (outfd, middle, SEEK_SET) >= 0
&& write (outfd, "", 1) == 1)
lower = middle;
else
upper = middle;
}
TEST_VERIFY (lower + 1 == upper);
maximum_offset = lower;
printf ("info: maximum writable file offset: %" PRIu64 " (%" PRIx64 ")\n",
lower, lower);
/* Check that writing at the valid offset actually works. */
xftruncate (outfd, 0);
xlseek (outfd, lower, SEEK_SET);
TEST_COMPARE (write (outfd, "", 1), 1);
/* Cross the boundary with a two-byte write. This can either result
in a short write, or a failure. */
xlseek (outfd, lower, SEEK_SET);
ssize_t ret = write (outfd, " ", 2);
if (ret < 0)
{
maximum_offset_errno = errno;
maximum_offset_hard_limit = true;
}
else
maximum_offset_hard_limit = false;
/* Check that writing at the next offset actually fails. This also
obtains the expected errno value. */
xftruncate (outfd, 0);
const char *action;
if (lseek64 (outfd, lower + 1, SEEK_SET) != 0)
{
if (write (outfd, "", 1) != -1)
FAIL_EXIT1 ("write to impossible offset %" PRIu64 " succeeded",
lower + 1);
action = "writing";
int errno_copy = errno;
if (maximum_offset_hard_limit)
TEST_COMPARE (errno_copy, maximum_offset_errno);
else
maximum_offset_errno = errno_copy;
}
else
{
action = "seeking";
maximum_offset_errno = errno;
}
printf ("info: %s out of range fails with %m (%d)\n",
action, maximum_offset_errno);
xftruncate (outfd, 0);
xlseek (outfd, 0, SEEK_SET);
}
/* Perform a copy of a file. */
static void
simple_file_copy (void)
@@ -247,390 +138,6 @@ simple_file_copy (void)
free (bytes);
}
/* Test that reading from a pipe willfails. */
static void
pipe_as_source (void)
{
int pipefds[2];
xpipe (pipefds);
for (int length = 0; length < 2; ++length)
{
if (test_verbose > 0)
printf ("info: %s: length=%d\n", __func__, length);
/* Make sure that there is something to copy in the pipe. */
xwrite (pipefds[1], "@", 1);
TEST_COMPARE (copy_file_range (pipefds[0], pinoff, outfd, poutoff,
length, 0), -1);
/* Linux 4.10 and later return EINVAL. Older kernels return
EXDEV. */
TEST_VERIFY (errno == EINVAL || errno == EXDEV);
TEST_COMPARE (inoff, 0);
TEST_COMPARE (outoff, 0);
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 0);
/* Make sure that nothing was read. */
char buf = 'A';
TEST_COMPARE (read (pipefds[0], &buf, 1), 1);
TEST_COMPARE (buf, '@');
}
xclose (pipefds[0]);
xclose (pipefds[1]);
}
/* Test that writing to a pipe fails. */
static void
pipe_as_destination (void)
{
/* Make sure that there is something to read in the input file. */
xwrite (infd, "abc", 3);
xlseek (infd, 0, SEEK_SET);
int pipefds[2];
xpipe (pipefds);
for (int length = 0; length < 2; ++length)
{
if (test_verbose > 0)
printf ("info: %s: length=%d\n", __func__, length);
TEST_COMPARE (copy_file_range (infd, pinoff, pipefds[1], poutoff,
length, 0), -1);
/* Linux 4.10 and later return EINVAL. Older kernels return
EXDEV. */
TEST_VERIFY (errno == EINVAL || errno == EXDEV);
TEST_COMPARE (inoff, 0);
TEST_COMPARE (outoff, 0);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
/* Make sure that nothing was written. */
struct pollfd pollfd = { .fd = pipefds[0], .events = POLLIN, };
TEST_COMPARE (poll (&pollfd, 1, 0), 0);
}
xclose (pipefds[0]);
xclose (pipefds[1]);
}
/* Test a write failure after (potentially) writing some bytes.
Failure occurs near the start of the buffer. */
static void
delayed_write_failure_beginning (void)
{
/* We need to write something to provoke the error. */
if (current_size == 0)
return;
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
/* Write failure near the start. The actual error code varies among
file systems. */
find_maximum_offset ();
off64_t where = maximum_offset;
if (current_size == 1)
++where;
outoff = where;
if (do_outoff)
xlseek (outfd, 1, SEEK_SET);
else
xlseek (outfd, where, SEEK_SET);
if (maximum_offset_hard_limit || where > maximum_offset)
{
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), -1);
TEST_COMPARE (errno, maximum_offset_errno);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
TEST_COMPARE (inoff, 0);
if (do_outoff)
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1);
else
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where);
TEST_COMPARE (outoff, where);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, 0);
}
else
{
/* The offset is not a hard limit. This means we write one
byte. */
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), 1);
if (do_inoff)
{
TEST_COMPARE (inoff, 1);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
}
else
{
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 1);
TEST_COMPARE (inoff, 0);
}
if (do_outoff)
{
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1);
TEST_COMPARE (outoff, where + 1);
}
else
{
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where + 1);
TEST_COMPARE (outoff, where);
}
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, where + 1);
}
}
/* Test a write failure after (potentially) writing some bytes.
Failure occurs near the end of the buffer. */
static void
delayed_write_failure_end (void)
{
if (current_size <= 1)
/* This would be same as the first test because there is not
enough data to write to make a difference. */
return;
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
find_maximum_offset ();
off64_t where = maximum_offset - current_size + 1;
if (current_size == sizeof (random_data))
/* Otherwise we do not reach the non-writable byte. */
++where;
outoff = where;
if (do_outoff)
xlseek (outfd, 1, SEEK_SET);
else
xlseek (outfd, where, SEEK_SET);
ssize_t ret = copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0);
if (ret < 0)
{
TEST_COMPARE (ret, -1);
TEST_COMPARE (errno, maximum_offset_errno);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, 0);
}
else
{
/* The first copy succeeded. This happens in the emulation
because the internal buffer of limited size does not
necessarily cross the off64_t boundary on the first write
operation. */
if (test_verbose > 0)
printf ("info: copy_file_range (%zu) returned %zd\n",
sizeof (random_data), ret);
TEST_VERIFY (ret > 0);
TEST_VERIFY (ret < maximum_size);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, where + ret);
if (do_inoff)
{
TEST_COMPARE (inoff, ret);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
}
else
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), ret);
char *buffer = xmalloc (ret);
TEST_COMPARE (pread64 (outfd, buffer, ret, where), ret);
TEST_VERIFY (memcmp (buffer, random_data, ret) == 0);
free (buffer);
/* The second copy fails. */
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), -1);
TEST_COMPARE (errno, maximum_offset_errno);
}
}
/* Test a write failure across devices. */
static void
cross_device_failure (void)
{
if (xdevfile == NULL)
/* Subtest not supported due to missing cross-device file. */
return;
/* We need something to write. */
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
int xdevfd = xopen (xdevfile, O_RDWR | O_LARGEFILE, 0);
TEST_COMPARE (copy_file_range (infd, pinoff, xdevfd, poutoff,
current_size, 0), -1);
TEST_COMPARE (errno, EXDEV);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
struct stat64 st;
xfstat (xdevfd, &st);
TEST_COMPARE (st.st_size, 0);
xclose (xdevfd);
}
/* Try to exercise ENOSPC behavior with a tempfs file system (so that
we do not have to fill up a regular file system to get the error).
This function runs in a subprocess, so that we do not change the
mount namespace of the actual test process. */
static void
enospc_failure_1 (void *closure)
{
#ifdef CLONE_NEWNS
support_become_root ();
/* Make sure that we do not alter the file system mounts of the
parents. */
if (! support_enter_mount_namespace ())
{
printf ("warning: ENOSPC test skipped\n");
return;
}
char *mountpoint = closure;
if (mount ("none", mountpoint, "tmpfs", MS_NODEV | MS_NOEXEC,
"size=500k") != 0)
{
printf ("warning: could not mount tmpfs at %s: %m\n", mountpoint);
return;
}
/* The source file must reside on the same file system. */
char *intmpfsfile = xasprintf ("%s/%s", mountpoint, "in");
int intmpfsfd = xopen (intmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600);
xwrite (intmpfsfd, random_data, sizeof (random_data));
xlseek (intmpfsfd, 1, SEEK_SET);
inoff = 1;
char *outtmpfsfile = xasprintf ("%s/%s", mountpoint, "out");
int outtmpfsfd = xopen (outtmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600);
/* Fill the file with data until ENOSPC is reached. */
while (true)
{
ssize_t ret = write (outtmpfsfd, random_data, sizeof (random_data));
if (ret < 0 && errno != ENOSPC)
FAIL_EXIT1 ("write to %s: %m", outtmpfsfile);
if (ret < sizeof (random_data))
break;
}
TEST_COMPARE (write (outtmpfsfd, "", 1), -1);
TEST_COMPARE (errno, ENOSPC);
off64_t maxsize = xlseek (outtmpfsfd, 0, SEEK_CUR);
TEST_VERIFY_EXIT (maxsize > sizeof (random_data));
/* Constructed the expected file contents. */
char *expected = xmalloc (maxsize);
TEST_COMPARE (pread64 (outtmpfsfd, expected, maxsize, 0), maxsize);
/* Go back a little, so some bytes can be written. */
enum { offset = 20000 };
TEST_VERIFY_EXIT (offset < maxsize);
TEST_VERIFY_EXIT (offset < sizeof (random_data));
memcpy (expected + maxsize - offset, random_data + 1, offset);
if (do_outoff)
{
outoff = maxsize - offset;
xlseek (outtmpfsfd, 2, SEEK_SET);
}
else
xlseek (outtmpfsfd, -offset, SEEK_CUR);
/* First call is expected to succeed because we made room for some
bytes. */
TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff,
maximum_size, 0), offset);
if (do_inoff)
{
TEST_COMPARE (inoff, 1 + offset);
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1);
}
else
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset);
if (do_outoff)
{
TEST_COMPARE (outoff, maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2);
}
else
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize);
struct stat64 st;
xfstat (outtmpfsfd, &st);
TEST_COMPARE (st.st_size, maxsize);
char *actual = xmalloc (st.st_size);
TEST_COMPARE (pread64 (outtmpfsfd, actual, st.st_size, 0), st.st_size);
TEST_VERIFY (memcmp (expected, actual, maxsize) == 0);
/* Second call should fail with ENOSPC. */
TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff,
maximum_size, 0), -1);
TEST_COMPARE (errno, ENOSPC);
/* Offsets should be unchanged. */
if (do_inoff)
{
TEST_COMPARE (inoff, 1 + offset);
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1);
}
else
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset);
if (do_outoff)
{
TEST_COMPARE (outoff, maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2);
}
else
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_END), maxsize);
TEST_COMPARE (pread64 (outtmpfsfd, actual, maxsize, 0), maxsize);
TEST_VERIFY (memcmp (expected, actual, maxsize) == 0);
free (actual);
free (expected);
xclose (intmpfsfd);
xclose (outtmpfsfd);
free (intmpfsfile);
free (outtmpfsfile);
#else /* !CLONE_NEWNS */
puts ("warning: ENOSPC test skipped (no mount namespaces)");
#endif
}
/* Call enospc_failure_1 in a subprocess. */
static void
enospc_failure (void)
{
char *mountpoint
= support_create_temp_directory ("tst-copy_file_range-enospc-");
support_isolate_in_subprocess (enospc_failure_1, mountpoint);
free (mountpoint);
}
/* The target file descriptor must have O_APPEND enabled. */
static void
oappend_failure (void)
{
/* Add data, to make sure we do not fail because there is
insufficient input data. */
xwrite (infd, random_data, current_size);
xlseek (infd, 0, SEEK_SET);
xclose (outfd);
outfd = xopen (outfile, O_RDWR | O_APPEND, 0);
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
current_size, 0), -1);
TEST_COMPARE (errno, EBADF);
}
/* Test that a short input file results in a shortened copy. */
static void
short_copy (void)
@@ -721,14 +228,6 @@ struct test_case
static struct test_case tests[] =
{
{ "simple_file_copy", simple_file_copy, .sizes = true },
{ "pipe_as_source", pipe_as_source, },
{ "pipe_as_destination", pipe_as_destination, },
{ "delayed_write_failure_beginning", delayed_write_failure_beginning,
.sizes = true },
{ "delayed_write_failure_end", delayed_write_failure_end, .sizes = true },
{ "cross_device_failure", cross_device_failure, .sizes = true },
{ "enospc_failure", enospc_failure, },
{ "oappend_failure", oappend_failure, .sizes = true },
{ "short_copy", short_copy, .sizes = true },
};
@@ -739,53 +238,18 @@ do_test (void)
*p = rand () >> 24;
infd = create_temp_file ("tst-copy_file_range-in-", &infile);
xclose (create_temp_file ("tst-copy_file_range-out-", &outfile));
/* Try to find a different directory from the default input/output
file. */
outfd = create_temp_file ("tst-copy_file_range-out-", &outfile);
{
struct stat64 instat;
xfstat (infd, &instat);
static const char *const candidates[] =
{ NULL, "/var/tmp", "/dev/shm" };
for (const char *const *c = candidates; c < array_end (candidates); ++c)
ssize_t ret = copy_file_range (infd, NULL, outfd, NULL, 0, 0);
if (ret != 0)
{
const char *path = *c;
char *to_free = NULL;
if (path == NULL)
{
to_free = xreadlink ("/proc/self/exe");
path = dirname (to_free);
}
struct stat64 cstat;
xstat (path, &cstat);
if (cstat.st_dev == instat.st_dev)
{
free (to_free);
continue;
}
printf ("info: using alternate temporary files directory: %s\n", path);
xdevfile = xasprintf ("%s/tst-copy_file_range-xdev-XXXXXX", path);
free (to_free);
break;
if (errno == ENOSYS)
FAIL_UNSUPPORTED ("copy_file_range is not support on this system");
FAIL_EXIT1 ("copy_file_range probing call: %m");
}
if (xdevfile != NULL)
{
int xdevfd = mkstemp (xdevfile);
if (xdevfd < 0)
FAIL_EXIT1 ("mkstemp (\"%s\"): %m", xdevfile);
struct stat64 xdevst;
xfstat (xdevfd, &xdevst);
TEST_VERIFY (xdevst.st_dev != instat.st_dev);
add_temp_file (xdevfile);
xclose (xdevfd);
}
else
puts ("warning: no alternate directory on different file system found");
}
xclose (infd);
xclose (outfd);
for (do_inoff = 0; do_inoff < 2; ++do_inoff)
for (do_outoff = 0; do_outoff < 2; ++do_outoff)
@@ -827,7 +291,6 @@ do_test (void)
free (infile);
free (outfile);
free (xdevfile);
return 0;
}
+16 -2
View File
@@ -64,7 +64,8 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof
tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
tst-wfile-sync
tests-internal = tst-vtables tst-vtables-interposed tst-readline
@@ -72,6 +73,9 @@ ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
tests += tst-fopenloc
# Add tst-bz24228 only if shared library is enabled since it can never meet its
# objective with static linking because the relevant code just is not there.
tests += tst-bz24228
endif
test-srcs = test-freopen
@@ -152,11 +156,14 @@ CFLAGS-oldtmpfile.c += -fexceptions
CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
tst_wprintf2-ARGS = "Some Text"
test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
generated += test-fmemopen.mtrace test-fmemopen.check
generated += tst-fopenloc.mtrace tst-fopenloc.check
@@ -165,6 +172,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
aux := fileops genops stdfiles stdio strops
ifeq ($(build-shared),yes)
generated += tst-bz24228.mtrace tst-bz24228.check
aux += oldfileops oldstdfiles
endif
@@ -179,7 +187,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
ifeq (yes,$(build-shared))
# Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
# library is enabled since they depend on tst-fopenloc.out.
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
endif
@@ -207,6 +216,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales)
$(objpfx)tst-ungetwc2.out: $(gen-locales)
$(objpfx)tst-widetext.out: $(gen-locales)
$(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
@@ -230,3 +240,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
$(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
$(evaluate-test)
$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
$(evaluate-test)
+12 -4
View File
@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
{
int legacy = 0;
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
legacy = 1;
#endif
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
&& fp->_mode != 0)
&& (legacy || fp->_mode != 0))
{
#ifdef _IO_MTSAFE_IO
int cnt;
@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
__sched_yield ();
#endif
if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
_IO_SETBUF (fp, NULL, 0);
if (fp->_mode > 0)
if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
#ifdef _IO_MTSAFE_IO
@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
/* Make sure that never again the wide char functions can be
used. */
fp->_mode = -1;
if (! legacy)
fp->_mode = -1;
}
#ifdef _IO_MTSAFE_IO
+5
View File
@@ -87,6 +87,11 @@ _IO_check_libio (void)
stdout->_vtable_offset = stderr->_vtable_offset =
((int) sizeof (struct _IO_FILE)
- (int) sizeof (struct _IO_FILE_complete));
if (_IO_stdin_.vtable != &_IO_old_file_jumps
|| _IO_stdout_.vtable != &_IO_old_file_jumps
|| _IO_stderr_.vtable != &_IO_old_file_jumps)
IO_set_accept_foreign_vtables (&_IO_vtable_check);
}
}
+29
View File
@@ -0,0 +1,29 @@
/* BZ #24228 check for memory corruption in legacy libio
Copyright (C) 2019 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 <mcheck.h>
#include <support/test-driver.h>
static int
do_test (void)
{
mtrace ();
return 0;
}
#include <support/test-driver.c>
+5
View File
@@ -0,0 +1,5 @@
# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
# implementation when it is available for the architecture.
{
local: _IO_stdin_used;
};
+1
View File
@@ -232,5 +232,6 @@ do_test (void)
return 0;
}
#define TIMEOUT 100
#define PREPARE prepare
#include <support/test-driver.c>
+39
View File
@@ -0,0 +1,39 @@
/* Test that _IO_wfile_sync does not crash (bug 20568).
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
#include <support/check.h>
#include <support/xunistd.h>
static int
do_test (void)
{
TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
/* Fill the stdio buffer and advance the read pointer. */
TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
/* This calls _IO_wfile_sync, it should not crash. */
TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
/* Verify that the external file offset has been synchronized. */
TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);
return 0;
}
#include <support/test-driver.c>
+1
View File
@@ -0,0 +1 @@
This is a test of _IO_wfile_sync.
+3 -2
View File
@@ -508,11 +508,12 @@ _IO_wfile_sync (FILE *fp)
generate the wide characters up to the current reading
position. */
int nread;
size_t wnread = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
fp->_IO_read_base,
fp->_IO_read_end, delta);
fp->_IO_read_end, wnread);
fp->_IO_read_ptr = fp->_IO_read_base + nread;
delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
}
+3 -1
View File
@@ -14946,7 +14946,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
"+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
"+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
+2 -2
View File
@@ -70,11 +70,11 @@ copy "da_DK"
END LC_NUMERIC
LC_TIME
abday "sab";"ata";/
abday "sap";"ata";/
"mar";"pin";/
"sis";"tal";/
"arf"
day "sabaat";/
day "sapaat";/
"ataasinngorneq";/
"marlunngorneq";/
"pingasunngorneq";/
+4 -1
View File
@@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-malloc_info \
tst-malloc-too-large \
tst-malloc-stats-cancellation \
tst-tcfree1 tst-tcfree2 tst-tcfree3 \
tests-static := \
tst-interpose-static-nothread \
@@ -53,7 +54,7 @@ tests-internal += \
tst-dynarray-at-fail \
ifneq (no,$(have-tunables))
tests += tst-malloc-usable-tunables
tests += tst-malloc-usable-tunables tst-mxfast
tests-static += tst-malloc-usable-static-tunables
endif
@@ -195,6 +196,8 @@ tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV)
tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3
tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV)
tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0
ifeq ($(experimental-malloc),yes)
CPPFLAGS-malloc.c += -DUSE_TCACHE=1
else
+2
View File
@@ -237,6 +237,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t)
TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t)
#endif
TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t)
#else
/* Initialization routine. */
#include <string.h>
@@ -324,6 +325,7 @@ ptmalloc_init (void)
TUNABLE_GET (tcache_unsorted_limit, size_t,
TUNABLE_CALLBACK (set_tcache_unsorted_limit));
# endif
TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
#else
const char *s = NULL;
if (__glibc_likely (_environ != NULL))
+107 -73
View File
@@ -321,6 +321,10 @@ __malloc_assert (const char *assertion, const char *file, unsigned int line,
/* This is another arbitrary limit, which tunables can change. Each
tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range
of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX
#endif
@@ -1624,7 +1628,7 @@ static INTERNAL_SIZE_T global_max_fast;
#define set_max_fast(s) \
global_max_fast = (((s) == 0) \
? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
? MIN_CHUNK_SIZE / 2 : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
static inline INTERNAL_SIZE_T
get_max_fast (void)
@@ -2810,6 +2814,7 @@ systrim (size_t pad, mstate av)
static void
munmap_chunk (mchunkptr p)
{
size_t pagesize = GLRO (dl_pagesize);
INTERNAL_SIZE_T size = chunksize (p);
assert (chunk_is_mmapped (p));
@@ -2819,6 +2824,7 @@ munmap_chunk (mchunkptr p)
if (DUMPED_MAIN_ARENA_CHUNK (p))
return;
uintptr_t mem = (uintptr_t) chunk2mem (p);
uintptr_t block = (uintptr_t) p - prev_size (p);
size_t total_size = prev_size (p) + size;
/* Unfortunately we have to do the compilers job by hand here. Normally
@@ -2826,7 +2832,8 @@ munmap_chunk (mchunkptr p)
page size. But gcc does not recognize the optimization possibility
(in the moment at least) so we combine the two values into one before
the bit test. */
if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0))
if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|| __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
malloc_printerr ("munmap_chunk(): invalid pointer");
atomic_decrement (&mp_.n_mmaps);
@@ -2849,16 +2856,22 @@ mremap_chunk (mchunkptr p, size_t new_size)
char *cp;
assert (chunk_is_mmapped (p));
assert (((size + offset) & (GLRO (dl_pagesize) - 1)) == 0);
uintptr_t block = (uintptr_t) p - offset;
uintptr_t mem = (uintptr_t) chunk2mem(p);
size_t total_size = offset + size;
if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|| __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
malloc_printerr("mremap_chunk(): invalid pointer");
/* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
new_size = ALIGN_UP (new_size + offset + SIZE_SZ, pagesize);
/* No need to remap if the number of pages does not change. */
if (size + offset == new_size)
if (total_size == new_size)
return p;
cp = (char *) __mremap ((char *) p - offset, size + offset, new_size,
cp = (char *) __mremap ((char *) block, total_size, new_size,
MREMAP_MAYMOVE);
if (cp == MAP_FAILED)
@@ -2888,6 +2901,8 @@ mremap_chunk (mchunkptr p, size_t new_size)
typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
struct tcache_perthread_struct *key;
} tcache_entry;
/* There is one of these for each thread, which contains the
@@ -2897,7 +2912,7 @@ typedef struct tcache_entry
time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
char counts[TCACHE_MAX_BINS];
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
@@ -2910,7 +2925,11 @@ static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
assert (tc_idx < TCACHE_MAX_BINS);
/* Mark this chunk as "in the tcache" so the test in _int_free will
detect a double free. */
e->key = tcache;
e->next = tcache->entries[tc_idx];
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
@@ -2922,10 +2941,9 @@ static __always_inline void *
tcache_get (size_t tc_idx)
{
tcache_entry *e = tcache->entries[tc_idx];
assert (tc_idx < TCACHE_MAX_BINS);
assert (tcache->entries[tc_idx] > 0);
tcache->entries[tc_idx] = e->next;
--(tcache->counts[tc_idx]);
e->key = NULL;
return (void *) e;
}
@@ -3027,9 +3045,8 @@ __libc_malloc (size_t bytes)
DIAG_PUSH_NEEDS_COMMENT;
if (tc_idx < mp_.tcache_bins
/*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
&& tcache
&& tcache->entries[tc_idx] != NULL)
&& tcache->counts[tc_idx] > 0)
{
return tcache_get (tc_idx);
}
@@ -3716,11 +3733,22 @@ _int_malloc (mstate av, size_t bytes)
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
{
bck = victim->bk;
if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (chunksize_nomask (victim)
> av->system_mem, 0))
malloc_printerr ("malloc(): memory corruption");
size = chunksize (victim);
mchunkptr next = chunk_at_offset (victim, size);
if (__glibc_unlikely (size <= 2 * SIZE_SZ)
|| __glibc_unlikely (size > av->system_mem))
malloc_printerr ("malloc(): invalid size (unsorted)");
if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|| __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
malloc_printerr ("malloc(): invalid next size (unsorted)");
if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
if (__glibc_unlikely (bck->fd != victim)
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
malloc_printerr ("malloc(): unsorted double linked list corrupted");
if (__glibc_unlikely (prev_inuse (next)))
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
/*
If a small request, try to use last remainder if it is the
@@ -3841,10 +3869,14 @@ _int_malloc (mstate av, size_t bytes)
{
victim->fd_nextsize = fwd;
victim->bk_nextsize = fwd->bk_nextsize;
if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
fwd->bk_nextsize = victim;
victim->bk_nextsize->fd_nextsize = victim;
}
bck = fwd->bk;
if (bck->fd != fwd)
malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
}
}
else
@@ -4076,6 +4108,9 @@ _int_malloc (mstate av, size_t bytes)
victim = av->top;
size = chunksize (victim);
if (__glibc_unlikely (size > av->system_mem))
malloc_printerr ("malloc(): corrupted top size");
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
{
remainder_size = size - nb;
@@ -4151,13 +4186,33 @@ _int_free (mstate av, mchunkptr p, int have_lock)
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache
&& tc_idx < mp_.tcache_bins
&& tcache->counts[tc_idx] < mp_.tcache_count)
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
tcache_put (p, tc_idx);
return;
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache))
{
tcache_entry *tmp;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = tmp->next)
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
#endif
@@ -4278,6 +4333,8 @@ _int_free (mstate av, mchunkptr p, int have_lock)
prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink(av, p, bck, fwd);
}
@@ -4439,6 +4496,8 @@ static void malloc_consolidate(mstate av)
prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size in fastbins");
unlink(av, p, bck, fwd);
}
@@ -4498,11 +4557,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
unsigned long copysize; /* bytes to copy */
unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */
INTERNAL_SIZE_T* s; /* copy source */
INTERNAL_SIZE_T* d; /* copy destination */
/* oldmem size */
if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (oldsize >= av->system_mem, 0))
@@ -4570,43 +4624,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
}
else
{
/*
Unroll copy of <= 36 bytes (72 if 8byte sizes)
We know that contents have an odd number of
INTERNAL_SIZE_T-sized words; minimally 3.
*/
copysize = oldsize - SIZE_SZ;
s = (INTERNAL_SIZE_T *) (chunk2mem (oldp));
d = (INTERNAL_SIZE_T *) (newmem);
ncopies = copysize / sizeof (INTERNAL_SIZE_T);
assert (ncopies >= 3);
if (ncopies > 9)
memcpy (d, s, copysize);
else
{
*(d + 0) = *(s + 0);
*(d + 1) = *(s + 1);
*(d + 2) = *(s + 2);
if (ncopies > 4)
{
*(d + 3) = *(s + 3);
*(d + 4) = *(s + 4);
if (ncopies > 6)
{
*(d + 5) = *(s + 5);
*(d + 6) = *(s + 6);
if (ncopies > 8)
{
*(d + 7) = *(s + 7);
*(d + 8) = *(s + 8);
}
}
}
}
memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ);
_int_free (av, oldp, 1);
check_inuse_chunk (av, newp);
return chunk2mem (newp);
@@ -5104,8 +5122,11 @@ static inline int
__always_inline
do_set_tcache_count (size_t value)
{
LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
mp_.tcache_count = value;
if (value <= MAX_TCACHE_COUNT)
{
LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
mp_.tcache_count = value;
}
return 1;
}
@@ -5119,6 +5140,19 @@ do_set_tcache_unsorted_limit (size_t value)
}
#endif
static inline int
__always_inline
do_set_mxfast (size_t value)
{
if (value >= 0 && value <= MAX_FAST_SIZE)
{
LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
set_max_fast (value);
return 1;
}
return 0;
}
int
__libc_mallopt (int param_number, int value)
{
@@ -5138,13 +5172,7 @@ __libc_mallopt (int param_number, int value)
switch (param_number)
{
case M_MXFAST:
if (value >= 0 && value <= MAX_FAST_SIZE)
{
LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
set_max_fast (value);
}
else
res = 0;
do_set_mxfast (value);
break;
case M_TRIM_THRESHOLD:
@@ -5410,6 +5438,12 @@ __malloc_info (int options, FILE *fp)
__libc_lock_lock (ar_ptr->mutex);
/* Account for top chunk. The top-most available chunk is
treated specially and is never in any bin. See "initial_top"
comments. */
avail = chunksize (ar_ptr->top);
nblocks = 1; /* Top always exists. */
for (size_t i = 0; i < NFASTBINS; ++i)
{
mchunkptr p = fastbin (ar_ptr, i);
@@ -5495,7 +5529,7 @@ __malloc_info (int options, FILE *fp)
for (size_t i = 0; i < nsizes; ++i)
if (sizes[i].count != 0 && i != NFASTBINS)
fprintf (fp, " \
fprintf (fp, "\
<size from=\"%zu\" to=\"%zu\" total=\"%zu\" count=\"%zu\"/>\n",
sizes[i].from, sizes[i].to, sizes[i].total, sizes[i].count);
+50
View File
@@ -0,0 +1,50 @@
/* Test that glibc.malloc.mxfast tunable works.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test verifies that setting the glibc.malloc.mxfast tunable to
zero results in free'd blocks being returned to the small bins, not
the fast bins. */
#include <malloc.h>
#include <support/check.h>
int
do_test (void)
{
struct mallinfo m;
char *volatile p1;
char *volatile p2;
/* Arbitrary value; must be in default fastbin range. */
p1 = malloc (3);
/* Something large so that p1 isn't a "top block" */
p2 = malloc (512);
free (p1);
m = mallinfo ();
/* This will fail if there are any blocks in the fastbins. */
TEST_COMPARE (m.smblks, 0);
/* To keep gcc happy. */
free (p2);
return 0;
}
#include <support/test-driver.c>
+42
View File
@@ -0,0 +1,42 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <limits.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/signal.h>
static int
do_test (void)
{
/* Do one allocation of any size that fits in tcache. */
char * volatile x = malloc (32);
free (x); // puts in tcache
free (x); // should abort
printf("FAIL: tcache double free not detected\n");
return 1;
}
#define TEST_FUNCTION do_test
#define EXPECTED_SIGNAL SIGABRT
#include <support/test-driver.c>
+48
View File
@@ -0,0 +1,48 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <limits.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/signal.h>
static int
do_test (void)
{
char * volatile ptrs[20];
int i;
/* Allocate enough small chunks so that when we free them all, the tcache
is full, and the first one we freed is at the end of its linked list. */
#define COUNT 20
for (i=0; i<COUNT; i++)
ptrs[i] = malloc (20);
for (i=0; i<COUNT; i++)
free (ptrs[i]);
free (ptrs[0]);
printf("FAIL: tcache double free\n");
return 1;
}
#define TEST_FUNCTION do_test
#define EXPECTED_SIGNAL SIGABRT
#include <support/test-driver.c>
+56
View File
@@ -0,0 +1,56 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <malloc.h>
#include <string.h>
/* Prevent GCC from optimizing away any malloc/free pairs. */
#pragma GCC optimize ("O0")
static int
do_test (void)
{
/* Do two allocation of any size that fit in tcache, and one that
doesn't. */
int ** volatile a = malloc (32);
int ** volatile b = malloc (32);
/* This is just under the mmap threshold. */
int ** volatile c = malloc (127 * 1024);
/* The invalid "tcache bucket" we might dereference will likely end
up somewhere within this memory block, so make all the accidental
"next" pointers cause segfaults. BZ #23907. */
memset (c, 0xff, 127 * 1024);
free (a); // puts in tcache
/* A is now free and contains the key we use to detect in-tcache.
Copy the key to the other chunks. */
memcpy (b, a, 32);
memcpy (c, a, 32);
/* This free tests the "are we in the tcache already" loop with a
VALID bin but "coincidental" matching key. */
free (b); // should NOT abort
/* This free tests the "is it a valid tcache bin" test. */
free (c); // should NOT abort
return 0;
}
#include <support/test-driver.c>
+5 -5
View File
@@ -1404,10 +1404,13 @@ failure occurs. The return value is zero if the end of the input file
is encountered immediately.
If no bytes can be copied, to report an error, @code{copy_file_range}
returns the value @math{-1} and sets @code{errno}. The following
@code{errno} error conditions are specific to this function:
returns the value @math{-1} and sets @code{errno}. The table below
lists some of the error conditions for this function.
@table @code
@item ENOSYS
The kernel does not implement the required functionality.
@item EISDIR
At least one of the descriptors @var{inputfd} or @var{outputfd} refers
to a directory.
@@ -1437,9 +1440,6 @@ reading.
The argument @var{outputfd} is not a valid file descriptor open for
writing, or @var{outputfd} has been opened with @code{O_APPEND}.
@item EXDEV
The input and output files reside on different file systems.
@end table
In addition, @code{copy_file_range} can fail with the error codes
+12
View File
@@ -243,6 +243,18 @@ This probe is triggered when the
value of this tunable.
@end deftp
@deftp Probe memory_tcache_double_free (void *@var{$arg1}, int @var{$arg2})
This probe is triggered when @code{free} determines that the memory
being freed has probably already been freed, and resides in the
per-thread cache. Note that there is an extremely unlikely chance
that this probe will trigger due to random payload data remaining in
the allocated memory matching the key used to detect double frees.
This probe actually indicates that an expensive linear search of the
tcache, looking for a double free, has happened. Argument @var{$arg1}
is the memory location as passed to @code{free}, Argument @var{$arg2}
is the tcache bin it resides in.
@end deftp
@node Mathematical Function Probes
@section Mathematical Function Probes
+15 -3
View File
@@ -188,8 +188,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
@deftp Tunable glibc.malloc.tcache_count
The maximum number of chunks of each size to cache. The default is 7.
There is no upper limit, other than available system memory. If set
to zero, the per-thread cache is effectively disabled.
The upper limit is 65535. If set to zero, the per-thread cache is effectively
disabled.
The approximate maximum overhead of the per-thread cache is thus equal
to the number of bins times the chunk count in each bin times the size
@@ -213,6 +213,18 @@ pre-fill the per-thread cache with. The default, or when set to zero,
is no limit.
@end deftp
@deftp Tunable glibc.malloc.mxfast
One of the optimizations malloc uses is to maintain a series of ``fast
bins'' that hold chunks up to a specific size. The default and
maximum size which may be held this way is 80 bytes on 32-bit systems
or 160 bytes on 64-bit systems. Applications which value size over
speed may choose to reduce the size of requests which are serviced
from fast bins with this tunable. Note that the value specified
includes malloc's internal overhead, which is normally the size of one
pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size
passed to @code{malloc} for the largest bin size to enable.
@end deftp
@node Elision Tunables
@section Elision Tunables
@cindex elision tunables
@@ -333,7 +345,7 @@ This tunable is specific to powerpc, powerpc64 and powerpc64le.
The @code{glibc.tune.cpu=xxx} tunable allows the user to tell @theglibc{} to
assume that the CPU is @code{xxx} where xxx may have one of these values:
@code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99},
@code{thunderx2t99p1}.
@code{thunderx2t99p1}, @code{ares}.
This tunable is specific to aarch64.
@end deftp
+8 -8
View File
@@ -119,32 +119,32 @@ static const struct test_fff_f_data fma_test_data[] =
TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
AUTO_TESTS_fff_f (fma),
};
+7
View File
@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
tst-preadvwritev2 tst-preadvwritev64v2
# Tests which need libdl.
ifeq (yes,$(build-shared))
tests += tst-gethostid
endif
tests-internal := tst-atomic tst-atomic-long tst-allocate_once
tests-static := tst-empty
@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace
$(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
$(evaluate-test)
$(objpfx)tst-gethostid: $(libdl)
+2
View File
@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...)
va_start (args, message);
error_tail (status, errnum, message, args);
va_end (args);
#ifdef _LIBC
_IO_funlockfile (stderr);
@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name,
va_start (args, message);
error_tail (status, errnum, message, args);
va_end (args);
#ifdef _LIBC
_IO_funlockfile (stderr);
+108
View File
@@ -0,0 +1,108 @@
/* Basic test for gethostid.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <gnu/lib-names.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/namespace.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/xdlfcn.h>
#include <support/xstdio.h>
#include <support/xunistd.h>
#include <unistd.h>
/* Initial test is run outside a chroot, to increase the likelihood of
success. */
static void
outside_chroot (void *closure)
{
long id = gethostid ();
printf ("info: host ID outside chroot: 0x%lx\n", id);
}
/* The same, but this time perform a chroot operation. */
static void
in_chroot (void *closure)
{
const char *chroot_path = closure;
xchroot (chroot_path);
long id = gethostid ();
printf ("info: host ID in chroot: 0x%lx\n", id);
}
static int
do_test (void)
{
support_isolate_in_subprocess (outside_chroot, NULL);
/* Now run the test inside a chroot. */
support_become_root ();
if (!support_can_chroot ())
/* Cannot perform further tests. */
return 0;
/* Only use nss_files. */
__nss_configure_lookup ("hosts", "files");
/* Load the DSO outside of the chroot. */
xdlopen (LIBNSS_FILES_SO, RTLD_LAZY);
char *chroot_dir = support_create_temp_directory ("tst-gethostid-");
support_isolate_in_subprocess (in_chroot, chroot_dir);
/* Tests with /etc/hosts in the chroot. */
{
char *path = xasprintf ("%s/etc", chroot_dir);
add_temp_file (path);
xmkdir (path, 0777);
free (path);
path = xasprintf ("%s/etc/hosts", chroot_dir);
add_temp_file (path);
FILE *fp = xfopen (path, "w");
xfclose (fp);
printf ("info: chroot test with an empty /etc/hosts file\n");
support_isolate_in_subprocess (in_chroot, chroot_dir);
char hostname[1024];
int ret = gethostname (hostname, sizeof (hostname));
if (ret < 0)
printf ("warning: invalid result from gethostname: %d\n", ret);
else if (strlen (hostname) == 0)
puts ("warning: gethostname returned empty string");
else
{
printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n",
hostname);
fp = xfopen (path, "w");
/* Use an IPv6 address to induce another lookup failure. */
fprintf (fp, "2001:db8::1 %s\n", hostname);
xfclose (fp);
support_isolate_in_subprocess (in_chroot, chroot_dir);
}
free (path);
}
free (chroot_dir);
return 0;
}
#include <support/test-driver.c>
+62 -3
View File
@@ -19,9 +19,6 @@
#include <limits.h>
#include <support/check.h>
static void
do_test_with_invalid_flags (void)
{
#ifndef RWF_HIPRI
# define RWF_HIPRI 0
#endif
@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void)
#endif
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \
| RWF_APPEND)
static void
do_test_with_invalid_fd (void)
{
char buf[256];
struct iovec iov = { buf, sizeof buf };
/* Check with flag being 0 to use the fallback code which calls pwritev
or writev. */
TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1);
TEST_COMPARE (errno, EBADF);
TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1);
TEST_COMPARE (errno, EBADF);
/* Same tests as before but with flags being different than 0. Since
there is no emulation for any flag value, fallback code returns
ENOTSUP. This is different running on a kernel with preadv2/pwritev2
support, where EBADF is returned). */
TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
}
static void
do_test_with_invalid_iov (void)
{
{
char buf[256];
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = (size_t)SSIZE_MAX + 1;
TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1);
TEST_COMPARE (errno, EINVAL);
TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1);
TEST_COMPARE (errno, EINVAL);
/* Same as for invalid file descriptor tests, emulation fallback
first checks for flag value and return ENOTSUP. */
TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
}
{
/* An invalid iovec buffer should trigger an invalid memory access
or an error (Linux for instance returns EFAULT). */
struct iovec iov[IOV_MAX+1] = { 0 };
TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
}
}
static void
do_test_with_invalid_flags (void)
{
/* Set the next bit from the mask of all supported flags. */
int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2;
invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag);
+2
View File
@@ -30,6 +30,8 @@ do_test (void)
{
do_test_with_invalid_flags ();
do_test_without_offset ();
do_test_with_invalid_fd ();
do_test_with_invalid_iov ();
return do_test_with_offset (0);
}
+2
View File
@@ -32,6 +32,8 @@ do_test (void)
{
do_test_with_invalid_flags ();
do_test_without_offset ();
do_test_with_invalid_fd ();
do_test_with_invalid_iov ();
return do_test_with_offset (0);
}
+23 -6
View File
@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++
tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \
tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
tst-mutexpi9 \
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
@@ -318,7 +318,10 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
tst-minstack-throw \
tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
tst-rwlock-pwn \
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
tst-unwind-thread
tests-internal := tst-rwlock19 tst-rwlock20 \
tst-sem11 tst-sem12 tst-sem13 \
@@ -382,7 +385,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
tst-oncex3 tst-oncex4
ifeq ($(build-shared),yes)
tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder
tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \
tst-audit-threads
tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1
tests-nolibpthread += tst-fini1
ifeq ($(have-z-execstack),yes)
@@ -394,7 +398,8 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
tst-join7mod tst-compat-forwarder-mod
tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \
tst-audit-threads-mod2
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \
tst-cleanup4aux.o tst-cleanupx4aux.o
test-extras += tst-cleanup4aux tst-cleanupx4aux
@@ -709,6 +714,18 @@ endif
$(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
# Protect against a build using -Wl,-z,now.
LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy
LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy
LDFLAGS-tst-audit-threads = -Wl,-z,lazy
$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so
$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so
tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
CFLAGS-tst-unwind-thread.c += -funwind-tables
# The tests here better do not run in parallel
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
.NOTPARALLEL:
+3 -1
View File
@@ -572,7 +572,9 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
/* Place the thread descriptor at the end of the stack. */
#if TLS_TCB_AT_TP
pd = (struct pthread *) ((char *) mem + size) - 1;
pd = (struct pthread *) ((((uintptr_t) mem + size)
- TLS_TCB_SIZE)
& ~__static_tls_align_m1);
#elif TLS_DTV_AT_TP
pd = (struct pthread *) ((((uintptr_t) mem + size
- __static_tls_size)
+8 -4
View File
@@ -110,19 +110,23 @@ enum
};
#define PTHREAD_MUTEX_PSHARED_BIT 128
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
#define PTHREAD_MUTEX_TYPE(m) \
((m)->__data.__kind & 127)
(atomic_load_relaxed (&((m)->__data.__kind)) & 127)
/* Don't include NO_ELISION, as that type is always the same
as the underlying lock type. */
#define PTHREAD_MUTEX_TYPE_ELISION(m) \
((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP))
(atomic_load_relaxed (&((m)->__data.__kind)) \
& (127 | PTHREAD_MUTEX_ELISION_NP))
#if LLL_PRIVATE == 0 && LLL_SHARED == 128
# define PTHREAD_MUTEX_PSHARED(m) \
((m)->__data.__kind & 128)
(atomic_load_relaxed (&((m)->__data.__kind)) & 128)
#else
# define PTHREAD_MUTEX_PSHARED(m) \
(((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE)
((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
? LLL_SHARED : LLL_PRIVATE)
#endif
/* The kernel when waking robust mutexes on exit never uses
+6 -2
View File
@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
{
/* There is still a waiter after spinning. Set the wake-request
flag and block. Relaxed MO is fine because this is just about
this futex word. */
r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1);
this futex word.
Update r to include the set wake-request flag so that the upcoming
futex_wait only blocks if the flag is still set (otherwise, we'd
violate the basic client-side futex protocol). */
r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1;
if ((r >> 1) > 0)
futex_wait_simple (cond->__data.__g_refs + g1, r, private);
+1 -1
View File
@@ -516,7 +516,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec rt;
if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
__libc_fatal ("clock_gettime does not support "
"CLOCK_MONOTONIC");
"CLOCK_MONOTONIC\n");
/* Convert the absolute timeout value to a relative
timeout. */
rt.tv_sec = abstime->tv_sec - rt.tv_sec;
+5 -2
View File
@@ -23,8 +23,11 @@
int
pthread_mutex_consistent (pthread_mutex_t *mutex)
{
/* Test whether this is a robust mutex with a dead owner. */
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
/* Test whether this is a robust mutex with a dead owner.
See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|| mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT)
return EINVAL;
+8 -3
View File
@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex)
{
LIBC_PROBE (mutex_destroy, 1, mutex);
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
&& mutex->__data.__nusers != 0)
return EBUSY;
/* Set to an invalid value. */
mutex->__data.__kind = -1;
/* Set to an invalid value. Relaxed MO is enough as it is undefined behavior
if the mutex is used after it has been destroyed. But you can reinitialize
it with pthread_mutex_init. */
atomic_store_relaxed (&(mutex->__data.__kind), -1);
return 0;
}
+3 -1
View File
@@ -24,7 +24,9 @@
int
pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling)
{
if (__builtin_expect ((mutex->__data.__kind
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
return EINVAL;
+9 -5
View File
@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
/* Copy the values from the attribute. */
mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
{
@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
return ENOTSUP;
#endif
mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
}
switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
{
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
break;
case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
int ceiling = (imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
| PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind);
/* Default values: mutex not used yet. */
// mutex->__count = 0; already done by memset
+21 -7
View File
@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
int
__pthread_mutex_lock (pthread_mutex_t *mutex)
{
/* See concurrency notes regarding mutex type which is loaded from __kind
in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
LIBC_PROBE (mutex_entry, 1, mutex);
@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
int kind, robust;
{
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
}
if (robust)
{
@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
case PTHREAD_MUTEX_PP_NORMAL_NP:
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int kind = atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_KIND_MASK_NP;
oldval = mutex->__data.__lock;
@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock)
void
__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
{
assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
/* Record the ownership. */
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
mutex->__data.__owner = id;
if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
++mutex->__data.__count;
}
#endif
+4 -3
View File
@@ -27,9 +27,10 @@ int
pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
int *old_ceiling)
{
/* The low bits of __kind aren't ever changed after pthread_mutex_init,
so we don't need a lock yet. */
if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
return EINVAL;
/* See __init_sched_fifo_prio. */
+14 -3
View File
@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
/* We must not check ABSTIME here. If the thread does not block
abstime must not be checked for a valid value. */
/* See concurrency notes regarding mutex type which is loaded from __kind
in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
PTHREAD_MUTEX_TIMED_NP))
{
@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
int kind, robust;
{
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
}
if (robust)
{
@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
case PTHREAD_MUTEX_PP_NORMAL_NP:
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int kind = atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_KIND_MASK_NP;
oldval = mutex->__data.__lock;
+73 -9
View File
@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
int oldval;
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
/* See concurrency notes regarding mutex type which is loaded from __kind
in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
PTHREAD_MUTEX_TIMED_NP))
{
@@ -54,7 +56,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
return 0;
}
if (lll_trylock (mutex->__data.__lock) == 0)
if (atomic_load_relaxed (&(mutex->__data.__lock)) == 0
&& lll_trylock (mutex->__data.__lock) == 0)
{
/* Record the ownership. */
mutex->__data.__owner = id;
@@ -77,7 +80,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
/*FALL THROUGH*/
case PTHREAD_MUTEX_ADAPTIVE_NP:
case PTHREAD_MUTEX_ERRORCHECK_NP:
if (lll_trylock (mutex->__data.__lock) != 0)
/* Mutex type is already loaded, lock check overhead should
be minimal. */
if (atomic_load_relaxed (&(mutex->__data.__lock)) != 0
|| lll_trylock (mutex->__data.__lock) != 0)
break;
/* Record the ownership. */
@@ -92,6 +98,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
&mutex->__data.__list.__next);
/* We need to set op_pending before starting the operation. Also
see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
oldval = mutex->__data.__lock;
do
@@ -117,7 +126,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
/* But it is inconsistent unless marked otherwise. */
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
/* We must not enqueue the mutex before we have acquired it.
Also see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
ENQUEUE_MUTEX (mutex);
/* We need to clear op_pending after we enqueue the mutex. */
__asm ("" ::: "memory");
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
/* Note that we deliberately exist here. If we fall
@@ -133,6 +147,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
int kind = PTHREAD_MUTEX_TYPE (mutex);
if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
{
/* We do not need to ensure ordering wrt another memory
access. Also see comments at ENQUEUE_MUTEX. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
NULL);
return EDEADLK;
@@ -140,6 +156,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
{
/* We do not need to ensure ordering wrt another memory
access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
NULL);
@@ -158,6 +176,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
id, 0);
if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
{
/* We haven't acquired the lock as it is already acquired by
another owner. We do not need to ensure ordering wrt another
memory access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return EBUSY;
@@ -171,13 +192,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
if (oldval == id)
lll_unlock (mutex->__data.__lock,
PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
/* FIXME This violates the mutex destruction requirements. See
__pthread_mutex_unlock_full. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return ENOTRECOVERABLE;
}
}
while ((oldval & FUTEX_OWNER_DIED) != 0);
/* We must not enqueue the mutex before we have acquired it.
Also see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
ENQUEUE_MUTEX (mutex);
/* We need to clear op_pending after we enqueue the mutex. */
__asm ("" ::: "memory");
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
mutex->__data.__owner = id;
@@ -199,14 +227,25 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
int kind, robust;
{
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
}
if (robust)
/* Note: robust PI futexes are signaled by setting bit 0. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
(void *) (((uintptr_t) &mutex->__data.__list.__next)
| 1));
{
/* Note: robust PI futexes are signaled by setting bit 0. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
(void *) (((uintptr_t) &mutex->__data.__list.__next)
| 1));
/* We need to set op_pending before starting the operation. Also
see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
}
oldval = mutex->__data.__lock;
@@ -215,12 +254,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
{
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
{
/* We do not need to ensure ordering wrt another memory
access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return EDEADLK;
}
if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
{
/* We do not need to ensure ordering wrt another memory
access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
/* Just bump the counter. */
@@ -242,6 +285,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
{
if ((oldval & FUTEX_OWNER_DIED) == 0)
{
/* We haven't acquired the lock as it is already acquired by
another owner. We do not need to ensure ordering wrt another
memory access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return EBUSY;
@@ -262,6 +308,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
if (INTERNAL_SYSCALL_ERROR_P (e, __err)
&& INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
{
/* The kernel has not yet finished the mutex owner death.
We do not need to ensure ordering wrt another memory
access. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return EBUSY;
@@ -279,7 +328,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
/* But it is inconsistent unless marked otherwise. */
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
/* We must not enqueue the mutex before we have acquired it.
Also see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
ENQUEUE_MUTEX (mutex);
/* We need to clear op_pending after we enqueue the mutex. */
__asm ("" ::: "memory");
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
/* Note that we deliberately exit here. If we fall
@@ -302,13 +356,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
0, 0);
/* To the kernel, this will be visible after the kernel has
acquired the mutex in the syscall. */
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
return ENOTRECOVERABLE;
}
if (robust)
{
/* We must not enqueue the mutex before we have acquired it.
Also see comments at ENQUEUE_MUTEX. */
__asm ("" ::: "memory");
ENQUEUE_MUTEX_PI (mutex);
/* We need to clear op_pending after we enqueue the mutex. */
__asm ("" ::: "memory");
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
}
@@ -325,7 +386,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
case PTHREAD_MUTEX_PP_NORMAL_NP:
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int kind = atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_KIND_MASK_NP;
oldval = mutex->__data.__lock;
+14 -3
View File
@@ -35,6 +35,8 @@ int
attribute_hidden
__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
{
/* See concurrency notes regarding mutex type which is loaded from __kind
in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
if (__builtin_expect (type &
~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
/* If the previous owner died and the caller did not succeed in
making the state consistent, mark the mutex as unrecoverable
and make all waiters. */
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
&& __builtin_expect (mutex->__data.__owner
== PTHREAD_MUTEX_INCONSISTENT, 0))
pi_notrecoverable:
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
if ((atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
{
continue_pi_robust:
/* Remove mutex from the list.
@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
/* Unlock. Load all necessary mutex data before releasing the mutex
to not violate the mutex destruction requirements (see
lll_unlock). */
int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
/* See concurrency notes regarding __kind in struct __pthread_mutex_s
in sysdeps/nptl/bits/thread-shared-types.h. */
int robust = atomic_load_relaxed (&(mutex->__data.__kind))
& PTHREAD_MUTEX_ROBUST_NORMAL_NP;
private = (robust
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
: PTHREAD_MUTEX_PSHARED (mutex));
+2 -2
View File
@@ -314,8 +314,8 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
harmless because the flag is just about the state of
__readers, and all threads set the flag under the same
conditions. */
while ((atomic_load_relaxed (&rwlock->__data.__readers)
& PTHREAD_RWLOCK_RWAITING) != 0)
while (((r = atomic_load_relaxed (&rwlock->__data.__readers))
& PTHREAD_RWLOCK_RWAITING) != 0)
{
int private = __pthread_rwlock_get_private (rwlock);
int err = futex_abstimed_wait (&rwlock->__data.__readers,
+16 -9
View File
@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
/* Same as in __pthread_rwlock_rdlock_full:
We started the read phase, so we are also responsible for
updating the write-phase futex. Relaxed MO is sufficient.
Note that there can be no other reader that we have to wake
because all other readers will see the read phase started by us
(or they will try to start it themselves); if a writer started
the read phase, we cannot have started it. Furthermore, we
cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
overwrite the value set by the most recent writer (or the readers
before it in case of explicit hand-over) and we know that there
are no waiting readers. */
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
We have to do the same steps as a writer would when handing over the
read phase to use because other readers cannot distinguish between
us and the writer.
Note that __pthread_rwlock_tryrdlock callers will not have to be
woken up because they will either see the read phase started by us
or they will try to start it themselves; however, callers of
__pthread_rwlock_rdlock_full just increase the reader count and then
check what state the lock is in, so they cannot distinguish between
us and a writer that acquired and released the lock in the
meantime. */
if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
& PTHREAD_RWLOCK_FUTEX_USED) != 0)
{
int private = __pthread_rwlock_get_private (rwlock);
futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
}
}
return 0;
+8 -1
View File
@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
&rwlock->__data.__readers, &r,
r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
{
/* We have become the primary writer and we cannot have shared
the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we
can simply enable blocking (see full wrlock code). */
atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
/* If we started a write phase, we need to enable readers to
wait. If we did not, we must not change it because other threads
may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */
if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
atomic_store_relaxed (&rwlock->__data.__cur_writer,
THREAD_GETMEM (THREAD_SELF, tid));
return 0;
+5 -3
View File
@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle)
}
void
__run_fork_handlers (enum __run_fork_handler_type who)
__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
{
struct fork_handler *runp;
if (who == atfork_run_prepare)
{
lll_lock (atfork_lock, LLL_PRIVATE);
if (do_locking)
lll_lock (atfork_lock, LLL_PRIVATE);
size_t sl = fork_handler_list_size (&fork_handlers);
for (size_t i = sl; i > 0; i--)
{
@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who)
else if (who == atfork_run_parent && runp->parent_handler)
runp->parent_handler ();
}
lll_unlock (atfork_lock, LLL_PRIVATE);
if (do_locking)
lll_unlock (atfork_lock, LLL_PRIVATE);
}
}
+74
View File
@@ -0,0 +1,74 @@
/* Dummy audit library for test-audit-threads.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <elf.h>
#include <link.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
/* We must use a dummy LD_AUDIT module to force the dynamic loader to
*not* update the real PLT, and instead use a cached value for the
lazy resolution result. It is the update of that cached value that
we are testing for correctness by doing this. */
/* Library to be audited. */
#define LIB "tst-audit-threads-mod2.so"
/* CALLNUM is the number of retNum functions. */
#define CALLNUM 7999
#define CONCATX(a, b) __CONCAT (a, b)
static int previous = 0;
unsigned int
la_version (unsigned int ver)
{
return 1;
}
unsigned int
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
{
return LA_FLG_BINDTO | LA_FLG_BINDFROM;
}
uintptr_t
CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym,
unsigned int ndx,
uintptr_t *refcook,
uintptr_t *defcook,
unsigned int *flags,
const char *symname)
{
const char * retnum = "retNum";
char * num = strstr (symname, retnum);
int n;
/* Validate if the symbols are getting called in the correct order.
This code is here to verify binutils does not optimize out the PLT
entries that require the symbol binding. */
if (num != NULL)
{
n = atoi (num);
assert (n >= previous);
assert (n <= CALLNUM);
previous = n;
}
return sym->st_value;
}
@@ -1,4 +1,5 @@
/* Syscall wrapper that do not set errno. Linux powerpc version.
/* Shared object with a huge number of functions for test-audit-threads.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,15 +17,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* __access_noerrno is used during process initialization in elf/dl-tunables.c
before the TCB is initialized, prohibiting the usage of
ABORT_TRANSACTION. */
#undef ABORT_TRANSACTION
#define ABORT_TRANSACTION
#include "sysdeps/unix/sysv/linux/not-errno.h"
/* Recover ABORT_TRANSACTION's previous value, in order to not affect
other syscalls. */
#undef ABORT_TRANSACTION
#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
/* Define all the retNumN functions in a library. */
#define definenum
#include "tst-audit-threads.h"
+97
View File
@@ -0,0 +1,97 @@
/* Test multi-threading using LD_AUDIT.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a
library with a huge number of functions in order to validate lazy symbol
binding with an audit library. We use one thread per CPU to test that
concurrent lazy resolution does not have any defects which would cause
the process to fail. We use an LD_AUDIT library to force the testing of
the relocation resolution caching code in the dynamic loader i.e.
_dl_runtime_profile and _dl_profile_fixup. */
#include <support/xthread.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
static int do_test (void);
/* This test usually takes less than 3s to run. However, there are cases that
take up to 30s. */
#define TIMEOUT 60
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
/* Declare the functions we are going to call. */
#define externnum
#include "tst-audit-threads.h"
#undef externnum
int num_threads;
pthread_barrier_t barrier;
void
sync_all (int num)
{
pthread_barrier_wait (&barrier);
}
void
call_all_ret_nums (void)
{
/* Call each function one at a time from all threads. */
#define callnum
#include "tst-audit-threads.h"
#undef callnum
}
void *
thread_main (void *unused)
{
call_all_ret_nums ();
return NULL;
}
#define STR2(X) #X
#define STR(X) STR2(X)
static int
do_test (void)
{
int i;
pthread_t *threads;
num_threads = get_nprocs ();
if (num_threads <= 1)
num_threads = 2;
/* Used to synchronize all the threads after calling each retNumN. */
xpthread_barrier_init (&barrier, NULL, num_threads);
threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t));
for (i = 0; i < num_threads; i++)
threads[i] = xpthread_create(NULL, thread_main, NULL);
for (i = 0; i < num_threads; i++)
xpthread_join(threads[i]);
free (threads);
return 0;
}
+92
View File
@@ -0,0 +1,92 @@
/* Helper header for test-audit-threads.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* We use this helper to create a large number of functions, all of
which will be resolved lazily and thus have their PLT updated.
This is done to provide enough functions that we can statistically
observe a thread vs. PLT resolution failure if one exists. */
#define CONCAT(a, b) a ## b
#define NUM(x, y) CONCAT (x, y)
#define FUNC10(x) \
FUNC (NUM (x, 0)); \
FUNC (NUM (x, 1)); \
FUNC (NUM (x, 2)); \
FUNC (NUM (x, 3)); \
FUNC (NUM (x, 4)); \
FUNC (NUM (x, 5)); \
FUNC (NUM (x, 6)); \
FUNC (NUM (x, 7)); \
FUNC (NUM (x, 8)); \
FUNC (NUM (x, 9))
#define FUNC100(x) \
FUNC10 (NUM (x, 0)); \
FUNC10 (NUM (x, 1)); \
FUNC10 (NUM (x, 2)); \
FUNC10 (NUM (x, 3)); \
FUNC10 (NUM (x, 4)); \
FUNC10 (NUM (x, 5)); \
FUNC10 (NUM (x, 6)); \
FUNC10 (NUM (x, 7)); \
FUNC10 (NUM (x, 8)); \
FUNC10 (NUM (x, 9))
#define FUNC1000(x) \
FUNC100 (NUM (x, 0)); \
FUNC100 (NUM (x, 1)); \
FUNC100 (NUM (x, 2)); \
FUNC100 (NUM (x, 3)); \
FUNC100 (NUM (x, 4)); \
FUNC100 (NUM (x, 5)); \
FUNC100 (NUM (x, 6)); \
FUNC100 (NUM (x, 7)); \
FUNC100 (NUM (x, 8)); \
FUNC100 (NUM (x, 9))
#define FUNC7000() \
FUNC1000 (1); \
FUNC1000 (2); \
FUNC1000 (3); \
FUNC1000 (4); \
FUNC1000 (5); \
FUNC1000 (6); \
FUNC1000 (7);
#ifdef FUNC
# undef FUNC
#endif
#ifdef externnum
# define FUNC(x) extern int CONCAT (retNum, x) (void)
#endif
#ifdef definenum
# define FUNC(x) int CONCAT (retNum, x) (void) { return x; }
#endif
#ifdef callnum
# define FUNC(x) CONCAT (retNum, x) (); sync_all (x)
#endif
/* A value of 7000 functions is chosen as an arbitrarily large
number of functions that will allow us enough attempts to
verify lazy resolution operation. */
FUNC7000 ();
+109
View File
@@ -0,0 +1,109 @@
/* Testing race while enabling lock elision.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <getopt.h>
#include <support/support.h>
#include <support/xthread.h>
static pthread_barrier_t barrier;
static pthread_mutex_t mutex;
static long long int iteration_count = 1000000;
static unsigned int thread_count = 3;
static void *
thr_func (void *arg)
{
long long int i;
for (i = 0; i < iteration_count; i++)
{
if ((uintptr_t) arg == 0)
{
xpthread_mutex_destroy (&mutex);
xpthread_mutex_init (&mutex, NULL);
}
xpthread_barrier_wait (&barrier);
/* Test if enabling lock elision works if it is enabled concurrently.
There was a race in FORCE_ELISION macro which leads to either
pthread_mutex_destroy returning EBUSY as the owner was recorded
by pthread_mutex_lock - in "normal mutex" code path - but was not
resetted in pthread_mutex_unlock - in "elision" code path.
Or it leads to the assertion in nptl/pthread_mutex_lock.c:
assert (mutex->__data.__owner == 0);
Please ensure that the test is run with lock elision:
export GLIBC_TUNABLES=glibc.elision.enable=1 */
xpthread_mutex_lock (&mutex);
xpthread_mutex_unlock (&mutex);
xpthread_barrier_wait (&barrier);
}
return NULL;
}
static int
do_test (void)
{
unsigned int i;
printf ("Starting %d threads to run %lld iterations.\n",
thread_count, iteration_count);
pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t));
xpthread_barrier_init (&barrier, NULL, thread_count);
xpthread_mutex_init (&mutex, NULL);
for (i = 0; i < thread_count; i++)
threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i);
for (i = 0; i < thread_count; i++)
xpthread_join (threads[i]);
xpthread_barrier_destroy (&barrier);
free (threads);
return EXIT_SUCCESS;
}
#define OPT_ITERATIONS 10000
#define OPT_THREADS 10001
#define CMDLINE_OPTIONS \
{ "iterations", required_argument, NULL, OPT_ITERATIONS }, \
{ "threads", required_argument, NULL, OPT_THREADS },
static void
cmdline_process (int c)
{
long long int arg = strtoll (optarg, NULL, 0);
switch (c)
{
case OPT_ITERATIONS:
if (arg > 0)
iteration_count = arg;
break;
case OPT_THREADS:
if (arg > 0 && arg < 100)
thread_count = arg;
break;
}
}
#define CMDLINE_PROCESS cmdline_process
#define TIMEOUT 50
#include <support/test-driver.c>
+87
View File
@@ -0,0 +1,87 @@
/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861).
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <support/xthread.h>
/* We choose 10 iterations because this happens to be able to trigger the
stall on contemporary hardware. */
#define LOOPS 10
/* We need 3 threads to trigger bug 23861. One thread as a writer, and
two reader threads. The test verifies that the second-to-last reader
is able to notify the *last* reader that it should be done waiting.
If the second-to-last reader fails to notify the last reader or does
so incorrectly then the last reader may stall indefinitely. */
#define NTHREADS 3
_Atomic int do_exit;
pthread_rwlockattr_t mylock_attr;
pthread_rwlock_t mylock;
void *
run_loop (void *a)
{
while (!do_exit)
{
if (random () & 1)
{
xpthread_rwlock_wrlock (&mylock);
xpthread_rwlock_unlock (&mylock);
}
else
{
xpthread_rwlock_rdlock (&mylock);
xpthread_rwlock_unlock (&mylock);
}
}
return NULL;
}
int
do_test (void)
{
xpthread_rwlockattr_init (&mylock_attr);
xpthread_rwlockattr_setkind_np (&mylock_attr,
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
xpthread_rwlock_init (&mylock, &mylock_attr);
for (int n = 0; n < LOOPS; n++)
{
pthread_t tids[NTHREADS];
do_exit = 0;
for (int i = 0; i < NTHREADS; i++)
tids[i] = xpthread_create (NULL, run_loop, NULL);
/* Let the threads run for some time. */
sleep (1);
printf ("Exiting...");
fflush (stdout);
do_exit = 1;
for (int i = 0; i < NTHREADS; i++)
xpthread_join (tids[i]);
printf ("done.\n");
}
pthread_rwlock_destroy (&mylock);
pthread_rwlockattr_destroy (&mylock_attr);
return 0;
}
#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS)
#include <support/test-driver.c>
+355
View File
@@ -0,0 +1,355 @@
/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* For a full analysis see comment:
https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
Provided here for reference:
--- Analysis of pthread_rwlock_tryrdlock() stall ---
A read lock begins to execute.
In __pthread_rwlock_rdlock_full:
We can attempt a read lock, but find that the lock is
in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
is set), and the lock is held by a primary writer
(PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
wait for explicit hand over from the writer to us or
one of the other waiters. The read lock threads are
about to execute:
341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
342 (1 << PTHREAD_RWLOCK_READER_SHIFT))
343 + (1 << PTHREAD_RWLOCK_READER_SHIFT));
An unlock beings to execute.
Then in __pthread_rwlock_wrunlock:
547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
...
549 while (!atomic_compare_exchange_weak_release
550 (&rwlock->__data.__readers, &r,
551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
553 : PTHREAD_RWLOCK_WRPHASE))))
554 {
...
556 }
We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
Back in the read lock.
The read lock adjusts __readres as above.
383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
385 {
...
390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
391 r ^ PTHREAD_RWLOCK_WRPHASE))
392 {
And then attemps to start the read phase.
Assume there happens to be a tryrdlock at this point, noting
that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
is 1. So the try lock attemps to start the read phase.
In __pthread_rwlock_tryrdlock:
44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
45 {
...
49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
50 && (rwlock->__data.__flags
51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
52 return EBUSY;
53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
54 }
...
89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
90 &r, rnew));
And succeeds.
Back in the write unlock:
557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
558 {
...
563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
564 & PTHREAD_RWLOCK_FUTEX_USED) != 0)
565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
566 }
We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
and don't wake anyone. This is OK because we handed
over to the trylock. It will be the trylock's responsibility
to wake any waiters.
Back in the read lock:
The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
the __readers value was adjusted by the trylock, and so it falls through
to waiting on the lock for explicit handover from either a new writer
or a new reader.
448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
449 1 | PTHREAD_RWLOCK_FUTEX_USED,
450 abstime, private);
We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
is in use.
At this point we have readers waiting on the read lock
to unlock. The wrlock is done. The trylock is finishing
the installation of the read phase.
92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
93 {
...
105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
106 }
The trylock does note that we were the one that
installed the read phase, but the comments are not
correct, the execution ordering above shows that
readers might indeed be waiting, and they are.
The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
and the waiting reader is never worken becuase as noted
above it is conditional on the futex being used.
The solution is for the trylock thread to inspect
PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
--- Analysis of pthread_rwlock_trywrlock() stall ---
A write lock begins to execute, takes the write lock,
and then releases the lock...
In pthread_rwlock_wrunlock():
547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
...
549 while (!atomic_compare_exchange_weak_release
550 (&rwlock->__data.__readers, &r,
551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
553 : PTHREAD_RWLOCK_WRPHASE))))
554 {
...
556 }
... leaving it in the write phase with zero readers
(the case where we leave the write phase in place
during a write unlock).
A write trylock begins to execute.
In __pthread_rwlock_trywrlock:
40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
43 {
The lock is not locked.
There are no readers.
45 if (atomic_compare_exchange_weak_acquire (
46 &rwlock->__data.__readers, &r,
47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
We atomically install the write phase and we take the
exclusive write lock.
48 {
49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
We get this far.
A reader lock begins to execute.
In pthread_rwlock_rdlock:
437 for (;;)
438 {
439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
441 {
442 int private = __pthread_rwlock_get_private (rwlock);
443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
444 && (!atomic_compare_exchange_weak_relaxed
445 (&rwlock->__data.__wrphase_futex,
446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
447 continue;
448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
449 1 | PTHREAD_RWLOCK_FUTEX_USED,
450 abstime, private);
We are in a write phase, so the while() on line 439 is true.
The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
since this is the first reader to lock.
The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
on the expectation that this reader will be woken during
the handoff.
Back in pthread_rwlock_trywrlock:
50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
51 atomic_store_relaxed (&rwlock->__data.__cur_writer,
52 THREAD_GETMEM (THREAD_SELF, tid));
53 return 0;
54 }
...
57 }
We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
and so in the unlock we will not awaken the waiting reader.
The solution to this is to realize that if we did not start the write
phase we need not write 1 or any other value to __wrphase_futex.
This ensures that any readers (which saw __wrphase_futex != 0) can
set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
wake them.
If we installed the write phase then all other readers are looping
here:
In __pthread_rwlock_rdlock_full:
437 for (;;)
438 {
439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
441 {
...
508 }
waiting for the write phase to be installed or removed before they
can begin waiting on __wrphase_futex (part of the algorithm), or
taking a concurrent read lock, and thus we can safely write 1 to
__wrphase_futex.
If we did not install the write phase then the readers may already
be waiting on the futex, the original writer wrote 1 to __wrphase_futex
as part of starting the write phase, and we cannot also write 1
without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
---
Summary for the pthread_rwlock_tryrdlock() stall:
The stall is caused by pthread_rwlock_tryrdlock failing to check
that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
and then waking the futex.
The fix for bug 23844 ensures that waiters on __wrphase_futex are
correctly woken. Before the fix the test stalls as readers can
wait forever on __wrphase_futex. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <support/xthread.h>
#include <errno.h>
/* We need only one lock to reproduce the issue. We will need multiple
threads to get the exact case where we have a read, try, and unlock
all interleaving to produce the case where the readers are waiting
and the try fails to wake them. */
pthread_rwlock_t onelock;
/* The number of threads is arbitrary but empirically chosen to have
enough threads that we see the condition where waiting readers are
not woken by a successful tryrdlock. */
#define NTHREADS 32
_Atomic int do_exit;
void *
run_loop (void *arg)
{
int i = 0, ret;
while (!do_exit)
{
/* Arbitrarily choose if we are the writer or reader. Choose a
high enough ratio of readers to writers to make it likely
that readers block (and eventually are susceptable to
stalling).
If we are a writer, take the write lock, and then unlock.
If we are a reader, try the lock, then lock, then unlock. */
if ((i % 8) != 0)
xpthread_rwlock_wrlock (&onelock);
else
{
if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
{
if (ret == EBUSY)
xpthread_rwlock_rdlock (&onelock);
else
exit (EXIT_FAILURE);
}
}
/* Thread does some work and then unlocks. */
xpthread_rwlock_unlock (&onelock);
i++;
}
return NULL;
}
int
do_test (void)
{
int i;
pthread_t tids[NTHREADS];
xpthread_rwlock_init (&onelock, NULL);
for (i = 0; i < NTHREADS; i++)
tids[i] = xpthread_create (NULL, run_loop, NULL);
/* Run for some amount of time. Empirically speaking exercising
the stall via pthread_rwlock_tryrdlock is much harder, and on
a 3.5GHz 4 core x86_64 VM system it takes somewhere around
20-200s to stall, approaching 100% stall past 200s. We can't
wait that long for a regression test so we just test for 20s,
and expect the stall to happen with a 5-10% chance (enough for
developers to see). */
sleep (20);
/* Then exit. */
printf ("INFO: Exiting...\n");
do_exit = 1;
/* If any readers stalled then we will timeout waiting for them. */
for (i = 0; i < NTHREADS; i++)
xpthread_join (tids[i]);
printf ("INFO: Done.\n");
xpthread_rwlock_destroy (&onelock);
printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
return 0;
}
#define TIMEOUT 30
#include <support/test-driver.c>
+108
View File
@@ -0,0 +1,108 @@
/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
Summary for the pthread_rwlock_trywrlock() stall:
The stall is caused by pthread_rwlock_trywrlock setting
__wrphase_futex futex to 1 and loosing the
PTHREAD_RWLOCK_FUTEX_USED bit.
The fix for bug 23844 ensures that waiters on __wrphase_futex are
correctly woken. Before the fix the test stalls as readers can
wait forever on __wrphase_futex. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <support/xthread.h>
#include <errno.h>
/* We need only one lock to reproduce the issue. We will need multiple
threads to get the exact case where we have a read, try, and unlock
all interleaving to produce the case where the readers are waiting
and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
subsequent unlock fails to wake them. */
pthread_rwlock_t onelock;
/* The number of threads is arbitrary but empirically chosen to have
enough threads that we see the condition where waiting readers are
not woken by a successful unlock. */
#define NTHREADS 32
_Atomic int do_exit;
void *
run_loop (void *arg)
{
int i = 0, ret;
while (!do_exit)
{
/* Arbitrarily choose if we are the writer or reader. Choose a
high enough ratio of readers to writers to make it likely
that readers block (and eventually are susceptable to
stalling).
If we are a writer, take the write lock, and then unlock.
If we are a reader, try the lock, then lock, then unlock. */
if ((i % 8) != 0)
{
if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
{
if (ret == EBUSY)
xpthread_rwlock_wrlock (&onelock);
else
exit (EXIT_FAILURE);
}
}
else
xpthread_rwlock_rdlock (&onelock);
/* Thread does some work and then unlocks. */
xpthread_rwlock_unlock (&onelock);
i++;
}
return NULL;
}
int
do_test (void)
{
int i;
pthread_t tids[NTHREADS];
xpthread_rwlock_init (&onelock, NULL);
for (i = 0; i < NTHREADS; i++)
tids[i] = xpthread_create (NULL, run_loop, NULL);
/* Run for some amount of time. The pthread_rwlock_tryrwlock stall
is very easy to trigger and happens in seconds under the test
conditions. */
sleep (10);
/* Then exit. */
printf ("INFO: Exiting...\n");
do_exit = 1;
/* If any readers stalled then we will timeout waiting for them. */
for (i = 0; i < NTHREADS; i++)
xpthread_join (tids[i]);
printf ("INFO: Done.\n");
xpthread_rwlock_destroy (&onelock);
printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
return 0;
}
#include <support/test-driver.c>
+49 -41
View File
@@ -19,12 +19,16 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <support/support.h>
#include <support/check.h>
#include <support/xthread.h>
struct test_s
{
int a;
int b;
__attribute__ ((aligned(0x20))) int a;
__attribute__ ((aligned(0x200))) int b;
};
#define INIT_A 1
@@ -36,15 +40,34 @@ __thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
.b = INIT_B
};
/* Use noinline in combination with not static to ensure that the
alignment check is really done. Otherwise it was optimized out! */
__attribute__ ((noinline)) void
check_alignment (const char *thr_name, const char *ptr_name,
int *ptr, int alignment)
{
uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1);
if (offset_aligment)
{
FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n",
ptr_name, ptr, alignment, thr_name);
}
}
static void
check_s (const char *thr_name)
{
if (s.a != INIT_A || s.b != INIT_B)
FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name);
check_alignment (thr_name, "s.a", &s.a, 0x20);
check_alignment (thr_name, "s.b", &s.b, 0x200);
}
static void *
tf (void *arg)
{
if (s.a != INIT_A || s.b != INIT_B)
{
puts ("initial value of s in child thread wrong");
exit (1);
}
check_s ("child");
++s.a;
@@ -55,25 +78,14 @@ tf (void *arg)
int
do_test (void)
{
if (s.a != INIT_A || s.b != INIT_B)
{
puts ("initial value of s in main thread wrong");
exit (1);
}
check_s ("main");
pthread_attr_t a;
if (pthread_attr_init (&a) != 0)
{
puts ("attr_init failed");
exit (1);
}
xpthread_attr_init (&a);
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
#define STACK_SIZE (1 * 1024 * 1024)
xpthread_attr_setstacksize (&a, STACK_SIZE);
#define N 10
int i;
@@ -83,29 +95,25 @@ do_test (void)
pthread_t th[M];
int j;
for (j = 0; j < M; ++j, ++s.a)
if (pthread_create (&th[j], &a, tf, NULL) != 0)
{
puts ("pthread_create failed");
exit (1);
}
th[j] = xpthread_create (&a, tf, NULL);
for (j = 0; j < M; ++j)
if (pthread_join (th[j], NULL) != 0)
{
puts ("pthread_join failed");
exit (1);
}
xpthread_join (th[j]);
}
if (pthread_attr_destroy (&a) != 0)
{
puts ("attr_destroy failed");
exit (1);
}
/* Also check the alignment of the tls variables if a misaligned stack is
specified. */
pthread_t th;
void *thr_stack = NULL;
thr_stack = xposix_memalign (0x200, STACK_SIZE + 1);
xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE);
th = xpthread_create (&a, tf, NULL);
xpthread_join (th);
free (thr_stack);
xpthread_attr_destroy (&a);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
#include <support/test-driver.c>

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