Compare commits

...
Author SHA1 Message Date
Raoni Fassina Firmino 0d6fdf9f05 Merge branch release/2.30/master into ibm/2.30/master 2022-02-25 10:57:31 -03:00
Raoni Fassina Firmino 6bbd88c251 Merge branch release/2.30/master into ibm/2.30/master 2022-02-25 10:56:29 -03:00
Raoni Fassina Firmino 821f0a9cb2 Merge branch release/2.30/master into ibm/2.30/master 2022-02-25 10:45:14 -03:00
H.J. Lu a79bc55e5b NEWS: Add a bug fix entry for BZ #28896 2022-02-18 19:13:02 -08:00
Noah Goldstein 31615a5f47 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 18:17:09 -08:00
Noah Goldstein 6428a662cc 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 18:17:04 -08:00
Noah GoldsteinandH.J. Lu a3ef8a0c3d 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 18:16:58 -08:00
H.J. Lu 70522b1c1d 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:40:37 -08:00
H.J. Lu 8ad5519ae1 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 12:25:00 -08:00
Noah Goldstein 23bc964c62 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 12:24:53 -08:00
H.J. Lu 76e30dd44e 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 07:28:00 -08:00
H.J. Lu 071e2bdd85 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 07:27:53 -08:00
H.J. Lu 25ed98a882 NEWS: Add a bug fix entry for BZ #27974 2022-01-27 16:02:09 -08:00
Noah Goldstein a3dd272e9c 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:01:04 -08:00
Noah Goldstein ae86a6bd48 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:00:59 -08:00
Noah Goldstein a0ce680598 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:00:54 -08:00
Noah Goldstein 178292fe01 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:00:48 -08:00
H.J. Lu 921b3e7ae3 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:00:38 -08:00
Alice Xu 6b4f9a4acc 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 15:57:15 -08:00
Noah Goldstein 81d2a205a9 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 15:57:08 -08:00
Noah Goldstein d5904daf76 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 15:57:03 -08:00
Noah Goldstein d436d8b7ad 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 15:56:57 -08:00
Noah Goldstein 1ad51a1840 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 15:56:52 -08:00
H.J. Lu 84619864c6 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 15:56:47 -08:00
H.J. Lu ad65f574aa 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 15:56:42 -08:00
H.J. Lu 87a18fc33a x86-64: Require BMI2 for __strlen_evex and __strnlen_evex
Since __strlen_evex and __strnlen_evex added by

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

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

use sarx:

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

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

(cherry picked from commit 55bf411b45)
2022-01-27 15:56:36 -08:00
H.J. Lu de28bb3c61 NEWS: Add a bug fix entry for BZ #27457 2022-01-27 12:24:44 -08:00
Sunil K Pandey fa93ff0640 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 11:44:17 -08:00
H.J. Lu bab2034153 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 11:44:17 -08:00
H.J. Lu 12e572c150 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 11:44:17 -08:00
H.J. Lu e1d6be36f5 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 11:44:17 -08:00
H.J. Lu 51bf3df138 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 11:44:17 -08:00
H.J. Lu 3d00e826aa 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 11:44:17 -08:00
H.J. Lu 373f43fd0c 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 11:44:17 -08:00
H.J. Lu 8ebaa0fb1e 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 11:44:17 -08:00
H.J. Lu d14cc230f6 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 11:44:17 -08:00
H.J. Lu 375515bdf7 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 11:44:17 -08:00
H.J. Lu 293a787c88 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 11:44:17 -08:00
H.J. Lu 9d868841f8 NEWS: Add a bug fix entry for BZ #28755 2022-01-27 05:31:02 -08:00
Noah Goldstein 6746407ed0 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 05:30:07 -08:00
Siddhesh Poyarekar 7341e72bc2 Fix SXID_ERASE behavior in setuid programs (BZ #27471)
When parse_tunables tries to erase a tunable marked as SXID_ERASE for
setuid programs, it ends up setting the envvar string iterator
incorrectly, because of which it may parse the next tunable
incorrectly.  Given that currently the implementation allows malformed
and unrecognized tunables pass through, it may even allow SXID_ERASE
tunables to go through.

This change revamps the SXID_ERASE implementation so that:

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

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

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

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

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

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

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

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

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

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

(cherry picked from commit 95c68080a3)
2021-04-14 10:57:36 +05:30
Siddhesh Poyarekar 447660cee5 support: Pass environ to child process
Pass environ to posix_spawn so that the child process can inherit
environment of the test.

(cherry picked from commit e958490f8c)
2021-04-14 10:57:36 +05:30
Stefan Liebler 2e776d7b31 S390: Also check vector support in memmove ifunc-selector [BZ #27511]
The arch13 memmove variant is currently selected by the ifunc selector
if the Miscellaneous-Instruction-Extensions Facility 3 facility bit
is present, but the function is also using vector instructions.
If the vector support is not present, one is receiving an operation
exception.

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

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

(cherry picked from commit 7759be2593)
2021-03-26 11:02:33 +01:00
Florian Weimer 889122cbfa NEWS: Fix typo in CVE-2021-3326 entry 2021-03-18 18:08:42 -03:00
Florian Weimer fa4162af6f NEWS: Mention CVE-2021-3326 (iconv assertion with ISO-20220-JP-3) 2021-03-18 18:08:20 -03:00
Raphael Moreira Zinsly 903f0b6942 Merge branch release/2.30/master into ibm/2.30/master 2021-03-18 18:05:13 -03:00
Siddhesh Poyarekar 3e33d93073 Add NEWS entry for CVE-2020-29562 (BZ #26923)
BZ #26923 now has a CVE entry, so add a NEWS entry for it.
2021-03-18 18:04:13 -03:00
Michael Colavita 3d8ef60802 iconv: Fix incorrect UCS4 inner loop bounds (BZ#26923)
Previously, in UCS4 conversion routines we limit the number of
characters we examine to the minimum of the number of characters in the
input and the number of characters in the output. This is not the
correct behavior when __GCONV_IGNORE_ERRORS is set, as we do not consume
an output character when we skip a code unit. Instead, track the input
and output pointers and terminate the loop when either reaches its
limit.

This resolves assertion failures when resetting the input buffer in a step of
iconv, which assumes that the input will be fully consumed given sufficient
output space.
2021-03-18 18:02:05 -03:00
Arjun Shankar 67b1fb515c iconv: Accept redundant shift sequences in IBM1364 [BZ #26224]
The IBM1364, IBM1371, IBM1388, IBM1390 and IBM1399 character sets
share converter logic (iconvdata/ibm1364.c) which would reject
redundant shift sequences when processing input in these character
sets.  This led to a hang in the iconv program (CVE-2020-27618).

This commit adjusts the converter to ignore redundant shift sequences
and adds test cases for iconv_prog hangs that would be triggered upon
their rejection.  This brings the implementation in line with other
converters that also ignore redundant shift sequences (e.g. IBM930
etc., fixed in commit 692de4b396).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2021-03-18 18:00:29 -03:00
DJ Delorie 1bf07898c9 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:41:39 +05:30
Florian Weimer 79bf3c9774 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 14:39:48 +01:00
H.J. Lu d811d240c0 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 14:27:36 -08:00
H.J. Lu 8113182a97 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 08:36:36 -08:00
H.J. Lu 369b47aaf7 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 06:09:23 -08:00
Tulio Magno Quites Machado Filho 13e5c43287 Merge branch release/2.30/master into ibm/2.30/master 2020-11-30 10:37:36 -03:00
Szabolcs Nagy 61e8ae9b66 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:23:43 +00:00
Wilco Dijkstra 24c0d68815 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 14:30:01 +01:00
Wilco Dijkstra 80259cd098 [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-12 17:10:25 +01:00
Krzysztof Koch 704e18d66d 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-12 17:10:15 +01:00
Wilco Dijkstra ad34abcad5 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-12 16:55:41 +01:00
Wilco Dijkstra 236287f869 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-12 16:55:30 +01:00
Wilco Dijkstra ade1fa24e3 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-12 16:55:09 +01:00
Wilco Dijkstra afc53d52dc 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-12 16:52:41 +01:00
Alexander Anisimov d59630f995 arm: CVE-2020-6096: Fix multiarch memcpy for negative length [BZ #25620]
Unsigned branch instructions could be used for r2 to fix the wrong
behavior when a negative length is passed to memcpy.
This commit fixes the armv7 version.

(cherry picked from commit beea361050)
2020-07-15 15:08:59 -04:00
Evgeny Eremin 501f426fe0 arm: CVE-2020-6096: fix memcpy and memmove for negative length [BZ #25620]
Unsigned branch instructions could be used for r2 to fix the wrong
behavior when a negative length is passed to memcpy and memmove.
This commit fixes the generic arm implementation of memcpy amd memmove.

(cherry picked from commit 79a4fa341b)
2020-07-15 15:08:07 -04:00
H.J. Lu 94abcef26e NEWS: Mention BZ 25933 fix 2020-07-04 09:51:12 -07:00
Sunil K Pandey 520aaef712 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 09:42:04 -07:00
Florian Weimer 1ba9ebfce3 nss_compat: internal_end*ent may clobber errno, hiding ERANGE [BZ #25976]
During cleanup, before returning from get*_r functions, the end*ent
calls must not change errno.  Otherwise, an ERANGE error from the
underlying implementation can be hidden, causing unexpected lookup
failures.  This commit introduces an internal_end*ent_noerror
function which saves and restore errno, and marks the original
internal_end*ent function as warn_unused_result, so that it is used
only in contexts were errors from it can be handled explicitly.

Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 790b8dda44)
2020-05-19 16:31:31 +02:00
Florian Weimer dd591f8469 NEWS: Merge two bug lists in the glibc 2.30.1 section 2020-05-19 16:31:08 +02:00
H.J. Lu 4748829f86 NEWS: Mention fixes for BZ 25810/25896/25902/25966 2020-05-09 12:48:08 -07:00
H.J. Lu 6ffe972db7 x86-64: Use RDX_LP on __x86_shared_non_temporal_threshold [BZ #25966]
Since __x86_shared_non_temporal_threshold is defined as

long int __x86_shared_non_temporal_threshold;

and long int is 4 bytes for x32, use RDX_LP to compare against
__x86_shared_non_temporal_threshold in assembly code.

(cherry picked from commit 55c7bcc71b)
2020-05-09 12:45:19 -07:00
Matheus Castanho 2900267d78 Merge branch release/2.30/master into ibm/2.30/master 2020-05-08 09:28:14 -03:00
H.J. Lu c8e3101337 Add a C wrapper for prctl [BZ #25896]
Add a C wrapper to pass arguments in

/* Control process execution.  */
extern int prctl (int __option, ...) __THROW;

to prctl syscall:

extern int prctl (int, unsigned long int, unsigned long int,
		  unsigned long int, unsigned long int);

(cherry picked from commit ff026950e2)
2020-05-07 05:12:27 -07:00
H.J. Lu 8e94ffe0f8 powerpc: Rename argN to _argN in LOADARGS_N [BZ #25902]
LOADARGS_N in powerpc/sysdep.h uses argN as local variables.  It breaks
when argN is also a function argument.  Rename argN to _argN to avoid
conflict.

(cherry picked from commit 14f43dd34d)
2020-05-07 05:12:27 -07:00
H.J. Lu bc33a4d53c Add C wrappers for process_vm_readv/process_vm_writev [BZ #25810]
Since the the U marker can only be applied to 2 unsigned long arguments
in syscalls.list files, add a C wrapper for process_vm_readv and
process_vm_writev syscals which have more than 2 unsigned long arguments.

(cherry picked from commit ad9fd65d71)
2020-05-07 05:12:27 -07:00
H.J. Lu a604ee4a54 Mark unsigned long arguments with U in more syscalls [BZ #25810]
Mark unsigned long arguments in mmap, read, recv, recvfrom, send, sendto,
write, ioperm, sendfile64, setxattr, lsetxattr, fsetxattr, getxattr,
lgetxattr, fgetxattr, listxattr, llistxattr and flistxattr with U in
syscalls.list files.

(cherry picked from commit 86f4f2263b)
2020-05-07 05:12:27 -07:00
H.J. Lu 618a86e09e Add a syscall test for [BZ #25810]
Add a test to pass 64-bit long arguments to syscall with undefined upper
32 bits on x32.

Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py.

(cherry picked from commit 781dacc4f4)
2020-05-07 05:12:27 -07:00
H.J. Lu 6bd82f5fd0 Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810]
X32 has 32-bit long and pointer with 64-bit off_t.  Since x32 psABI
requires that pointers passed in registers must be zero-extended to
64bit, x32 can share many syscall interfaces with LP64.  When a LP64
syscall with long and unsigned long int arguments is used for x32, these
arguments must be properly extended to 64-bit.  Otherwise if the upper
32 bits of the register have undefined value, such a syscall will be
rejected by kernel.

For syscalls implemented in assembly codes, 'U' is added to syscall
signature key letters for unsigned long, which is zero-extended to
64-bit types.  SYSCALL_ULONG_ARG_1 and SYSCALL_ULONG_ARG_2 are passed
to syscall-template.S for the first and the second unsigned long int
arguments if PSEUDOS_HAVE_ULONG_INDICES is defined.  They are used by
x32 to zero-extend 32-bit arguments to 64 bits.

Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py.

(cherry picked from commit 2ad5d0845d)
2020-05-07 05:12:27 -07:00
H.J. Lu 7378e9c520 x32: Properly pass long to syscall [BZ #25810]
X32 has 32-bit long and pointer with 64-bit off_t.  Since x32 psABI
requires that pointers passed in registers must be zero-extended to
64bit, x32 can share many syscall interfaces with LP64.  When a LP64
syscall with long and unsigned long arguments is used for x32, these
arguments must be properly extended to 64-bit.  Otherwise if the upper
32 bits of the register have undefined value, such a syscall will be
rejected by kernel.

Enforce zero-extension for pointers and array system call arguments.
For integer types, extend to int64_t (the full register) using a
regular cast, resulting in zero or sign extension based on the
signedness of the original type.

For

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);

we now generate

   0:	41 f7 c1 ff 0f 00 00 	test   $0xfff,%r9d
   7:	75 1f                	jne    28 <__mmap64+0x28>
   9:	48 63 d2             	movslq %edx,%rdx
   c:	89 f6                	mov    %esi,%esi
   e:	4d 63 c0             	movslq %r8d,%r8
  11:	4c 63 d1             	movslq %ecx,%r10
  14:	b8 09 00 00 40       	mov    $0x40000009,%eax
  19:	0f 05                	syscall

That is

1. addr is unchanged.
2. length is zero-extend to 64 bits.
3. prot is sign-extend to 64 bits.
4. flags is sign-extend to 64 bits.
5. fd is sign-extend to 64 bits.
6. offset is unchanged.

For int arguments, since kernel uses only the lower 32 bits and ignores
the upper 32 bits in 64-bit registers, these work correctly.

Tested on x86-64 and x32.  There are no code changes on x86-64.

(cherry picked from commit df76ff3a44)
2020-05-07 05:12:27 -07:00
John David Anglin 1c05b8f551 Add new file missed in previous hppa commit.
(cherry picked from commit acdcca7294)
2020-05-04 22:00:52 +02:00
John David Anglin 6f4527a7dd Fix data race in setting function descriptors during lazy binding on hppa.
This addresses an issue that is present mainly on SMP machines running
threaded code.  In a typical indirect call or PLT import stub, the
target address is loaded first.  Then the global pointer is loaded into
the PIC register in the delay slot of a branch to the target address.
During lazy binding, the target address is a trampoline which transfers
to _dl_runtime_resolve().

_dl_runtime_resolve() uses the relocation offset stored in the global
pointer and the linkage map stored in the trampoline to find the
relocation.  Then, the function descriptor is updated.

In a multi-threaded application, it is possible for the global pointer
to be updated between the load of the target address and the global
pointer.  When this happens, the relocation offset has been replaced
by the new global pointer.  The function pointer has probably been
updated as well but there is no way to find the address of the function
descriptor and to transfer to the target.  So, _dl_runtime_resolve()
typically crashes.

HP-UX addressed this problem by adding an extra pc-relative branch to
the trampoline.  The descriptor is initially setup to point to the
branch.  The branch then transfers to the trampoline.  This allowed
the trampoline code to figure out which descriptor was being used
without any modification to user code.  I didn't use this approach
as it is more complex and changes function pointer canonicalization.

The order of loading the target address and global pointer in
indirect calls was not consistent with the order used in import stubs.
In particular, $$dyncall and some inline versions of it loaded the
global pointer first.  This was inconsistent with the global pointer
being updated first in dl-machine.h.  Assuming the accesses are
ordered, we want elf_machine_fixup_plt() to store the global pointer
first and calls to load it last.  Then, the global pointer will be
correct when the target function is entered.

However, just to make things more fun, HP added support for
out-of-order execution of accesses in PA 2.0.  The accesses used by
calls are weakly ordered. So, it's possibly under some circumstances
that a function might be entered with the wrong global pointer.
However, HP uses weakly ordered accesses in 64-bit HP-UX, so I assume
that loading the global pointer in the delay slot of the branch must
work consistently.

The basic fix for the race is a combination of modifying user code to
preserve the address of the function descriptor in register %r22 and
setting the least-significant bit in the relocation offset.  The
latter was suggested by Carlos as a way to distinguish relocation
offsets from global pointer values.  Conventionally, %r22 is used
as the address of the function descriptor in calls to $$dyncall.
So, it wasn't hard to preserve the address in %r22.

I have updated gcc trunk and gcc-9 branch to not clobber %r22 in
$$dyncall and inline indirect calls.  I have also modified the import
stubs in binutils trunk and the 2.33 branch to preserve %r22.  This
required making the stubs one instruction longer but we save one
relocation.  I also modified binutils to align the .plt section on
a 8-byte boundary.  This allows descriptors to be updated atomically
with a floting-point store.

With these changes, _dl_runtime_resolve() can fallback to an alternate
mechanism to find the relocation offset when it has been clobbered.
There's just one additional instruction in the fast path. I tested
the fallback function, _dl_fix_reloc_arg(), by changing the branch to
always use the fallback.  Old code still runs as it did before.

Fixes bug 23296.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 1a044511a3)
2020-05-04 22:00:52 +02:00
Adhemerval Zanella c56022269f stdlib: Move tst-system to tests-container
Fix some issues with different shell and error messages.

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

(cherry picked from commit 4eda036f5b)
2020-03-25 10:00:39 -03:00
Adhemerval Zanella 42766b3db2 support/shell-container.c: Add builtin kill
No options supported.

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

(cherry picked from commit 1c17100c43)
2020-03-25 10:00:27 -03:00
Adhemerval Zanella 946ee0281a support/shell-container.c: Add builtin exit
Reviewed-by: DJ Delorie <dj@redhat.com>

(cherry picked from commit 5a5a3a3234)
2020-03-25 10:00:15 -03:00
Adhemerval Zanella 55e77b7d81 support/shell-container.c: Return 127 if execve fails
Reviewed-by: DJ Delorie <dj@redhat.com>

(cherry picked from commit 5fce0e095b)
2020-03-25 09:59:50 -03:00
Aurelien Jarno 6b19792c9c Add NEWS entry for CVE-2020-1751 (bug 25423)
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 07d16a6deb)
2020-03-24 23:19:25 +01:00
Adhemerval Zanella 9cd7745689 posix: Fix system error return value [BZ #25715]
It fixes 5fb7fc9635 when posix_spawn fails.

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

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

(cherry picked from commit f09542c584)
2020-03-24 08:48:58 -03:00
Adhemerval Zanella b3778c01b7 sparc: Move sigreturn stub to assembly
It seems that some gcc versions might generates a stack frame for the
sigreturn stub requires on sparc signal handling.  For instance:

  $ cat test.c
  #define _GNU_SOURCE
  #include <sys/syscall.h>

  __attribute__ ((__optimize__ ("-fno-stack-protector")))
  void
  __sigreturn_stub (void)
  {
    __asm__ ("mov %0, %%g1\n\t"
            "ta  0x10\n\t"
            : /* no outputs */
            : "i" (SYS_rt_sigreturn));
  }
  $ gcc -v
  [...]
  gcc version 9.2.1 20200224 (Debian 9.2.1-30)
  $ gcc -O2 -m64 test.c -S -o -
  [...]
    __sigreturn_stub:
          save    %sp, -176, %sp
  #APP
  ! 9 "t.c" 1
          mov 101, %g1
          ta  0x10

  ! 0 "" 2
  #NO_APP
          .size   __sigreturn_stub, .-__sigreturn_stub

As indicated by kernel developers [1], the sigreturn stub can not change
the register window or the stack pointer since the kernel has setup the
restore frame at a precise location relative to the stack pointer when
the stub is invoked.

I tried to play with some compiler flags and even with _Noreturn and
__builtin_unreachable after the asm does not help (and Sparc does not
support naked functions).

To avoid similar issues, as the stack-protector support also have
stumbled, this patch moves the implementation of the sigreturn stubs to
assembly.

Checked on sparcv9-linux-gnu and sparc64-linux-gnu with gcc 9.2.1
and gcc 7.5.0.

[1] https://lkml.org/lkml/2016/5/27/465

(cherry picked from commit b33e946fbb)
2020-03-24 08:48:45 -03:00
Adhemerval Zanella 4f0ae74135 arm: Fix softp-fp Implies (BZ #25635)
The commit "arm: Split BE/LE abilist"
(1673ba87fe) changed the soft-fp order for
ARM selection when __SOFTFP__ is defined by the compiler.

On 2.30 the sysdeps order is:

2.30
sysdeps/unix/sysv/linux/arm
sysdeps/arm/nptl
sysdeps/unix/sysv/linux
sysdeps/nptl
sysdeps/pthread
sysdeps/gnu
sysdeps/unix/inet
sysdeps/unix/sysv
sysdeps/unix/arm
sysdeps/unix
sysdeps/posix
sysdeps/arm/nofpu
sysdeps/ieee754/soft-fp
sysdeps/arm
sysdeps/wordsize-32
sysdeps/ieee754/flt-32
sysdeps/ieee754/dbl-64
sysdeps/ieee754
sysdeps/generic

While on master is:

sysdeps/unix/sysv/linux/arm/le
sysdeps/unix/sysv/linux/arm
sysdeps/arm/nptl
sysdeps/unix/sysv/linux
sysdeps/nptl
sysdeps/pthread
sysdeps/gnu
sysdeps/unix/inet
sysdeps/unix/sysv
sysdeps/unix/arm
sysdeps/unix
sysdeps/posix
sysdeps/arm/le
sysdeps/arm
sysdeps/wordsize-32
sysdeps/ieee754/flt-32
sysdeps/ieee754/dbl-64
sysdeps/arm/nofpu
sysdeps/ieee754/soft-fp
sysdeps/ieee754
sysdeps/generic

It make the build select some routines (fadd, fdiv, fmul, fsub, and fma)
on ieee754/flt-32 and ieee754/dbl-64 that requires fenv support to be
correctly rounded which in turns lead to math failures since the
__SOFTFP__ does not have fenv support.

With this patch the order is now:

sysdeps/unix/sysv/linux/arm/le
sysdeps/unix/sysv/linux/arm
sysdeps/arm/nptl
sysdeps/unix/sysv/linux
sysdeps/nptlsysdeps/pthread
sysdeps/gnu
sysdeps/unix/inet
sysdeps/unix/sysv
sysdeps/unix/arm
sysdeps/unix
sysdeps/posix
sysdeps/arm/le/nofpu
sysdeps/arm/nofpu
sysdeps/ieee754/soft-fp
sysdeps/arm/le
sysdeps/arm
sysdeps/wordsize-32
sysdeps/ieee754/flt-32
sysdeps/ieee754/dbl-64
sysdeps/ieee754
sysdeps/generic

Checked on arm-linux-gnuaebi.

(cherry picked from commit af09e5e5d9)
2020-03-24 08:48:43 -03:00
Adhemerval Zanella 1ce16683d9 i386: Use comdat instead of .gnu.linkonce for i386 setup pic register (BZ #20543)
GCC has moved from using .gnu.linkonce for i386 setup pic register with
minimum current version (as for binutils minimum binutils that support
comdat).

Trying to pinpoint when binutils has added comdat support for i686, it
seems it was around 2004 [1].  I also checking with some ancient
binutils older than 2.16 I see:

test.o: In function `__x86.get_pc_thunk.bx':
test.o(.text.__x86.get_pc_thunk.bx+0x0): multiple definition of `__x86.get_pc_thunk.bx'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/crti.o(.gnu.linkonce.t.__x86.get_pc_thunk.bx+0x0): first defined here

Which seems that such version can not handle either comdat at all or
a mix of linkonce and comdat.  For binutils 2.16.1 I am getting a
different issue trying to link a binary with and more recent
ctri.o (unrecognized relocation (0x2b) in section `.init', which is
R_386_GOT32X and old binutils won't generate it anyway).

So I think that either unlikely someone will use an older binutils than
the one used to glibc and even this scenario may fail with some issue
as the R_386_GOT32X.  Also, 2.16.1 is quite old and not really supported
(glibc itself required 2.25).

Checked on i686-linux-gnu.

[1] https://gcc.gnu.org/ml/gcc/2004-05/msg00030.html

(cherry picked from commit 35200fd3892f6caf867bf89bc8048e553906af28)
2020-03-24 08:46:59 -03:00
Aurelien Jarno 6b11f60c70 Add NEWS entry for CVE-2020-1752 (bug 25414)
(cherry picked from commit 39a05214fe)
2020-03-19 23:12:42 +01:00
Andreas Schwab fb266e65cc 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-18 10:26:13 -04:00
Andreas Schwab da97c6b88e 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-17 20:31:16 -04:00
Aurelien Jarno dd34bce38c Add NEWS entry for CVE-2020-10029 (bug 25487)
(cherry picked from commit 15ab195229)
2020-03-11 13:01:29 +01:00
Florian Weimer 949fbe7826 math/test-sinl-pseudo: Use stack protector only if available
This fixes commit 9333498794 ("Avoid ldbl-96 stack
corruption from range reduction of pseudo-zero (bug 25487).").

(cherry picked from commit c10acd4026)
2020-03-11 12:59:42 +01:00
Joseph Myers 57700813eb Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487).
Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero
argument (an representation where all the significand bits, including
the explicit high bit, are zero, but the exponent is not zero, which
is not a valid representation for the long double type).

Although this is not a valid long double representation, existing
practice in this area (see bug 4586, originally marked invalid but
subsequently fixed) is that we still seek to avoid invalid memory
accesses as a result, in case of programs that treat arbitrary binary
data as long double representations, although the invalid
representations of the ldbl-96 format do not need to be consistently
handled the same as any particular valid representation.

This patch makes the range reduction detect pseudo-zero and unnormal
representations that would otherwise go to __kernel_rem_pio2, and
returns a NaN for them instead of continuing with the range reduction
process.  (Pseudo-zero and unnormal representations whose unbiased
exponent is less than -1 have already been safely returned from the
function before this point without going through the rest of range
reduction.)  Pseudo-zero representations would previously result in
the value passed to __kernel_rem_pio2 being all-zero, which is
definitely unsafe; unnormal representations would previously result in
a value passed whose high bit is zero, which might well be unsafe
since that is not a form of input expected by __kernel_rem_pio2.

Tested for x86_64.

(cherry picked from commit 9333498794)
2020-03-11 12:59:12 +01:00
Fangrui Song 75fa5fd7c3 Improve IFUNC check [BZ #25506]
GNU ld's RISCV port does not support IFUNC. ld -no-pie produces no
relocation and the test passed incorrectly. Be more rigid by testing
IRELATIVE explicitly.

Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 87a698a216)
2020-03-08 14:07:19 +01:00
Adhemerval Zanella d53f5cac50 malloc/tst-mallocfork2: Kill lingering process for unexpected failures
If the test fails due some unexpected failure after the children
creation, either in the signal handler by calling abort or in the main
loop; the created children might not be killed properly.

This patches fixes it by:

  * Avoid aborting in the signal handler by setting a flag that
    an error has occured and add a check in the main loop.

  * Add a atexit handler to handle kill child processes.

Checked on x86_64-linux-gnu.
2020-02-27 17:27:19 -03:00
Adhemerval Zanella 74d9b0811e riscv: Avoid clobbering register parameters in syscall
The riscv INTERNAL_SYSCALL macro might clobber the register
parameter if the argument itself might clobber any register (a function
call for instance).

This patch fixes it by using temporary variables for the expressions
between the register assignments (as indicated by GCC documentation,
6.47.5.2 Specifying Registers for Local Variables).

It is similar to the fix done for MIPS (bug 25523).

Checked with riscv64-linux-gnu-rv64imafdc-lp64d build.

(cherry picked from commit be74b42ee2)
2020-02-16 15:16:50 +01:00
Adhemerval Zanella e1766196b6 microblaze: Avoid clobbering register parameters in syscall
The microblaze INTERNAL_SYSCALL macro might clobber the register
parameter if the argument itself might clobber any register (a function
call for instance).

This patch fixes it by using temporary variables for the expressions
between the register assignments (as indicated by GCC documentation,
6.47.5.2 Specifying Registers for Local Variables).

It is similar to the fix done for MIPS (bug 25523).

Checked with microblaze-linux-gnu and microblazeel-linux-gnu build.

(cherry picked from commit 6cc8fc7c15)
2020-02-16 15:16:10 +01:00
WANG Xuerui b3be12767c mips: Fix argument passing for inlined syscalls on Linux [BZ #25523]
According to [gcc documentation][1], temporary variables must be used for
the desired content to not be call-clobbered.

Fix the Linux inline syscall templates by adding temporary variables,
much like what x86 did before
(commit 381a0c26d7).

Tested with gcc 9.2.0, both cross-compiled and natively on Loongson
3A4000.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html

(cherry picked from commit 4fbba6fe90)
2020-02-16 11:44:25 +01:00
WANG Xuerui 761c0e6086 mips: Use 'long int' and 'long long int' in linux syscall code
Style fixes only, no functional change.

(cherry picked from commit d3fbb18aa3)
2020-02-16 11:40:39 +01:00
John David Anglin 43598ef6e2 hppa: Align __clone stack argument to 8 bytes (Bug 25066)
The hppa architecture requires strict alignment for loads and stores.
As a result, the minimum stack alignment that will work is 8 bytes.
This patch adjusts __clone() to align the stack argument passed to it.
It also adjusts slightly some formatting.

This fixes the nptl/tst-tls1 test.

(cherry picked from commit e4c23a029a)
2020-02-05 22:13:40 +01:00
Tulio Magno Quites Machado Filho 60c67613ea Merge branch release/2.30/master into ibm/2.30/master 2020-01-17 17:27:49 -03:00
Florian Weimer 994e529a37 Remove incorrect alloc_size attribute from pvalloc [BZ #25401]
pvalloc is guarantueed to round up the allocation size to the page
size, so applications can assume that the memory region is larger
than the passed-in argument.  The alloc_size attribute cannot express
that.

The test case is based on a suggestion from Jakub Jelinek.

This fixes commit 9bf8e29ca1 ("malloc:
make malloc fail with requests larger than PTRDIFF_MAX (BZ#23741)").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 768c83b7f6)
2020-01-17 15:11:20 +01:00
Florian Weimer 858069cb60 login: Use pread64 in utmp implementation
This reduces the possible error scenarios considerably because
no longer can file seek fail, leaving the file descriptor in an
inconsistent state and out of sync with the cache.

As a result, it is possible to avoid setting file_offset to -1
to make an error persistent.  Instead, subsequent calls will retry
the operation and report any errors returned by the kernel.

This change also avoids reading the file from the start if pututline
is called multiple times, to work around lock acquisition failures
due to timeouts.

Change-Id: If21ea0c162c38830a89331ea93cddec14c0974de
(cherry picked from commit d4625a19fe)
2020-01-17 13:56:43 +01:00
Leandro Pereira 6359e79b4c Add nocancel version of pread64()
This is in preparation for changes in the dynamic linker so that
pread() is used instead of lseek()+read().

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit fed33b0fb0)
2020-01-17 13:56:43 +01:00
Florian Weimer dfa1f9fe0d login: Introduce matches_last_entry to utmp processing
This simplifies internal_getut_nolock and fixes a regression,
introduced in commit be6b16d975
("login: Acquire write lock early in pututline [BZ #24882]")
in pututxline because __utmp_equal can only compare process-related
utmp entries.

Fixes: be6b16d975
Change-Id: Ib8a85002f7f87ee41590846d16d7e52bdb82f5a5
(cherry picked from commit 76a7c103eb)
2020-01-17 13:56:43 +01:00
Florian Weimer 83f793e6a6 login: Acquire write lock early in pututline [BZ #24882]
It has been reported that due to lack of fairness in POSIX file
locking, the current reader-to-writer lock upgrade can result in
lack of forward progress.  Acquiring the write lock directly
hopefully avoids this issue if there are only writers.

This also fixes bug 24882 due to the cache revalidation in
__libc_pututline.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Change-Id: I57e31ae30719e609a53505a0924dda101d46372e
(cherry picked from commit be6b16d975)
2020-01-17 13:56:29 +01:00
Florian Weimer 85da102c52 login: Add nonstring attributes to struct utmp, struct utmpx [BZ #24899]
Commit 7532837d7b ("The
-Wstringop-truncation option new in GCC 8 detects common misuses")
added __attribute_nonstring__ to bits/utmp.h, but it did not update
the parallel bits/utmpx.h header.  In struct utmp, the nonstring
attribute for ut_id was missing.

(cherry picked from commit c2adefbafc)
2020-01-17 13:56:00 +01:00
Florian Weimer 143cea84a0 login: Remove double-assignment of fl.l_whence in try_file_lock
Since l_whence is the second member of struct flock, it is written
twice.  The double-assignment is technically undefined behavior due to
the lack of a sequence point.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Change-Id: I2baf9e70690e723c61051b25ccbd510aec15976c
(cherry picked from commit b0a83ae71b)
2020-01-17 13:55:40 +01:00
Florian Weimer f0cd1cfbe3 login: pututxline could fail to overwrite existing entries [BZ #24902]
The internal_getut_r function updates the file_offset variable and
therefore must always update last_entry as well.

Previously, if pututxline could not upgrade the read lock to a
write lock, internal_getut_r would update file_offset only,
without updating last_entry, and a subsequent call would not
overwrite the existing utmpx entry at file_offset, instead
creating a new entry.  This has been observed to cause unbounded
file growth in high-load situations.

This commit removes the buffer argument to internal_getut_r and
updates the last_entry variable directly, along with file_offset.

Initially reported and fixed by Ondřej Lysoněk.

Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
(cherry picked from commit 61d3db4281)
2020-01-17 13:55:35 +01:00
Florian Weimer dbbd748c5f login: Use struct flock64 in utmp [BZ #24880]
Commit 06ab719d30 ("Fix Linux fcntl OFD
locks for non-LFS architectures (BZ#20251)") introduced the use of
fcntl64 into the utmp implementation.  However, the lock file
structure was not updated to struct flock64 at that point.

(cherry picked from commit 0d5b291753)
2020-01-17 13:55:03 +01:00
Florian Weimer 8baeebad9a login: Disarm timer after utmp lock acquisition [BZ #24879]
If the file processing takes a long time for some reason, SIGALRM can
arrive while the file is still being processed.  At that point, file
access will fail with EINTR.  Disarming the timer after lock
acquisition avoids that.  (If there was a previous alarm, it is the
responsibility of the caller to deal with the EINTR error.)

(cherry picked from commit 628598be7e)
2020-01-17 13:54:37 +01:00
Florian Weimer 16a5765042 login: Fix updwtmp, updwtmx unlocking
Commit 5a3afa9738 (login: Replace
macro-based control flow with function calls in utmp) introduced
a regression because after it, __libc_updwtmp attempts to unlock
the wrong file descriptor.

(cherry picked from commit 341da5b4b6)
2020-01-17 13:54:11 +01:00
Florian Weimer 2f02abb81c login: Replace macro-based control flow with function calls in utmp
(cherry picked from commit 5a3afa9738)
2020-01-17 13:54:11 +01:00
Florian Weimer 799f4baa1d login: Assume that _HAVE_UT_* constants are true
Make the GNU version of bits/utmp.h the generic version because
all remaining ports use it (with a sysdeps override for
Linux s390/s390x).

(cherry picked from commit a33b817f13)
2020-01-17 13:54:11 +01:00
Florian Weimer b90aefd4ac login: Remove utmp backend jump tables [BZ #23518]
There is just one file-based implementation, so this dispatch
mechanism is unnecessary.  Instead of the vtable pointer
__libc_utmp_jump_table, use a non-negative file_fd as the indicator
that the backend is initialized.

(cherry picked from commit 1a7fe2ebe5)
2020-01-17 13:54:07 +01:00
Florian Weimer 50f20fe506 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:30:13 +01:00
Kamlesh Kumar 4719e1851c <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:54:47 +01:00
Florian Weimer 761452f127 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.
2019-12-03 20:26:28 +01:00
Florian Weimer 5a08bdb1e7 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:18:12 +01:00
Stefan Liebler f4419b0d01 S390: Fix handling of needles crossing a page in strstr z15 ifunc-variant. [BZ #25226]
If the specified needle crosses a page-boundary, the s390-z15 ifunc variant of
strstr truncates the needle which results in invalid results.

This is fixed by loading the needle beyond the page boundary to v18 instead of v16.
The bug is sometimes observable in test-strstr.c in check1 and check2 as the
haystack and needle is stored on stack. Thus the needle can be on a page boundary.

check2 is now extended to test haystack / needles located on stack, at end of page
and on two pages.

This bug was introduced with commit 6f47401bd5
("S390: Add arch13 strstr ifunc variant.") and is already released in glibc 2.30.

(cherry picked from commit bfdb731438)
2019-11-27 12:38:58 +01:00
Tulio Magno Quites Machado Filho b325b5a60f Merge branch release/2.30/master into ibm/2.30/master 2019-11-22 17:16:27 -03:00
Marcin Kościelnicki 37c90e1173 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:09:23 +01:00
Emilio Cobos Álvarez a4b3bbf71e Don't use a custom wrapper macro around __has_include (bug 25189).
This causes issues when using clang with -frewrite-includes to e.g.,
submit the translation unit to a distributed compiler.

In my case, I was building Firefox using sccache.

See [1] for a reduced test-case since I initially thought this was a
clang bug, and [2] for more context.

Apparently doing this is invalid C++ per [cpp.cond], which mentions [3]:

> The #ifdef and #ifndef directives, and the defined conditional
> inclusion operator, shall treat __has_include and __has_cpp_attribute
> as if they were the names of defined macros.  The identifiers
> __has_include and __has_cpp_attribute shall not appear in any context
> not mentioned in this subclause.

[1]: https://bugs.llvm.org/show_bug.cgi?id=43982
[2]: https://bugs.llvm.org/show_bug.cgi?id=37990
[3]: http://eel.is/c++draft/cpp.cond#7.sentence-2

Change-Id: Id4b8ee19176a9e4624b533087ba870c418f27e60
(cherry picked from commit bfa864e164)
2019-11-22 13:09:01 +01:00
DJ Delorie 919af705ee 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-11-19 12:27:04 +01:00
Florian Weimer 09abef31a5 malloc: Various cleanups for malloc/tst-mxfast
(cherry picked from commit f9769a2397)
2019-11-19 12:26:20 +01:00
DJ Delorie 09b81b2bab 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-11-19 12:24:06 +01:00
Niklas Hambüchen 5f620768fb 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-11-19 12:23:07 +01:00
Paul A. Clarke 0c08d8e575 ChangeLog update from my last commit
I forgot to include the ChangeLog update with my last commit:
7b8481b330.

Signed-off-by: Paul A. Clarke  <pc@us.ibm.com>
2019-11-13 15:39:48 -06:00
Paul A. Clarke 13f59c3ea6 [powerpc] No need to enter "Ignore Exceptions Mode"
Since at least POWER8, there is no performance advantage to entering
"Ignore Exceptions Mode", and doing so conditionally requires
 - the conditional logic, and
 - a system call.

Make it a no-op for uses within glibc.
2019-11-13 15:37:27 -06:00
Paul A. Clarke 54486d8bf8 [powerpc] Rename fesetenv_mode to fesetenv_control
fesetenv_mode is used variously to write the FPSCR exception enable
bits and rounding mode bits.  These are referred to as the control
bits in the POWER ISA.  Change the name to be reflective of its
current and expected use, and match up well with fegetenv_control.
2019-11-13 15:37:19 -06:00
Paul A. Clarke f8a5de7385 [powerpc] libc_feholdsetround_noex_ppc_ctx: optimize FPSCR write
libc_feholdsetround_noex_ppc_ctx currently performs:
1. Read FPSCR, save to context.
2. Create new FPSCR value: clear enables and set new rounding mode.
3. Write new value to FPSCR.

Since other bits just pass through, there is no need to write them.

Instead, write just the changed values (enables and rounding mode),
which can be a bit more efficient.
2019-11-13 15:37:09 -06:00
Paul A. Clarke d58efcaa0b [powerpc] Rename fegetenv_status to fegetenv_control
fegetenv_status is used variously to retrieve the FPSCR exception enable
bits, rounding mode bits, or both.  These are referred to as the control
bits in the POWER ISA.  FPSCR status bits are also returned by the
'mffs' and 'mffsl' instructions, but they are uniformly ignored by all
uses of fegetenv_status.  Change the name to be reflective of its
current and expected use.

Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
2019-11-13 15:36:58 -06:00
Paul A. Clarke 8a7b3df72d [powerpc] __fesetround_inline optimizations
On POWER9, use more efficient means to update the 2-bit rounding mode
via the 'mffscrn' instruction (instead of two 'mtfsb0/1' instructions
or one 'mtfsfi' instruction that modifies 4 bits).

Suggested-by: Paul E. Murphy  <murphyp@linux.ibm.com>
Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
2019-11-13 15:36:50 -06:00
Paul A. Clarke 11c0fd3ab3 [powerpc] libc_feupdateenv_test: optimize FPSCR access
ROUND_TO_ODD and a couple of other places use libc_feupdateenv_test to
restore the rounding mode and exception enables, preserve exception flags,
and test whether given exception(s) were generated.

If the exception flags haven't changed, then it is sufficient and a bit
more efficient to just restore the rounding mode and enables, rather than
writing the full Floating-Point Status and Control Register (FPSCR).

Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
2019-11-13 15:36:41 -06:00
Paul A. Clarke 6a1cfa6c0b [powerpc] fenv_private.h clean up
fenv_private.h includes unused functions, magic macro constants, and
some replicated common code fragments.

Remove unused functions, replace magic constants with constants from
fenv_libc.h, and refactor replicated code.

Suggested-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-By: Paul E Murphy <murphyp@linux.ibm.com>
2019-11-13 15:36:31 -06:00
Paul A. Clarke d7c93b27ee [powerpc] SET_RESTORE_ROUND optimizations and bug fix
SET_RESTORE_ROUND brackets a block of code, temporarily setting and
restoring the rounding mode and letting everything else, including
exceptions generated within the block, pass through.

On powerpc, the current code clears the exception enables, which will hide
exceptions generated within the block.  This issue was introduced by me
in commit e905212627.

Fix this by not clearing exception enable bits in the prologue.

Also, since we are no longer changing the enable bits in either the
prologue or the epilogue, there is no need to test for entering/exiting
non-stop mode.

Also, optimize the prologue get/save/set rounding mode operations for
POWER9 and later by using 'mffscrn' when possible.

Suggested-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
Fixes: e905212627

2019-09-19  Paul A. Clarke  <pc@us.ibm.com>

	* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_and_set_rn): New.
	(__fe_mffscrn): New.
	* sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
	Do not clear enable bits, remove obsolete code, use
	fegetenv_and_set_rn.
	(libc_feresetround_ppc): Remove obsolete code, use
	fegetenv_and_set_rn.
2019-11-13 15:36:08 -06:00
Paul A. Clarke f34079acb8 [powerpc] fegetenv_status: simplify instruction generation
fegetenv_status() wants to use the lighter weight instruction 'mffsl'
for reading the Floating-Point Status and Control Register (FPSCR).
It currently will use it directly if compiled '-mcpu=power9', and will
perform a runtime check (cpu_supports("arch_3_00")) otherwise.

Nicely, it turns out that the 'mffsl' instruction will decode to
'mffs' on architectures older than "arch_3_00" because the additional
bits set for 'mffsl' are "don't care" for 'mffs'.  'mffs' is a superset
of 'mffsl'.

So, just generate 'mffsl'.
2019-11-13 15:35:53 -06:00
Paul A. Clarke c930cf421e [powerpc] fesetenv: optimize FPSCR access
fesetenv() reads the current value of the Floating-Point Status and Control
Register (FPSCR) to determine the difference between the current state of
exception enables and the newly requested state.  All of these bits are also
returned by the lighter weight 'mffsl' instruction used by fegetenv_status().
Use that instead.

Also, remove a local macro _FPU_MASK_ALL in favor of a common macro,
FPU_ENABLES_MASK from fenv_libc.h.

Finally, use a local variable ('new') in favor of a pointer dereference
('*envp').
2019-11-13 15:35:40 -06:00
Paul A. Clarke 9859549f35 [powerpc] SET_RESTORE_ROUND improvements
SET_RESTORE_ROUND uses libc_feholdsetround_ppc_ctx and
libc_feresetround_ppc_ctx to bracket a block of code where the floating point
rounding mode must be set to a certain value.

For the *prologue*, libc_feholdsetround_ppc_ctx is used and performs:
1. Read/save FPSCR.
2. Create new value for FPSCR with new rounding mode and enables cleared.
3. If new value is different than current value,
   a. If transitioning from a state where some exceptions enabled,
      enter "ignore exceptions / non-stop" mode.
   b. Write new value to FPSCR.
   c. Put a mark on the wall indicating the FPSCR was changed.

(1) uses the 'mffs' instruction.  On POWER9, the lighter weight 'mffsl'
instruction can be used, but it doesn't return all of the bits in the FPSCR.
fegetenv_status uses 'mffsl' on POWER9, 'mffs' otherwise, and can thus be
used instead of fegetenv_register.
(3b) uses 'mtfsf 0b11111111' to write the entire FPSCR, so it must
instead use 'mtfsf 0b00000011' to write just the enables and the mode,
because some of the rest of the bits are not valid if 'mffsl' was used.
fesetenv_mode uses 'mtfsf 0b00000011' on POWER9, 'mtfsf 0b11111111'
otherwise.

For the *epilogue*, libc_feresetround_ppc_ctx checks the mark on the wall, then
calls libc_feresetround_ppc, which just calls __libc_femergeenv_ppc with
parameters such that it performs:
1. Retreive saved value of FPSCR, saved in prologue above.
2. Read FPSCR.
3. Create new value of FPSCR where:
   - Summary bits and exception indicators = current OR saved.
   - Rounding mode and enables = saved.
   - Status bits = current.
4. If transitioning from some exceptions enabled to none,
   enter "ignore exceptions / non-stop" mode.
5. If transitioning from no exceptions enabled to some,
   enter "catch exceptions" mode.
6. Write new value to FPSCR.

The summary bits are hardwired to the exception indicators, so there is no
need to restore any saved summary bits.
The exception indicator bits, which are sticky and remain set unless
explicitly cleared, would only need to be restored if the code block
might explicitly clear any of them.  This is certainly not expected.

So, the only bits that need to be restored are the enables and the mode.
If it is the case that only those bits are to be restored, there is no need to
read the FPSCR.  Steps (2) and (3) are unnecessary, and step (6) only needs to
write the bits being restored.

We know we are transitioning out of "ignore exceptions" mode, so step (4) is
unnecessary, and in step (6), we only need to check the state we are
entering.
2019-11-13 15:35:26 -06:00
Paul A. Clarke 5216c16e80 [powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses
Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the
"mode" (exception enable and rounding mode) bits of the Floating Point Status
Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used
to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be
used to write just those bits back to the FPSCR.  The net is better performance.

In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or
they determine that it doesn't need to be written because it is not changing.
In either case, the local variable holds the current values of the enable
bits in the FPSCR.  This local variable can be used instead of again reading
the FPSCR.

Also, that value of the FPSCR which is read the second time is validated
against the requested enables.  Since the write can't fail, this validation
step is unnecessary, and can be removed.  Instead, the exceptions to be
enabled (or disabled) are transformed into available bits in the FPSCR,
then validated after being transformed back, to ensure that all requested
bits are actually being set.  For example, FE_INVALID_SQRT can be
requested, but cannot actually be set.  This bit is not mapped during the
transformations, so a test for that bit being set before and after
transformations will show the bit would not be set, and the function will
return -1 for failure.

Finally, convert the local macros in fesetmode.c to more generally useful
macros in fenv_libc.h.
2019-11-13 15:35:17 -06:00
Paul A. Clarke f2923060f0 [powerpc] fe{en,dis}ableexcept optimize bit translations
The exceptions passed to fe{en,dis}ableexcept() are defined in the ABI
as a bitmask, a combination of FE_INVALID, FE_OVERFLOW, etc.
Within the functions, these bits must be translated to/from the corresponding
enable bits in the Floating Point Status Control Register (FPSCR).
This translation is currently done bit-by-bit.  The compiler generates
a series of conditional bit operations.  Nicely, the "FE" exception
bits are all a uniform offset from the FPSCR enable bits, so the bit-by-bit
operation can instead be performed by a shift with appropriate masking.
2019-11-13 15:34:52 -06:00
Stefan Liebler 26fe8ad37a S390: Add new s390 platform z15.
The new IBM z15 is added to platform string array.
The macro _DL_PLATFORMS_COUNT is incremented.

(cherry picked from commit 2901743568)
2019-11-13 15:31:24 -06:00
Joseph Myers c70164e727 Fix RISC-V vfork build with Linux 5.3 kernel headers.
Building glibc for RISC-V with Linux 5.3 kernel headers fails because
<linux/sched.h>, included in vfork.S for CLONE_* constants, contains a
structure definition not safe for inclusion in assembly code.

All other architectures already avoid use of that header in vfork.S,
either defining the CLONE_* constants locally or embedding the
required values directly in the relevant instruction, where they
implement vfork using the clone syscall (see the implementations for
aarch64, ia64, mips and nios2).  This patch makes the RISC-V version
define the constants locally like the other architectures.

Tested build for all three RISC-V configurations in
build-many-glibcs.py with Linux 5.3 headers.

	* sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
	<linux/sched.h>.
	(CLONE_VM): New macro.
	(CLONE_VFORK): Likewise.

(cherry picked from commit 8cacbcf4a9)
2019-11-13 15:31:23 -06:00
Aurelien Jarno 9adcf488e6 alpha: force old OSF1 syscalls for getegid, geteuid and getppid [BZ #24986]
On alpha, Linux kernel 5.1 added the standard getegid, geteuid and
getppid syscalls (commit ecf7e0a4ad15287). Up to now alpha was using
the corresponding OSF1 syscalls through:
 - sysdeps/unix/alpha/getegid.S
 - sysdeps/unix/alpha/geteuid.S
 - sysdeps/unix/alpha/getppid.S

When building against kernel headers >= 5.1, the glibc now use the new
syscalls through sysdeps/unix/sysv/linux/syscalls.list. When it is then
used with an older kernel, the corresponding 3 functions fail.

A quick fix is to move the OSF1 wrappers under the
sysdeps/unix/sysv/linux/alpha directory so they override the standard
linux ones. A better fix would be to try the new syscalls and fallback
to the old OSF1 in case the new ones fail. This can be implemented in
a later commit.

Changelog:
	[BZ #24986]
        * sysdeps/unix/alpha/getegid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
        * sysdeps/unix/alpha/geteuid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
        * sysdeps/unix/alpha/getppid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
(cherry picked from commit 1a6566094d)
2019-11-13 15:31:23 -06:00
Adhemerval Zanella 139e62dba9 hppa: Update libm-tests-ulps
The make regen-ulps was done on a PA8900 with 8.3.0.

	* sysdeps/hppa/fpu/libm-test-ulps: Update.

(cherry picked from commit 3175dcc1e6)
2019-11-13 15:31:23 -06:00
Aurelien Jarno d9e31526ba Update Alpha libm-test-ulps
Changelog:

	* sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.

(cherry picked from commit b5367a08ae)
2019-11-13 15:31:23 -06:00
Rafal Luzynski 01efb543d5 Chinese locales: Set first_weekday to 2 (bug 24682).
The first day of the week in China (Mainland) should be Monday according
to the national standard GB/T 7408-2005.  References:

* https://www.doc88.com/p-1166696540287.html
* https://unicode-org.atlassian.net/browse/CLDR-11510

	[BZ #24682]
	* NEWS: Mention this bug fixed.
	* localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
	* localedata/locales/ug_CN (first_weekday): Likewise.
	* localedata/locales/zh_CN (first_weekday): Likewise.

(cherry picked from commit c0fd3244e7)
2019-11-13 15:31:22 -06:00
Florian Weimer c1a0df3bcb 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-11-13 15:31:22 -06:00
Dragan Mladjenovic c347431fb5 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:57:13 -03:00
Gabriel F. T. Gomes fca2d6186a Make tst-strftime2 and tst-strftime3 depend on locale generation
Building the test cases in parallel might make tst-strftime2 and
tst-strftime3 fail.  Simply re-running the test case (or building
serially) makes the problem go away.  This patch adds the necessary
dependency to allow parallel builds in the time subdirectory.

Tested for powerpc64le.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
(cherry picked from commit 52151051b3)
2019-10-31 21:49:14 +00:00
Stefan Liebler 5397c399f9 S390: Add new s390 platform z15.
The new IBM z15 is added to platform string array.
The macro _DL_PLATFORMS_COUNT is incremented.

(cherry picked from commit 2901743568)
2019-10-18 15:07:15 +02:00
Joseph Myers a6aaabd036 Fix RISC-V vfork build with Linux 5.3 kernel headers.
Building glibc for RISC-V with Linux 5.3 kernel headers fails because
<linux/sched.h>, included in vfork.S for CLONE_* constants, contains a
structure definition not safe for inclusion in assembly code.

All other architectures already avoid use of that header in vfork.S,
either defining the CLONE_* constants locally or embedding the
required values directly in the relevant instruction, where they
implement vfork using the clone syscall (see the implementations for
aarch64, ia64, mips and nios2).  This patch makes the RISC-V version
define the constants locally like the other architectures.

Tested build for all three RISC-V configurations in
build-many-glibcs.py with Linux 5.3 headers.

	* sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
	<linux/sched.h>.
	(CLONE_VM): New macro.
	(CLONE_VFORK): Likewise.

(cherry picked from commit 8cacbcf4a9)
2019-09-20 21:28:34 +02:00
Aurelien Jarno b1299aab22 alpha: force old OSF1 syscalls for getegid, geteuid and getppid [BZ #24986]
On alpha, Linux kernel 5.1 added the standard getegid, geteuid and
getppid syscalls (commit ecf7e0a4ad15287). Up to now alpha was using
the corresponding OSF1 syscalls through:
 - sysdeps/unix/alpha/getegid.S
 - sysdeps/unix/alpha/geteuid.S
 - sysdeps/unix/alpha/getppid.S

When building against kernel headers >= 5.1, the glibc now use the new
syscalls through sysdeps/unix/sysv/linux/syscalls.list. When it is then
used with an older kernel, the corresponding 3 functions fail.

A quick fix is to move the OSF1 wrappers under the
sysdeps/unix/sysv/linux/alpha directory so they override the standard
linux ones. A better fix would be to try the new syscalls and fallback
to the old OSF1 in case the new ones fail. This can be implemented in
a later commit.

Changelog:
	[BZ #24986]
        * sysdeps/unix/alpha/getegid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
        * sysdeps/unix/alpha/geteuid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
        * sysdeps/unix/alpha/getppid.S: Move to ...
	* sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
(cherry picked from commit 1a6566094d)
2019-09-14 20:08:02 +02:00
Adhemerval Zanella 3c3f8dc307 hppa: Update libm-tests-ulps
The make regen-ulps was done on a PA8900 with 8.3.0.

	* sysdeps/hppa/fpu/libm-test-ulps: Update.

(cherry picked from commit 3175dcc1e6)
2019-09-08 22:57:15 +02:00
Aurelien Jarno 5438639cff Update Alpha libm-test-ulps
Changelog:

	* sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.

(cherry picked from commit b5367a08ae)
2019-09-03 21:38:07 +02:00
Rafal Luzynski d74461fa34 Chinese locales: Set first_weekday to 2 (bug 24682).
The first day of the week in China (Mainland) should be Monday according
to the national standard GB/T 7408-2005.  References:

* https://www.doc88.com/p-1166696540287.html
* https://unicode-org.atlassian.net/browse/CLDR-11510

	[BZ #24682]
	* NEWS: Mention this bug fixed.
	* localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
	* localedata/locales/ug_CN (first_weekday): Likewise.
	* localedata/locales/zh_CN (first_weekday): Likewise.

(cherry picked from commit c0fd3244e7)
2019-08-28 22:37:52 +02:00
Tulio Magno Quites Machado Filho 9ca2648e2a Let ld.so have flags DT_RPATH and DT_RUNPATH
2018-08-02  Tulio Magno Quites Machado Filho  <tuliom@linux.ibm.com>

	* elf/get-dynamic-info.h: Remove asserts that prevent ld.so from
	having the flags DT_RPATH and DT_RUNPATH.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
2019-08-01 14:01:04 -03:00
Florian Weimer be9a328c93 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-08-01 16:48:12 +02:00
291 changed files with 12945 additions and 3292 deletions
+379
View File
@@ -1,3 +1,382 @@
2019-08-15 Florian Weimer <fweimer@redhat.com>
[BZ #24899]
* sysdeps/gnu/bits/utmpx.h (struct utmpx): Add
__attribute_nonstring__ to ut_line, ut_id, ut_user, ut_host.
* sysdeps/unix/sysv/linux/s390/bits/utmpx.h (struct utmpx):
Likewise.
* sysdeps/gnu/bits/utmp.h (struct utmp): Add
__attribute_nonstring__ to ut_id.
* sysdeps/unix/sysv/linux/s390/bits/utmpx.h (struct utmp):
Likewise.
2019-08-28 Florian Weimer <fweimer@redhat.com>
[BZ #24902]
* login/Makefile (tests): Add tst-pututxline-lockfail.
(tst-pututxline-lockfail): Link with -lpthread.
* login/utmp_file.c (internal_getut_r): Remove buffer argument.
(__libc_getutid_r): Adjust.
(__libc_pututline): Likewise. Check for file_offset == -1.
* login/tst-pututxline-lockfail.c: New file.
2019-08-15 Florian Weimer <fweimer@redhat.com>
[BZ #24880]
* login/utmp_file.c (file_locking_failed): Use struct flock64.
(file_locking_unlock): Likewise.
2019-08-15 Florian Weimer <fweimer@redhat.com>
[BZ #24879]
login: Disarm timer after utmp lock acquisition.
* login/utmp_file.c (struct file_locking): Remove.
(try_file_lock): Adjust.
(file_lock_restore): Remove function.
(__libc_getutent_r): .
(internal_getut_r): Likewise.
(__libc_getutline_r): Likewise.
(__libc_pututline): Likewise.
(__libc_updwtmp): Likewise.
2019-08-15 Florian Weimer <fweimer@redhat.com>
* login/utmp_file.c (__libc_updwtmp): Unlock the right file
descriptor.
* login/Makefile (tests): Add tst-updwtmpx.
* login/tst-updwtmpx.c: New file.
2019-08-13 Florian Weimer <fweimer@redhat.com>
* login/utmp_file.c (LOCK_FILE, LOCKING_FAILED, UNLOCK_FILE):
Remove macros.
(struct file_locking): New.
(try_file_lock, file_unlock, file_lock_restore): New functions.
(__libc_getutent_r): Use the new functions.
(internal_getut_r): Likewise.
(__libc_getutline_r): Likewise.
(__libc_pututline): Likewise.
(__libc_updwtmp): Likewise.
2019-08-13 Florian Weimer <fweimer@redhat.com>
* login/getutid_r.c (__getutid_r): _HAVE_UT_ID and _HAVE_UT_TYPE
are always true.
* login/getutmp.c (getutmp): _HAVE_UT_TYPE, _HAVE_UT_PID,
_HAVE_UT_ID, _HAVE_UT_HOST, _HAVE_UT_TV are always true.
* login/getutmpx.c (getutmpx): Likewise.
* login/login.c (login): _HAVE_UT_TYPE, _HAVE_UT_PID are always
true.
* login/logout.c (logout): _HAVE_UT_TYPE, _HAVE_UT_HOST,
_HAVE_UT_TV are always true.
* login/logwtmp.c (logwtmp): _HAVE_UT_PID, _HAVE_UT_TYPE,
_HAVE_UT_HOST, _HAVE_UT_TV are always true.
* login/tst-utmp.c: _HAVE_UT_TYPE, _HAVE_UT_TV are always true.
* login/utmp_file.c (__libc_setutent): _HAVE_UT_TYPE, _HAVE_UT_ID
are always true.
(internal_getut_r): _HAVE_UT_TYPE is always true.
(__libc_pututline): Likewise.
* login/programs/utmpdump.c (print_entry): Assume that
_HAVE_UT_TYPE, _HAVE_UT_PID, _HAVE_UT_ID, _HAVE_UT_HOST,
_HAVE_UT_TV are always true.
* sysdeps/generic/utmp-equal.h (__utmp_equal): _HAVE_UT_TYPE,
_HAVE_UT_ID are always true.
* sysdeps/gnu/bits/utmp.h: Move to ...
* bits/utmp.h: ... here, replacing the old file.
2019-08-05 Florian Weimer <fweimer@redhat.com>
[BZ #23518]
* login/uptmp-private.h (struct ufuncs): Remove definition.
(__libc_utmp_file_functions, __libc_utmp_unknown_functions)
(__libc_utmp_jump_table): Remove declarations.
(__libc_setutent, __libc_getutent_r, __libc_getutid_r)
(__libc_getutline_r, __libc_pututline, __libc_endutent)
(__libc_updwtmp): Declare.
* login/getutent_r.c (__libc_utmp_unknown_functions)
(__libc_utmp_jump_table, setutent_unknown, getutent_r_unknown)
(getutid_r_unknown, getutline_r_unknown, pututline_unknown)
(endutent_unknown): Remove definitions.
(__setutent): Call __libc_setutent.
(__getutent_r): Call __libc_getutent_r.
(__pututline): Call __libc_pututline.
(__endutent): Call __libc_endutent.
* login/getutid_r.c (__getutid_r): Call __libc_getutid_r.
* login/getutline_r.c (__getutline_r): Call __libc_getutline_r.
* login/updwtmp.c (__updwtmp): Call __libc_updwtmp.
* login/utmp_file.c (__libc_utmp_file_functions): Remove definition
(__libc_setutent): Rename from stetutent_file. Drop static.
(maybe_setutent): New function.
(__libc_getutent_r): Rename from getutent_r_file. Drop static.
Check for initialization.
(__libc_getutid_r): Rename from getutid_r_file. Drop static.
Check for initialization.
(__libc_getutline_r): Rename from getutline_r_file. Drop static.
Check for initialization.
(__libc_pututline): Rename from pututline_file. Drop static.
Check for initialization.
(__libc_endutent): Rename from endutent_file. Drop static. Check
for initialization.
(__libc_updwtmp): Rename from updwtmp_file. Drop static.
* login/utmpname.c (__utmpname): Call __libc_endutent.
* sysdeps/unix/getlogin_r (__getlogin_r): Call __libc_setutent,
__libc_getutlien_r, __libc_endutent.
* manual/users.texi (Who Logged In, Manipulating the Database):
Adjust.
2019-08-15 Florian Weimer <fweimer@redhat.com>
* malloc/Makefile (tests): Only add tst-mxfast for
$(have-tunables).
* malloc/tst-mxfast.c: Fix copyright year.
(do_test): Fix GNU style issues. Use TEST_COMPARE instead of
assert for checks.
2019-08-09 DJ Delorie <dj@redhat.com>
* 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.
2019-08-08 Niklas Hambüchen <mail@nh2.me>
Carlos O'Donell <carlos@redhat.com>
[BZ #24026]
* malloc/malloc.c (__malloc_info): Account for top chunk.
2019-11-01 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
* 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.
2019-10-08 Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
* Makefile: Fix locale dependency for a couple of tests.
($(objpfx)tst-strftime2.out): New rule.
($(objpfx)tst-strftime3.out): Likewise.
2019-09-20 Joseph Myers <joseph@codesourcery.com>
* sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
<linux/sched.h>.
(CLONE_VM): New macro.
(CLONE_VFORK): Likewise.
2019-09-14 Aurelien Jarno <aurelien@aurel32.net>
[BZ #24986]
* sysdeps/unix/alpha/getegid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
* sysdeps/unix/alpha/geteuid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
* sysdeps/unix/alpha/getppid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
2019-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/hppa/fpu/libm-test-ulps: Update.
2019-09-03 Aurelien Jarno <aurelien@aurel32.net>
* sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.
2019-08-28 Rafal Luzynski <digitalfreak@lingonborough.com>
[BZ #24682]
* NEWS: Mention this bug fixed.
* localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
* localedata/locales/ug_CN (first_weekday): Likewise.
* localedata/locales/zh_CN (first_weekday): Likewise.
2019-08-01 Florian Weimer <fweimer@redhat.com>
[BZ #24867]
* malloc/malloc.c (__malloc_info): Remove unwanted leading
whitespace.
2019-10-02 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_private.h:
(__TEST_AND_BEGIN_NON_STOP): New.
(__TEST_AND_END_NON_STOP): New.
(libc_feholdexcept_setround_ppc): Use __TEST_AND_BEGIN_NON_STOP.
(__libc_femergeenv_ppc): Use __TEST_AND_BEGIN_NON_STOP and
__TEST_AND_END_NON_STOP.
(libc_feholdsetround_noex_ppc_ctx): Use __TEST_AND_END_NON_STOP.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_mode): Rename to
fesetenv_control.
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Accommodate
rename of fesetenv_mode to fegetenv_control.
* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
* sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
* sysdeps/powerpc/fpu/fenv_private.h (__libc_femergeenv_ppc): Likewise.
(libc_feholdsetround_noex_ppc_ctx): Likewise.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_private.h
(libc_feholdsetround_noex_ppc_ctx): Call fesetenv_mode instead
of fesetenv_register.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status): Rename to
fegetenv_control.
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Accommodate
rename of fegetenv_status to fegetenv_control.
* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
* sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Likewise.
* sysdeps/powerpc/fpu/fegetmode.c (fegetmode): Likewise.
* sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
* sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (__fesetround_inline): Use
'mffscrn' instruction on POWER9.
(__fesetround_inline_nocheck): Likewise.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (FPSCR_EXCEPTIONS_MASK): New.
* sysdeps/powerpc/fpu/fenv_private.h (__libc_femergeenv_ppc): Optimize
to write FPSCR control only, if exceptions have not changed.
2019-09-27 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h:
(__TEST_AND_ENTER_NON_STOP): New.
(__TEST_AND_EXIT_NON_STOP): New.
* sysdeps/powerpc/fpu/fenv_private.h
(_FPU_ALL_TRAPS): Delete, replace with FPSCR_ENABLES_MASK.
(_FPU_MASK_RN): Delete.
(_FPU_MASK_NOT_RN_NI): Delete.
(_FPU_MASK_TRAPS_RN): Delete, replace with ~FPSCR_CONTROL_MASK.
(_FPU_MASK_FRAC_INEX_RET_CC): Delete, replace with ~FPSCR_STATUS_MASK.
(__libc_feholdbits_ppc): Delete, move code into
libc_feholdexcept_setround_ppc.
(libc_feholdexcept_ppc): Delete.
(libc_fesetround_ppc): Delete.
(libc_fetestexcept_ppc): Delete.
(libc_feholdsetround_ppc): Delete.
(__libc_femergeenv_ppc): Use __TEST_AND_ENTER/EXIT_NON_STOP.
(libc_feholdsetround_noex_ppc_ctx): Likewise.
(libc_feupdateenv_test_ppc): Use FPSCR defines.
* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Use
__TEST_AND_ENTER_NON_STOP.
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
* sysdeps/powerpc/fpu/feholdexcpt.c (__feholdexcept): Likewise.
* sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
* sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
* sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Likewise.
(_FPU_MASK_ALL): Delete.
2019-09-19 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_and_set_rn): New.
(__fe_mffscrn): New.
* sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
Do not clear enable bits, remove obsolete code, use
fegetenv_and_set_rn.
(libc_feresetround_ppc): Remove obsolete code, use
fegetenv_and_set_rn.
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status_ISA300): Delete.
(fegetenv_status): Generate 'mffsl' unconditionally.
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Utilize lightweight
FPSCR read.
(_FPU_MASK_ALL): Delete.
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
Utilize lightweight FPSCR read if possible, set fewer FPSCR bits
if possible.
(libc_feresetround_ppc): Replace call to __libc_femergeenv_ppc
with simpler required steps, set fewer FPSCR bits if possible.
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_mode): New.
(FPSCR_FPRF_MASK): New. (FPSCR_STATUS_MASK): New.
* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Use lighter-
weight access to FPSCR; remove unnecessary second FPSCR read and
validate.
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
* sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Use lighter-weight
access to FPSCR; Use macros in fenv_libc.h in favor of local.
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu/fenv_libc.h: Define FPSCR bitmasks.
(fenv_reg_to_exceptions): Replace bitwise operations with mask-shift.
(fenv_exceptions_to_reg): New.
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Replace bitwise
operation with call to fenv_exceptions_to_reg().
* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
2019-09-20 Joseph Myers <joseph@codesourcery.com>
* sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
<linux/sched.h>.
(CLONE_VM): New macro.
(CLONE_VFORK): Likewise.
2019-09-14 Aurelien Jarno <aurelien@aurel32.net>
[BZ #24986]
* sysdeps/unix/alpha/getegid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
* sysdeps/unix/alpha/geteuid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
* sysdeps/unix/alpha/getppid.S: Move to ...
* sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
2019-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/hppa/fpu/libm-test-ulps: Update.
2019-09-03 Aurelien Jarno <aurelien@aurel32.net>
* sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.
2019-08-28 Rafal Luzynski <digitalfreak@lingonborough.com>
[BZ #24682]
* NEWS: Mention this bug fixed.
* localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
* localedata/locales/ug_CN (first_weekday): Likewise.
* localedata/locales/zh_CN (first_weekday): Likewise.
2019-08-01 Florian Weimer <fweimer@redhat.com>
[BZ #24867]
* malloc/malloc.c (__malloc_info): Remove unwanted leading
whitespace.
2019-08-01 Carlos O'Donell <carlos@redhat.com>
* version.h (RELEASE): Set to "stable".
+75
View File
@@ -4,6 +4,81 @@ 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.30.1
Security related changes:
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-10029: Trigonometric functions on x86 targets suffered from stack
corruption when they were passed a pseudo-zero argument. Reported by Guido
Vranken / ForAllSecure Mayhem.
CVE-2020-1751: A defect in the PowerPC backtrace function could cause an
out-of-bounds write when executed in a signal frame context.
CVE-2020-1752: A use-after-free vulnerability in the glob function when
expanding ~user has been fixed.
CVE-2020-27618: An infinite loop has been fixed in the iconv program when
invoked with input containing redundant shift sequences in the IBM1364,
IBM1371, IBM1388, IBM1390, or IBM1399 character sets.
CVE-2020-29562: An assertion failure has been fixed in the iconv function
when invoked with UCS4 input containing an invalid character.
CVE-2021-3326: An assertion failure during conversion from the
ISO-20220-JP-3 character set using the iconv function has been fixed.
This assertion was triggered by certain valid inputs in which the
converted output contains a combined sequence of two wide characters
crossing a buffer boundary. Reported by Tavis Ormandy.
The following bugs are resolved with this release:
[20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT
[20543] Please move from .gnu.linkonce to comdat
[23296] Data race in setting function descriptor during lazy binding
[23518] login: Remove utmp backend jump tables
[24682] localedata: zh_CN first weekday should be Monday per GB/T
7408-2005
[24867] malloc: Remove unwanted leading whitespace in malloc_info
[24879] login: Disarm timer after utmp lock acquisition
[24880] login: Use struct flock64 in utmp
[24882] login: Acquire write lock early in pututline
[24986] alpha: new getegid, geteuid and getppid syscalls used
unconditionally
[24899] login: Add nonstring attributes to struct utmp, struct utmpx
[24902] login: pututxline could fail to overwrite existing entries
[25066] FAIL: nptl/tst-tls1 on hppa
[25189] Don't use a custom wrapper macro around __has_include
[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++
[25401] Remove incorrect alloc_size attribute from pvalloc
[25487] sinl() stack corruption from crafted input (CVE-2020-10029)
[25523] MIPS/Linux inline syscall template is miscompiled
[25635] arm: Wrong sysdep order selection for soft-fp
[25715] system() returns wrong errors when posix_spawn fails
[25810] x32: Incorrect syscall entries with pointer, off_t and size_t
[25896] Incorrect prctl
[25902] Bad LOADARGS_N
[25933] Off by one error in __strncmp_avx2
[25966] Incorrect access of __x86_shared_non_temporal_threshold for x32
[25976] nss_compat: internal_end*ent may clobber errno, hiding ERANGE
[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
Version 2.30
+91 -13
View File
@@ -1,4 +1,4 @@
/* The `struct utmp' type, describing entries in the utmp file. Generic/BSDish
/* The `struct utmp' type, describing entries in the utmp file.
Copyright (C) 1993-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -21,29 +21,107 @@
#endif
#include <paths.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <bits/wordsize.h>
#define UT_NAMESIZE 8
#define UT_LINESIZE 8
#define UT_HOSTSIZE 16
#define UT_LINESIZE 32
#define UT_NAMESIZE 32
#define UT_HOSTSIZE 256
/* The structure describing an entry in the database of
previous logins. */
struct lastlog
{
time_t ll_time;
#if __WORDSIZE_TIME64_COMPAT32
int32_t ll_time;
#else
__time_t ll_time;
#endif
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
struct utmp
/* The structure describing the status of a terminated process. This
type is used in `struct utmp' below. */
struct exit_status
{
char ut_line[UT_LINESIZE];
char ut_user[UT_NAMESIZE];
#define ut_name ut_user
char ut_host[UT_HOSTSIZE];
long int ut_time;
short int e_termination; /* Process termination status. */
short int e_exit; /* Process exit status. */
};
#define _HAVE_UT_HOST 1 /* We have the ut_host field. */
/* The structure describing an entry in the user accounting database. */
struct utmp
{
short int ut_type; /* Type of login. */
pid_t ut_pid; /* Process ID of login process. */
char ut_line[UT_LINESIZE]
__attribute_nonstring__; /* Devicename. */
char ut_id[4]
__attribute_nonstring__; /* Inittab ID. */
char ut_user[UT_NAMESIZE]
__attribute_nonstring__; /* Username. */
char ut_host[UT_HOSTSIZE]
__attribute_nonstring__; /* Hostname for remote login. */
struct exit_status ut_exit; /* Exit status of a process marked
as DEAD_PROCESS. */
/* The ut_session and ut_tv fields must be the same size when compiled
32- and 64-bit. This allows data files and shared memory to be
shared between 32- and 64-bit applications. */
#if __WORDSIZE_TIME64_COMPAT32
int32_t ut_session; /* Session ID, used for windowing. */
struct
{
int32_t tv_sec; /* Seconds. */
int32_t tv_usec; /* Microseconds. */
} ut_tv; /* Time entry was made. */
#else
long int ut_session; /* Session ID, used for windowing. */
struct timeval ut_tv; /* Time entry was made. */
#endif
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
char __glibc_reserved[20]; /* Reserved for future use. */
};
/* Backwards compatibility hacks. */
#define ut_name ut_user
#ifndef _NO_UT_TIME
/* We have a problem here: `ut_time' is also used otherwise. Define
_NO_UT_TIME if the compiler complains. */
# define ut_time ut_tv.tv_sec
#endif
#define ut_xtime ut_tv.tv_sec
#define ut_addr ut_addr_v6[0]
/* Values for the `ut_type' field of a `struct utmp'. */
#define EMPTY 0 /* No valid user accounting information. */
#define RUN_LVL 1 /* The system's runlevel. */
#define BOOT_TIME 2 /* Time of system boot. */
#define NEW_TIME 3 /* Time after system clock changed. */
#define OLD_TIME 4 /* Time when system clock changed. */
#define INIT_PROCESS 5 /* Process spawned by the init process. */
#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
#define USER_PROCESS 7 /* Normal process. */
#define DEAD_PROCESS 8 /* Terminated process. */
#define ACCOUNTING 9
/* Old Linux name for the EMPTY type. */
#define UT_UNKNOWN EMPTY
/* Tell the user that we have a modern system with UT_HOST, UT_PID,
UT_TYPE, UT_ID and UT_TV fields. */
#define _HAVE_UT_TYPE 1
#define _HAVE_UT_PID 1
#define _HAVE_UT_ID 1
#define _HAVE_UT_TV 1
#define _HAVE_UT_HOST 1
Vendored
+23 -2
View File
@@ -3777,11 +3777,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
@@ -4014,7 +4035,7 @@ if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
-o conftest conftest.S 1>&5 2>&5; then
# Do a link to see if the backend supports IFUNC relocs.
$READELF -r conftest 1>&5
LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || {
LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && {
libc_cv_ld_gnu_indirect_function=yes
}
fi
+9 -2
View File
@@ -472,11 +472,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
@@ -641,7 +648,7 @@ if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
-o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
# Do a link to see if the backend supports IFUNC relocs.
$READELF -r conftest 1>&AS_MESSAGE_LOG_FD
LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || {
LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && {
libc_cv_ld_gnu_indirect_function=yes
}
fi
+12
View File
@@ -89,6 +89,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
+2 -2
View File
@@ -1302,6 +1302,8 @@ CFLAGS-ifuncmain7pie.c += $(pie-ccflag)
CFLAGS-ifuncmain9pie.c += $(pie-ccflag)
CFLAGS-tst-ifunc-textrel.c += $(pic-ccflag)
LDFLAGS-ifuncmain6pie = -Wl,-z,lazy
$(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so
$(objpfx)ifuncmain1staticpie: $(objpfx)ifuncdep1pic.o
$(objpfx)ifuncmain1vispie: $(objpfx)ifuncmod1.so
@@ -1512,8 +1514,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
+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
}
}
cpu {
hwcap_mask {
+1 -4
View File
@@ -142,10 +142,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
assert (info[DT_FLAGS] == NULL
|| (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
#endif
#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
assert (info[DT_RUNPATH] == NULL);
assert (info[DT_RPATH] == NULL);
#else
#if ! defined RTLD_BOOTSTRAP && ! defined STATIC_PIE_BOOTSTRAP
if (info[DT_FLAGS] != NULL)
{
/* Flags are used. Translate to the old form where available.
+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 ();
}
+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
+1 -1
View File
@@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION
CFLAGS-simple-hash.c += -I../locale
tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \
tst-iconv7 tst-iconv-mt
tst-iconv7 tst-iconv8 tst-iconv-mt
others = iconv_prog iconvconfig
install-others-programs = $(inst_bindir)/iconv
+4 -12
View File
@@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[0] > 0x80))
{
@@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[3] > 0x80))
{
+50
View File
@@ -0,0 +1,50 @@
/* Test iconv behavior on UCS4 conversions with //IGNORE.
Copyright (C) 2020 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/>. */
/* Derived from BZ #26923 */
#include <errno.h>
#include <iconv.h>
#include <stdio.h>
#include <support/check.h>
static int
do_test (void)
{
iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/");
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
/*
* Convert sequence beginning with an irreversible character into buffer that
* is too small.
*/
char input[12] = "\xe1\x80\xa1" "AAAAAAAAA";
char *inptr = input;
size_t insize = sizeof (input);
char output[6];
char *outptr = output;
size_t outsize = sizeof (output);
TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1);
TEST_VERIFY (errno == E2BIG);
TEST_VERIFY_EXIT (iconv_close (cd) != -1);
return 0;
}
#include <support/test-driver.c>
+284
View File
@@ -0,0 +1,284 @@
#!/bin/bash
# Test for some known iconv(1) hangs from bug 19519, and miscellaneous
# iconv(1) program error conditions.
# Copyright (C) 2020 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/>.
codir=$1
test_wrapper_env="$2"
run_program_env="$3"
# We have to have some directories in the library path.
LIBPATH=$codir:$codir/iconvdata
# How the start the iconv(1) program. $from is not defined/expanded yet.
ICONV='
$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so
$codir/iconv/iconv_prog
'
ICONV="$test_wrapper_env $run_program_env $ICONV"
# List of known hangs;
# Gathered by running an exhaustive 2 byte input search against glibc-2.28
hangarray=(
"\x00\x23;-c;ANSI_X3.110;UTF-8//TRANSLIT//IGNORE"
"\x00\xa1;-c;ARMSCII-8;UTF-8//TRANSLIT//IGNORE"
"\x00\xa1;-c;ASMO_449;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;BIG5;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BIG5HKSCS;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BRF;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BS_4730;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1250;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;CP1251;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1252;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1253;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1254;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1255;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1257;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1258;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CP932;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CSA_Z243.4-1985-1;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CSA_Z243.4-1985-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DEC-MCS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DIN_66003;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DS_2089;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-AT-DE;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-AT-DE-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-CA-FR;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-DK-NO;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-DK-NO-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES-S;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FI-SE;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FI-SE-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FR;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-IS-FRISS;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-IT;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-PT;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-UK;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-US;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ES;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ES2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-CN;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JISX0213;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JP;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JP-MS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-KR;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-TW;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GB18030;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GB_1988-80;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GBK;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GOST_19768-74;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK7;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK7-OLD;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK-CCITT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-GREEK8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-ROMAN8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-ROMAN9;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-THAI8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-TURKISH8;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM038;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM1004;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;IBM1008;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM1046;UTF-8//TRANSLIT//IGNORE"
"\x00\x51;-c;IBM1132;UTF-8//TRANSLIT//IGNORE"
"\x00\xa0;-c;IBM1133;UTF-8//TRANSLIT//IGNORE"
"\x00\xce;-c;IBM1137;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE"
"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE"
"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE"
"\x00\x0f;-c;IBM1364;UTF-8"
"\x0e\x0e;-c;IBM1364;UTF-8"
"\x00\x0f;-c;IBM1371;UTF-8"
"\x0e\x0e;-c;IBM1371;UTF-8"
"\x00\x0f;-c;IBM1388;UTF-8"
"\x0e\x0e;-c;IBM1388;UTF-8"
"\x00\x0f;-c;IBM1390;UTF-8"
"\x0e\x0e;-c;IBM1390;UTF-8"
"\x00\x0f;-c;IBM1399;UTF-8"
"\x0e\x0e;-c;IBM1399;UTF-8"
"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM281;UTF-8//TRANSLIT//IGNORE"
"\x00\x57;-c;IBM290;UTF-8//TRANSLIT//IGNORE"
"\x00\x45;-c;IBM420;UTF-8//TRANSLIT//IGNORE"
"\x00\x68;-c;IBM423;UTF-8//TRANSLIT//IGNORE"
"\x00\x70;-c;IBM424;UTF-8//TRANSLIT//IGNORE"
"\x00\x53;-c;IBM4517;UTF-8//TRANSLIT//IGNORE"
"\x00\x53;-c;IBM4899;UTF-8//TRANSLIT//IGNORE"
"\x00\xa5;-c;IBM4909;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;IBM4971;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM803;UTF-8//TRANSLIT//IGNORE"
"\x00\x91;-c;IBM851;UTF-8//TRANSLIT//IGNORE"
"\x00\x9b;-c;IBM856;UTF-8//TRANSLIT//IGNORE"
"\x00\xd5;-c;IBM857;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM864;UTF-8//TRANSLIT//IGNORE"
"\x00\x94;-c;IBM868;UTF-8//TRANSLIT//IGNORE"
"\x00\x94;-c;IBM869;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM874;UTF-8//TRANSLIT//IGNORE"
"\x00\x6a;-c;IBM875;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM880;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM891;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM903;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM904;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM905;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM9066;UTF-8//TRANSLIT//IGNORE"
"\x00\x48;-c;IBM918;UTF-8//TRANSLIT//IGNORE"
"\x00\x57;-c;IBM930;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM932;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM933;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM935;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM937;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM939;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM943;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS-8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS-CYRILLIC;UTF-8//TRANSLIT//IGNORE"
"\x00\xec;-c;ISIRI-3342;UTF-8//TRANSLIT//IGNORE"
"\x00\xec;-c;ISO_10367-BOX;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-CN;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-CN-EXT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP-3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-KR;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_2033;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5427;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5427-EXT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5428;UTF-8//TRANSLIT//IGNORE"
"\x00\xa4;-c;ISO_6937;UTF-8//TRANSLIT//IGNORE"
"\x00\xa0;-c;ISO_6937-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-11;UTF-8//TRANSLIT//IGNORE"
"\x00\xa5;-c;ISO-8859-3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-6;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-7;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-8;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;ISO-IR-197;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;ISO-IR-209;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IT;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JIS_C6220-1969-RO;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JIS_C6229-1984-B;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JOHAB;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JUS_I.B1.002;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;KOI-8;UTF-8//TRANSLIT//IGNORE"
"\x00\x88;-c;KOI8-T;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;KSC5636;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;LATIN-GREEK;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;LATIN-GREEK-1;UTF-8//TRANSLIT//IGNORE"
"\x00\xf6;-c;MAC-IS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;MSZ_7795.3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NATS-DANO;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NATS-SEFI;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NC_NC00-10;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NF_Z_62-010;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NF_Z_62-010_1973;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NS_4551-1;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NS_4551-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;PT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;PT2;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;RK1048;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;SEN_850200_B;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;SEN_850200_C;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;Shift_JISX0213;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;SJIS;UTF-8//TRANSLIT//IGNORE"
"\x00\x23;-c;T.61-8BIT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;TIS-620;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;TSCII;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;UHC;UTF-8//TRANSLIT//IGNORE"
"\x00\xd8;-c;UNICODE;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;UTF-16;UTF-8//TRANSLIT//IGNORE"
"\xdc\x00;-c;UTF-16BE;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;UTF-16LE;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;UTF-7;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;WIN-SAMI-2;UTF-8//TRANSLIT//IGNORE"
)
# List of option combinations that *should* lead to an error
errorarray=(
# Converting from/to invalid character sets should cause error
"\x00\x00;;INVALID;INVALID"
"\x00\x00;;INVALID;UTF-8"
"\x00\x00;;UTF-8;INVALID"
)
# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret
execute_test ()
{
eval PROG=\"$ICONV\"
echo -en "$twobyte" \
| timeout -k 4 3 $PROG $c -f $from -t "$to" &>/dev/null
ret=$?
}
check_hangtest_result ()
{
if [ "$ret" -eq "124" ] || [ "$ret" -eq "137" ]; then # timeout/hang
result="HANG"
else
if [ "$ret" -eq "139" ]; then # segfault
result="SEGFAULT"
else
if [ "$ret" -gt "127" ]; then # unexpected error
result="UNEXPECTED"
else
result="OK"
fi
fi
fi
echo -n "$result: from: \"$from\", to: \"$to\","
echo " input \"$twobyte\", flags \"$c\""
if [ "$result" != "OK" ]; then
exit 1
fi
}
for hangcommand in "${hangarray[@]}"; do
twobyte="$(echo "$hangcommand" | cut -d";" -f 1)"
c="$(echo "$hangcommand" | cut -d";" -f 2)"
from="$(echo "$hangcommand" | cut -d";" -f 3)"
to="$(echo "$hangcommand" | cut -d";" -f 4)"
execute_test
check_hangtest_result
done
check_errtest_result ()
{
if [ "$ret" -eq "1" ]; then # we errored out as expected
result="PASS"
else
result="FAIL"
fi
echo -n "$result: from: \"$from\", to: \"$to\","
echo " input \"$twobyte\", flags \"$c\", return code $ret"
if [ "$result" != "PASS" ]; then
exit 1
fi
}
for errorcommand in "${errorarray[@]}"; do
twobyte="$(echo "$errorcommand" | cut -d";" -f 1)"
c="$(echo "$errorcommand" | cut -d";" -f 2)"
from="$(echo "$errorcommand" | cut -d";" -f 3)"
to="$(echo "$errorcommand" | cut -d";" -f 4)"
execute_test
check_errtest_result
done
+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>
+2 -12
View File
@@ -158,24 +158,14 @@ enum
\
if (__builtin_expect (ch, 0) == SO) \
{ \
/* Shift OUT, change to DBCS converter. */ \
if (curcs == db) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
/* Shift OUT, change to DBCS converter (redundant escape okay). */ \
curcs = db; \
++inptr; \
continue; \
} \
if (__builtin_expect (ch, 0) == SI) \
{ \
/* Shift IN, change to SBCS converter. */ \
if (curcs == sb) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
/* Shift IN, change to SBCS converter (redundant escape okay). */ \
curcs = sb; \
++inptr; \
continue; \
+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; \
+1
View File
@@ -4,6 +4,7 @@
# ifndef _ISOMAC
extern int __prctl (int __option, ...);
libc_hidden_proto (__prctl)
# endif /* !_ISOMAC */
#endif
+5
View File
@@ -83,6 +83,11 @@ _IO_check_libio (void)
= 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);
}
}
+1
View File
@@ -128,6 +128,7 @@ t_fmt_ampm "<U0F46><U0F74><U0F0B><U0F5A><U0F7C><U0F51>/
<U0025><U0070>"
week 7;19971130;1
first_weekday 2
END LC_TIME
LC_MESSAGES
+1
View File
@@ -165,6 +165,7 @@ am_pm "";""
date_fmt "%a<U060C> %d-%m-%Y<U060C> %T"
week 7;19971130;1
first_weekday 2
END LC_TIME
LC_MESSAGES
+1
View File
@@ -139,6 +139,7 @@ t_fmt_ampm "%p %I<U65F6>%M<U5206>%S<U79D2>"
date_fmt "%Y<U5E74> %m<U6708> %d<U65E5> %A %H:%M:%S %Z"
week 7;19971130;1
first_weekday 2
END LC_TIME
LC_MESSAGES
+5 -1
View File
@@ -43,7 +43,8 @@ endif
subdir-dirs = programs
vpath %.c programs
tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin
tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
tst-pututxline-lockfail tst-pututxline-cache
# Build the -lutil library with these extra functions.
extra-libs := libutil
@@ -71,3 +72,6 @@ endif
$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
$(make-target-directory)
-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
$(objpfx)tst-pututxline-lockfail: $(shared-thread-library)
$(objpfx)tst-pututxline-cache: $(shared-thread-library)
+4 -104
View File
@@ -23,115 +23,16 @@
#include "utmp-private.h"
/* Functions defined here. */
static int setutent_unknown (void);
static int getutent_r_unknown (struct utmp *buffer, struct utmp **result);
static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer,
struct utmp **result);
static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer,
struct utmp **result);
static struct utmp *pututline_unknown (const struct utmp *data);
static void endutent_unknown (void);
/* Initial Jump table. */
const struct utfuncs __libc_utmp_unknown_functions =
{
setutent_unknown,
getutent_r_unknown,
getutid_r_unknown,
getutline_r_unknown,
pututline_unknown,
endutent_unknown,
NULL
};
/* Currently selected backend. */
const struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
/* We need to protect the opening of the file. */
__libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden)
static int
setutent_unknown (void)
{
int result;
result = (*__libc_utmp_file_functions.setutent) ();
if (result)
__libc_utmp_jump_table = &__libc_utmp_file_functions;
return result;
}
static int
getutent_r_unknown (struct utmp *buffer, struct utmp **result)
{
/* The backend was not yet initialized. */
if (setutent_unknown ())
return (*__libc_utmp_jump_table->getutent_r) (buffer, result);
/* Not available. */
*result = NULL;
return -1;
}
static int
getutid_r_unknown (const struct utmp *id, struct utmp *buffer,
struct utmp **result)
{
/* The backend was not yet initialized. */
if (setutent_unknown ())
return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
/* Not available. */
*result = NULL;
return -1;
}
static int
getutline_r_unknown (const struct utmp *line, struct utmp *buffer,
struct utmp **result)
{
/* The backend was not yet initialized. */
if (setutent_unknown ())
return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
/* Not available. */
*result = NULL;
return -1;
}
static struct utmp *
pututline_unknown (const struct utmp *data)
{
/* The backend was not yet initialized. */
if (setutent_unknown ())
return (*__libc_utmp_jump_table->pututline) (data);
/* Not available. */
return NULL;
}
static void
endutent_unknown (void)
{
/* Nothing to do. */
}
void
__setutent (void)
{
__libc_lock_lock (__libc_utmp_lock);
(*__libc_utmp_jump_table->setutent) ();
__libc_setutent ();
__libc_lock_unlock (__libc_utmp_lock);
}
@@ -145,7 +46,7 @@ __getutent_r (struct utmp *buffer, struct utmp **result)
__libc_lock_lock (__libc_utmp_lock);
retval = (*__libc_utmp_jump_table->getutent_r) (buffer, result);
retval = __libc_getutent_r (buffer, result);
__libc_lock_unlock (__libc_utmp_lock);
@@ -162,7 +63,7 @@ __pututline (const struct utmp *data)
__libc_lock_lock (__libc_utmp_lock);
buffer = (*__libc_utmp_jump_table->pututline) (data);
buffer = __libc_pututline (data);
__libc_lock_unlock (__libc_utmp_lock);
@@ -177,8 +78,7 @@ __endutent (void)
{
__libc_lock_lock (__libc_utmp_lock);
(*__libc_utmp_jump_table->endutent) ();
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
__libc_endutent ();
__libc_lock_unlock (__libc_utmp_lock);
}
+1 -6
View File
@@ -32,7 +32,6 @@ __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
int
__getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
{
#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0)
int retval;
/* Test whether ID has any of the legal types. */
@@ -49,15 +48,11 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
__libc_lock_lock (__libc_utmp_lock);
retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result);
retval = __libc_getutid_r (id, buffer, result);
__libc_lock_unlock (__libc_utmp_lock);
return retval;
#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */
__set_errno (ENOSYS);
return -1;
#endif
}
libc_hidden_def (__getutid_r)
weak_alias (__getutid_r, getutid_r)
+1 -1
View File
@@ -36,7 +36,7 @@ __getutline_r (const struct utmp *line, struct utmp *buffer,
__libc_lock_lock (__libc_utmp_lock);
retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result);
retval = __libc_getutline_r (line, buffer, result);
__libc_lock_unlock (__libc_utmp_lock);
-12
View File
@@ -23,23 +23,11 @@
void
getutmp (const struct utmpx *utmpx, struct utmp *utmp)
{
#if _HAVE_UT_TYPE - 0
utmp->ut_type = utmpx->ut_type;
#endif
#if _HAVE_UT_PID - 0
utmp->ut_pid = utmpx->ut_pid;
#endif
memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line));
memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user));
#if _HAVE_UT_ID - 0
memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id));
#endif
#if _HAVE_UT_HOST - 0
memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host));
#endif
#if _HAVE_UT_TV - 0
utmp->ut_tv = utmpx->ut_tv;
#else
utmp->ut_time = utmpx->ut_time;
#endif
}
-13
View File
@@ -24,24 +24,11 @@ void
getutmpx (const struct utmp *utmp, struct utmpx *utmpx)
{
memset (utmpx, 0, sizeof (struct utmpx));
#if _HAVE_UT_TYPE - 0
utmpx->ut_type = utmp->ut_type;
#endif
#if _HAVE_UT_PID - 0
utmpx->ut_pid = utmp->ut_pid;
#endif
memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line));
memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user));
#if _HAVE_UT_ID - 0
memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id));
#endif
#if _HAVE_UT_HOST - 0
memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host));
#endif
#if _HAVE_UT_TV - 0
utmpx->ut_tv = utmp->ut_tv;
#else
utmpx->ut_time = utmp->ut_time;
#endif
}
-4
View File
@@ -91,12 +91,8 @@ login (const struct utmp *ut)
struct utmp copy = *ut;
/* Fill in those fields we supply. */
#if _HAVE_UT_TYPE - 0
copy.ut_type = USER_PROCESS;
#endif
#if _HAVE_UT_PID - 0
copy.ut_pid = getpid ();
#endif
/* Seek tty. */
found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty));
-10
View File
@@ -36,9 +36,7 @@ logout (const char *line)
setutent ();
/* Fill in search information. */
#if _HAVE_UT_TYPE - 0
tmp.ut_type = USER_PROCESS;
#endif
strncpy (tmp.ut_line, line, sizeof tmp.ut_line);
/* Read the record. */
@@ -46,20 +44,12 @@ logout (const char *line)
{
/* Clear information about who & from where. */
memset (ut->ut_name, '\0', sizeof ut->ut_name);
#if _HAVE_UT_HOST - 0
memset (ut->ut_host, '\0', sizeof ut->ut_host);
#endif
#if _HAVE_UT_TV - 0
struct timeval tv;
__gettimeofday (&tv, NULL);
ut->ut_tv.tv_sec = tv.tv_sec;
ut->ut_tv.tv_usec = tv.tv_usec;
#else
ut->ut_time = time (NULL);
#endif
#if _HAVE_UT_TYPE - 0
ut->ut_type = DEAD_PROCESS;
#endif
if (pututline (ut) != NULL)
result = 1;
-10
View File
@@ -30,26 +30,16 @@ logwtmp (const char *line, const char *name, const char *host)
/* Set information in new entry. */
memset (&ut, 0, sizeof (ut));
#if _HAVE_UT_PID - 0
ut.ut_pid = getpid ();
#endif
#if _HAVE_UT_TYPE - 0
ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS;
#endif
strncpy (ut.ut_line, line, sizeof ut.ut_line);
strncpy (ut.ut_name, name, sizeof ut.ut_name);
#if _HAVE_UT_HOST - 0
strncpy (ut.ut_host, host, sizeof ut.ut_host);
#endif
#if _HAVE_UT_TV - 0
struct timeval tv;
__gettimeofday (&tv, NULL);
ut.ut_tv.tv_sec = tv.tv_sec;
ut.ut_tv.tv_usec = tv.tv_usec;
#else
ut.ut_time = time (NULL);
#endif
updwtmp (_PATH_WTMP, &ut);
}
+5 -41
View File
@@ -37,47 +37,11 @@ print_entry (struct utmp *up)
temp_tv.tv_sec = up->ut_tv.tv_sec;
temp_tv.tv_usec = up->ut_tv.tv_usec;
(printf) (
/* The format string. */
#if _HAVE_UT_TYPE
"[%d] "
#endif
#if _HAVE_UT_PID
"[%05d] "
#endif
#if _HAVE_UT_ID
"[%-4.4s] "
#endif
"[%-8.8s] [%-12.12s]"
#if _HAVE_UT_HOST
" [%-16.16s]"
#endif
" [%-15.15s]"
#if _HAVE_UT_TV
" [%ld]"
#endif
"\n"
/* The arguments. */
#if _HAVE_UT_TYPE
, up->ut_type
#endif
#if _HAVE_UT_PID
, up->ut_pid
#endif
#if _HAVE_UT_ID
, up->ut_id
#endif
, up->ut_user, up->ut_line
#if _HAVE_UT_HOST
, up->ut_host
#endif
#if _HAVE_UT_TV
, 4 + ctime (&temp_tv.tv_sec)
, (long int) temp_tv.tv_usec
#else
, 4 + ctime (&up->ut_time)
#endif
);
printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-16.16s] [%-15.15s]"
" [%ld]\n",
up->ut_type, up->ut_pid, up->ut_id, up->ut_user, up->ut_line,
up->ut_host, 4 + ctime (&temp_tv.tv_sec),
(long int) temp_tv.tv_usec);
}
int
+193
View File
@@ -0,0 +1,193 @@
/* Test case for cache invalidation after concurrent write (bug 24882).
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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
/* This test writes an entry to the utmpx file, reads it (so that it
is cached) in process1, and overwrites the same entry in process2
with something that does not match the search criteria. At this
point, the cache of the first process is stale, and when process1
attempts to write a new record which would have gone to the same
place (as indicated by the cache), it needs to realize that it has
to pick a different slot because the old slot is now used for
something else. */
#include <errno.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/xthread.h>
#include <support/xunistd.h>
#include <utmp.h>
#include <utmpx.h>
/* Set to the path of the utmp file. */
static char *utmp_file;
/* Used to synchronize the subprocesses. The barrier itself is
allocated in shared memory. */
static pthread_barrier_t *barrier;
/* setutxent with error checking. */
static void
xsetutxent (void)
{
errno = 0;
setutxent ();
TEST_COMPARE (errno, 0);
}
/* getutxent with error checking. */
static struct utmpx *
xgetutxent (void)
{
errno = 0;
struct utmpx *result = getutxent ();
if (result == NULL)
FAIL_EXIT1 ("getutxent: %m");
return result;
}
static void
put_entry (const char *id, pid_t pid, const char *user, const char *line)
{
struct utmpx ut =
{
.ut_type = LOGIN_PROCESS,
.ut_pid = pid,
.ut_host = "localhost",
};
strcpy (ut.ut_id, id);
strncpy (ut.ut_user, user, sizeof (ut.ut_user));
strncpy (ut.ut_line, line, sizeof (ut.ut_line));
TEST_VERIFY (pututxline (&ut) != NULL);
}
/* Use two cooperating subprocesses to avoid issues related to
unlock-on-close semantics of POSIX advisory locks. */
static __attribute__ ((noreturn)) void
process1 (void)
{
TEST_COMPARE (utmpname (utmp_file), 0);
/* Create an entry. */
xsetutxent ();
put_entry ("1", 101, "root", "process1");
/* Retrieve the entry. This will fill the internal cache. */
{
errno = 0;
setutxent ();
TEST_COMPARE (errno, 0);
struct utmpx ut =
{
.ut_type = LOGIN_PROCESS,
.ut_line = "process1",
};
struct utmpx *result = getutxline (&ut);
if (result == NULL)
FAIL_EXIT1 ("getutxline (\"process1\"): %m");
TEST_COMPARE (result->ut_pid, 101);
}
/* Signal the other process to overwrite the entry. */
xpthread_barrier_wait (barrier);
/* Wait for the other process to complete the write operation. */
xpthread_barrier_wait (barrier);
/* Add another entry. Note: This time, there is no setutxent call. */
put_entry ("1", 103, "root", "process1");
_exit (0);
}
static void
process2 (void *closure)
{
/* Wait for the first process to write its entry. */
xpthread_barrier_wait (barrier);
/* Truncate the file. The glibc interface does not support
re-purposing records, but an external expiration mechanism may
trigger this. */
TEST_COMPARE (truncate64 (utmp_file, 0), 0);
/* Write the replacement entry. */
TEST_COMPARE (utmpname (utmp_file), 0);
xsetutxent ();
put_entry ("2", 102, "user", "process2");
/* Signal the other process that the entry has been replaced. */
xpthread_barrier_wait (barrier);
}
static int
do_test (void)
{
xclose (create_temp_file ("tst-tumpx-cache-write-", &utmp_file));
{
pthread_barrierattr_t attr;
xpthread_barrierattr_init (&attr);
xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS);
barrier = support_shared_allocate (sizeof (*barrier));
xpthread_barrier_init (barrier, &attr, 2);
}
/* Run both subprocesses in parallel. */
{
pid_t pid1 = xfork ();
if (pid1 == 0)
process1 ();
support_isolate_in_subprocess (process2, NULL);
int status;
xwaitpid (pid1, &status, 0);
TEST_COMPARE (status, 0);
}
/* Check that the utmpx database contains the expected records. */
{
TEST_COMPARE (utmpname (utmp_file), 0);
xsetutxent ();
struct utmpx *ut = xgetutxent ();
TEST_COMPARE_STRING (ut->ut_id, "2");
TEST_COMPARE (ut->ut_pid, 102);
TEST_COMPARE_STRING (ut->ut_user, "user");
TEST_COMPARE_STRING (ut->ut_line, "process2");
ut = xgetutxent ();
TEST_COMPARE_STRING (ut->ut_id, "1");
TEST_COMPARE (ut->ut_pid, 103);
TEST_COMPARE_STRING (ut->ut_user, "root");
TEST_COMPARE_STRING (ut->ut_line, "process1");
if (getutxent () != NULL)
FAIL_EXIT1 ("additional utmpx entry");
}
xpthread_barrier_destroy (barrier);
support_shared_free (barrier);
free (utmp_file);
return 0;
}
#include <support/test-driver.c>
+176
View File
@@ -0,0 +1,176 @@
/* Test the lock upgrade path in tst-pututxline.
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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
/* pututxline upgrades the read lock on the file to a write lock.
This test verifies that if the lock upgrade fails, the utmp
subsystem remains in a consistent state, so that pututxline can be
called again. */
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/xthread.h>
#include <support/xunistd.h>
#include <unistd.h>
#include <utmp.h>
#include <utmpx.h>
/* Path to the temporary utmp file. */
static char *path;
/* Used to synchronize the subprocesses. The barrier itself is
allocated in shared memory. */
static pthread_barrier_t *barrier;
/* Use pututxline to write an entry for PID. */
static struct utmpx *
write_entry (pid_t pid)
{
struct utmpx ut =
{
.ut_type = LOGIN_PROCESS,
.ut_id = "1",
.ut_user = "root",
.ut_pid = pid,
.ut_line = "entry",
.ut_host = "localhost",
};
return pututxline (&ut);
}
/* Create the initial entry in a subprocess, so that the utmp
subsystem in the original process is not disturbed. */
static void
subprocess_create_entry (void *closure)
{
TEST_COMPARE (utmpname (path), 0);
TEST_VERIFY (write_entry (101) != NULL);
}
/* Acquire an advisory read lock on PATH. */
__attribute__ ((noreturn)) static void
subprocess_lock_file (void)
{
int fd = xopen (path, O_RDONLY, 0);
struct flock64 fl =
{
.l_type = F_RDLCK,
fl.l_whence = SEEK_SET,
};
TEST_COMPARE (fcntl64 (fd, F_SETLKW, &fl), 0);
/* Signal to the main process that the lock has been acquired. */
xpthread_barrier_wait (barrier);
/* Wait for the unlock request from the main process. */
xpthread_barrier_wait (barrier);
/* Implicitly unlock the file. */
xclose (fd);
/* Overwrite the existing entry. */
TEST_COMPARE (utmpname (path), 0);
errno = 0;
setutxent ();
TEST_COMPARE (errno, 0);
TEST_VERIFY (write_entry (102) != NULL);
errno = 0;
endutxent ();
TEST_COMPARE (errno, 0);
_exit (0);
}
static int
do_test (void)
{
xclose (create_temp_file ("tst-pututxline-lockfail-", &path));
{
pthread_barrierattr_t attr;
xpthread_barrierattr_init (&attr);
xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS);
barrier = support_shared_allocate (sizeof (*barrier));
xpthread_barrier_init (barrier, &attr, 2);
xpthread_barrierattr_destroy (&attr);
}
/* Write the initial entry. */
support_isolate_in_subprocess (subprocess_create_entry, NULL);
pid_t locker_pid = xfork ();
if (locker_pid == 0)
subprocess_lock_file ();
/* Wait for the file locking to complete. */
xpthread_barrier_wait (barrier);
/* Try to add another entry. This attempt will fail, with EINTR or
EAGAIN. */
TEST_COMPARE (utmpname (path), 0);
TEST_VERIFY (write_entry (102) == NULL);
if (errno != EINTR)
TEST_COMPARE (errno, EAGAIN);
/* Signal the subprocess to overwrite the entry. */
xpthread_barrier_wait (barrier);
/* Wait for write and unlock to complete. */
{
int status;
xwaitpid (locker_pid, &status, 0);
TEST_COMPARE (status, 0);
}
/* The file is no longer locked, so this operation will succeed. */
TEST_VERIFY (write_entry (103) != NULL);
errno = 0;
endutxent ();
TEST_COMPARE (errno, 0);
/* Check that there is just one entry with the expected contents.
If pututxline becomes desynchronized internally, the entry is not
overwritten (bug 24902). */
errno = 0;
setutxent ();
TEST_COMPARE (errno, 0);
struct utmpx *ut = getutxent ();
TEST_VERIFY_EXIT (ut != NULL);
TEST_COMPARE (ut->ut_type, LOGIN_PROCESS);
TEST_COMPARE_STRING (ut->ut_id, "1");
TEST_COMPARE_STRING (ut->ut_user, "root");
TEST_COMPARE (ut->ut_pid, 103);
TEST_COMPARE_STRING (ut->ut_line, "entry");
TEST_COMPARE_STRING (ut->ut_host, "localhost");
TEST_VERIFY (getutxent () == NULL);
errno = 0;
endutxent ();
TEST_COMPARE (errno, 0);
xpthread_barrier_destroy (barrier);
support_shared_free (barrier);
free (path);
return 0;
}
#include <support/test-driver.c>
+112
View File
@@ -0,0 +1,112 @@
/* Basic test coverage for updwtmpx.
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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
/* This program runs a series of tests. Each one calls updwtmpx
twice, to write two records, optionally with misalignment in the
file, and reads back the results. */
#include <errno.h>
#include <stdlib.h>
#include <support/check.h>
#include <support/descriptors.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <support/xunistd.h>
#include <unistd.h>
#include <utmpx.h>
static int
do_test (void)
{
/* Two entries filled with an arbitrary bit pattern. */
struct utmpx entries[2];
unsigned char pad;
{
unsigned char *p = (unsigned char *) &entries[0];
for (size_t i = 0; i < sizeof (entries); ++i)
{
p[i] = i;
}
/* Make sure that the first and second entry and the padding are
different. */
p[sizeof (struct utmpx)] = p[0] + 1;
pad = p[0] + 2;
}
char *path;
int fd = create_temp_file ("tst-updwtmpx-", &path);
/* Used to check that updwtmpx does not leave an open file
descriptor around. */
struct support_descriptors *descriptors = support_descriptors_list ();
/* updwtmpx is expected to remove misalignment. Optionally insert
one byte of misalignment at the start and in the middle (after
the first entry). */
for (int misaligned_start = 0; misaligned_start < 2; ++misaligned_start)
for (int misaligned_middle = 0; misaligned_middle < 2; ++misaligned_middle)
{
if (test_verbose > 0)
printf ("info: misaligned_start=%d misaligned_middle=%d\n",
misaligned_start, misaligned_middle);
xftruncate (fd, 0);
TEST_COMPARE (pwrite64 (fd, &pad, misaligned_start, 0),
misaligned_start);
/* Write first entry and check it. */
errno = 0;
updwtmpx (path, &entries[0]);
TEST_COMPARE (errno, 0);
support_descriptors_check (descriptors);
TEST_COMPARE (xlseek (fd, 0, SEEK_END), sizeof (struct utmpx));
struct utmpx buffer;
TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0),
sizeof (buffer));
TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]),
&buffer, sizeof (buffer));
/* Middle mis-alignmet. */
TEST_COMPARE (pwrite64 (fd, &pad, misaligned_middle,
sizeof (struct utmpx)), misaligned_middle);
/* Write second entry and check both entries. */
errno = 0;
updwtmpx (path, &entries[1]);
TEST_COMPARE (errno, 0);
support_descriptors_check (descriptors);
TEST_COMPARE (xlseek (fd, 0, SEEK_END), 2 * sizeof (struct utmpx));
TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0),
sizeof (buffer));
TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]),
&buffer, sizeof (buffer));
TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), sizeof (buffer)),
sizeof (buffer));
TEST_COMPARE_BLOB (&entries[1], sizeof (entries[1]),
&buffer, sizeof (buffer));
}
support_descriptors_free (descriptors);
free (path);
xclose (fd);
return 0;
}
#include <support/test-driver.c>
-25
View File
@@ -39,8 +39,6 @@
#endif
#if defined UTMPX || _HAVE_UT_TYPE
/* Prototype for our test function. */
static int do_test (int argc, char *argv[]);
@@ -75,11 +73,7 @@ do_prepare (int argc, char *argv[])
struct utmp entry[] =
{
#if defined UTMPX || _HAVE_UT_TV
#define UT(a) .ut_tv = { .tv_sec = (a)}
#else
#define UT(a) .ut_time = (a)
#endif
{ .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
{ .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
@@ -167,11 +161,7 @@ simulate_login (const char *line, const char *user)
entry[n].ut_pid = (entry_pid += 27);
entry[n].ut_type = USER_PROCESS;
strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
#if defined UTMPX || _HAVE_UT_TV - 0
entry[n].ut_tv.tv_sec = (entry_time += 1000);
#else
entry[n].ut_time = (entry_time += 1000);
#endif
setutent ();
if (pututline (&entry[n]) == NULL)
@@ -201,11 +191,7 @@ simulate_logout (const char *line)
{
entry[n].ut_type = DEAD_PROCESS;
strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
#if defined UTMPX || _HAVE_UT_TV - 0
entry[n].ut_tv.tv_sec = (entry_time += 1000);
#else
entry[n].ut_time = (entry_time += 1000);
#endif
setutent ();
if (pututline (&entry[n]) == NULL)
@@ -390,14 +376,3 @@ do_test (int argc, char *argv[])
return result;
}
#else
/* No field 'ut_type' in struct utmp. */
int
main (void)
{
return 0;
}
#endif
+1 -1
View File
@@ -29,7 +29,7 @@ __updwtmp (const char *wtmp_file, const struct utmp *utmp)
{
const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file);
(*__libc_utmp_file_functions.updwtmp) (file_name, utmp);
__libc_updwtmp (file_name, utmp);
}
libc_hidden_def (__updwtmp)
weak_alias (__updwtmp, updwtmp)
+11 -18
View File
@@ -24,24 +24,17 @@
#include <utmp.h>
#include <libc-lock.h>
/* The structure describing the functions in a backend. */
struct utfuncs
{
int (*setutent) (void);
int (*getutent_r) (struct utmp *, struct utmp **);
int (*getutid_r) (const struct utmp *, struct utmp *, struct utmp **);
int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **);
struct utmp *(*pututline) (const struct utmp *);
void (*endutent) (void);
int (*updwtmp) (const char *, const struct utmp *);
};
/* The tables from the services. */
extern const struct utfuncs __libc_utmp_file_functions attribute_hidden;
extern const struct utfuncs __libc_utmp_unknown_functions attribute_hidden;
/* Currently selected backend. */
extern const struct utfuncs *__libc_utmp_jump_table attribute_hidden;
/* These functions check for initialization, but not perform any
locking. */
int __libc_setutent (void) attribute_hidden;
int __libc_getutent_r (struct utmp *, struct utmp **) attribute_hidden;
int __libc_getutid_r (const struct utmp *, struct utmp *, struct utmp **)
attribute_hidden;
int __libc_getutline_r (const struct utmp *, struct utmp *, struct utmp **)
attribute_hidden;
struct utmp *__libc_pututline (const struct utmp *) attribute_hidden;
void __libc_endutent (void) attribute_hidden;
int __libc_updwtmp (const char *, const struct utmp *) attribute_hidden;
/* Current file name. */
extern const char *__libc_utmp_file_name attribute_hidden;
+252 -269
View File
@@ -43,6 +43,25 @@ static off64_t file_offset;
/* Cache for the last read entry. */
static struct utmp last_entry;
/* Returns true if *ENTRY matches last_entry, based on
data->ut_type. */
static bool
matches_last_entry (const struct utmp *data)
{
if (file_offset <= 0)
/* Nothing has been read. last_entry is stale and cannot match. */
return false;
if (data->ut_type == RUN_LVL
|| data->ut_type == BOOT_TIME
|| data->ut_type == OLD_TIME
|| data->ut_type == NEW_TIME)
/* For some entry types, only a type match is required. */
return data->ut_type == last_entry.ut_type;
else
/* For the process-related entries, a full match is needed. */
return __utmp_equal (&last_entry, data);
}
/* Locking timeout. */
#ifndef TIMEOUT
@@ -52,90 +71,70 @@ static struct utmp last_entry;
/* Do-nothing handler for locking timeout. */
static void timeout_handler (int signum) {};
/* LOCK_FILE(fd, type) failure_statement
attempts to get a lock on the utmp file referenced by FD. If it fails,
the failure_statement is executed, otherwise it is skipped.
LOCKING_FAILED()
jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE.
UNLOCK_FILE(fd)
unlocks the utmp file referenced by FD and performs the cleanup of
LOCK_FILE.
*/
#define LOCK_FILE(fd, type) \
{ \
struct flock fl; \
struct sigaction action, old_action; \
unsigned int old_timeout; \
\
/* Cancel any existing alarm. */ \
old_timeout = alarm (0); \
\
/* Establish signal handler. */ \
action.sa_handler = timeout_handler; \
__sigemptyset (&action.sa_mask); \
action.sa_flags = 0; \
__sigaction (SIGALRM, &action, &old_action); \
\
alarm (TIMEOUT); \
\
/* Try to get the lock. */ \
memset (&fl, '\0', sizeof (struct flock)); \
fl.l_type = (type); \
fl.l_whence = SEEK_SET; \
if (__fcntl64_nocancel ((fd), F_SETLKW, &fl) < 0)
#define LOCKING_FAILED() \
goto unalarm_return
/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking
operation failed and recovery needs to be performed.
#define UNLOCK_FILE(fd) \
/* Unlock the file. */ \
fl.l_type = F_UNLCK; \
__fcntl64_nocancel ((fd), F_SETLKW, &fl); \
\
unalarm_return: \
/* Reset the signal handler and alarm. We must reset the alarm \
before resetting the handler so our alarm does not generate a \
spurious SIGALRM seen by the user. However, we cannot just set \
the user's old alarm before restoring the handler, because then \
it's possible our handler could catch the user alarm's SIGARLM \
and then the user would never see the signal he expected. */ \
alarm (0); \
__sigaction (SIGALRM, &old_action, NULL); \
if (old_timeout != 0) \
alarm (old_timeout); \
} while (0)
file_unlock (FD) removes the lock (which must have been
successfully acquired). */
/* Functions defined here. */
static int setutent_file (void);
static int getutent_r_file (struct utmp *buffer, struct utmp **result);
static int getutid_r_file (const struct utmp *key, struct utmp *buffer,
struct utmp **result);
static int getutline_r_file (const struct utmp *key, struct utmp *buffer,
struct utmp **result);
static struct utmp *pututline_file (const struct utmp *data);
static void endutent_file (void);
static int updwtmp_file (const char *file, const struct utmp *utmp);
/* Jump table for file functions. */
const struct utfuncs __libc_utmp_file_functions =
static bool
try_file_lock (int fd, int type)
{
setutent_file,
getutent_r_file,
getutid_r_file,
getutline_r_file,
pututline_file,
endutent_file,
updwtmp_file
};
/* Cancel any existing alarm. */
int old_timeout = alarm (0);
/* Establish signal handler. */
struct sigaction old_action;
struct sigaction action;
action.sa_handler = timeout_handler;
__sigemptyset (&action.sa_mask);
action.sa_flags = 0;
__sigaction (SIGALRM, &action, &old_action);
alarm (TIMEOUT);
/* Try to get the lock. */
struct flock64 fl =
{
.l_type = type,
.l_whence = SEEK_SET,
};
bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
int saved_errno = errno;
/* Reset the signal handler and alarm. We must reset the alarm
before resetting the handler so our alarm does not generate a
spurious SIGALRM seen by the user. However, we cannot just set
the user's old alarm before restoring the handler, because then
it's possible our handler could catch the user alarm's SIGARLM and
then the user would never see the signal he expected. */
alarm (0);
__sigaction (SIGALRM, &old_action, NULL);
if (old_timeout != 0)
alarm (old_timeout);
__set_errno (saved_errno);
return status;
}
static void
file_unlock (int fd)
{
struct flock64 fl =
{
.l_type = F_UNLCK,
};
__fcntl64_nocancel (fd, F_SETLKW, &fl);
}
#ifndef TRANSFORM_UTMP_FILE_NAME
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
#endif
static int
setutent_file (void)
int
__libc_setutent (void)
{
if (file_fd < 0)
{
@@ -153,56 +152,68 @@ setutent_file (void)
__lseek64 (file_fd, 0, SEEK_SET);
file_offset = 0;
/* Make sure the entry won't match. */
#if _HAVE_UT_TYPE - 0
last_entry.ut_type = -1;
#else
last_entry.ut_line[0] = '\177';
# if _HAVE_UT_ID - 0
last_entry.ut_id[0] = '\0';
# endif
#endif
return 1;
}
static int
getutent_r_file (struct utmp *buffer, struct utmp **result)
/* Preform initialization if necessary. */
static bool
maybe_setutent (void)
{
ssize_t nbytes;
return file_fd >= 0 || __libc_setutent ();
}
assert (file_fd >= 0);
/* Reads the entry at file_offset, storing it in last_entry and
updating file_offset on success. Returns -1 for a read error, 0
for EOF, and 1 for a successful read. last_entry and file_offset
are only updated on a successful and complete read. */
static ssize_t
read_last_entry (void)
{
struct utmp buffer;
ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, sizeof (buffer),
file_offset);
if (nbytes < 0)
return -1;
else if (nbytes != sizeof (buffer))
/* Assume EOF. */
return 0;
else
{
last_entry = buffer;
file_offset += sizeof (buffer);
return 1;
}
}
if (file_offset == -1l)
int
__libc_getutent_r (struct utmp *buffer, struct utmp **result)
{
int saved_errno = errno;
if (!maybe_setutent ())
{
/* Not available. */
*result = NULL;
return -1;
}
LOCK_FILE (file_fd, F_RDLCK)
if (try_file_lock (file_fd, F_RDLCK))
return -1;
ssize_t nbytes = read_last_entry ();
file_unlock (file_fd);
if (nbytes <= 0) /* Read error or EOF. */
{
nbytes = 0;
LOCKING_FAILED ();
}
/* Read the next entry. */
nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
UNLOCK_FILE (file_fd);
if (nbytes != sizeof (struct utmp))
{
if (nbytes != 0)
file_offset = -1l;
if (nbytes == 0)
/* errno should be unchanged to indicate success. A premature
EOF is treated like an EOF (missing complete record at the
end). */
__set_errno (saved_errno);
*result = NULL;
return -1;
}
/* Update position pointer. */
file_offset += sizeof (struct utmp);
memcpy (buffer, &last_entry, sizeof (struct utmp));
*result = buffer;
@@ -210,82 +221,55 @@ getutent_r_file (struct utmp *buffer, struct utmp **result)
}
/* Search for *ID, updating last_entry and file_offset. Return 0 on
success and -1 on failure. Does not perform locking; for that see
internal_getut_r below. */
static int
internal_getut_r (const struct utmp *id, struct utmp *buffer,
bool *lock_failed)
internal_getut_nolock (const struct utmp *id)
{
int result = -1;
while (1)
{
ssize_t nbytes = read_last_entry ();
if (nbytes < 0)
return -1;
if (nbytes == 0)
{
/* End of file reached. */
__set_errno (ESRCH);
return -1;
}
LOCK_FILE (file_fd, F_RDLCK)
if (matches_last_entry (id))
break;
}
return 0;
}
/* Search for *ID, updating last_entry and file_offset. Return 0 on
success and -1 on failure. If the locking operation failed, write
true to *LOCK_FAILED. */
static int
internal_getut_r (const struct utmp *id, bool *lock_failed)
{
if (try_file_lock (file_fd, F_RDLCK))
{
*lock_failed = true;
LOCKING_FAILED ();
return -1;
}
#if _HAVE_UT_TYPE - 0
if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
|| id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
{
/* Search for next entry with type RUN_LVL, BOOT_TIME,
OLD_TIME, or NEW_TIME. */
while (1)
{
/* Read the next entry. */
if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
!= sizeof (struct utmp))
{
__set_errno (ESRCH);
file_offset = -1l;
goto unlock_return;
}
file_offset += sizeof (struct utmp);
if (id->ut_type == buffer->ut_type)
break;
}
}
else
#endif /* _HAVE_UT_TYPE */
{
/* Search for the next entry with the specified ID and with type
INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */
while (1)
{
/* Read the next entry. */
if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
!= sizeof (struct utmp))
{
__set_errno (ESRCH);
file_offset = -1l;
goto unlock_return;
}
file_offset += sizeof (struct utmp);
if (__utmp_equal (buffer, id))
break;
}
}
result = 0;
unlock_return:
UNLOCK_FILE (file_fd);
int result = internal_getut_nolock (id);
file_unlock (file_fd);
return result;
}
/* For implementing this function we don't use the getutent_r function
because we can avoid the reposition on every new entry this way. */
static int
getutid_r_file (const struct utmp *id, struct utmp *buffer,
struct utmp **result)
int
__libc_getutid_r (const struct utmp *id, struct utmp *buffer,
struct utmp **result)
{
assert (file_fd >= 0);
if (file_offset == -1l)
if (!maybe_setutent ())
{
*result = NULL;
return -1;
@@ -294,7 +278,7 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer,
/* We don't have to distinguish whether we can lock the file or
whether there is no entry. */
bool lock_failed = false;
if (internal_getut_r (id, &last_entry, &lock_failed) < 0)
if (internal_getut_r (id, &lock_failed) < 0)
{
*result = NULL;
return -1;
@@ -306,69 +290,65 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer,
return 0;
}
/* For implementing this function we don't use the getutent_r function
because we can avoid the reposition on every new entry this way. */
static int
getutline_r_file (const struct utmp *line, struct utmp *buffer,
struct utmp **result)
int
__libc_getutline_r (const struct utmp *line, struct utmp *buffer,
struct utmp **result)
{
assert (file_fd >= 0);
if (file_offset == -1l)
if (!maybe_setutent ())
{
*result = NULL;
return -1;
}
LOCK_FILE (file_fd, F_RDLCK)
if (try_file_lock (file_fd, F_RDLCK))
{
*result = NULL;
LOCKING_FAILED ();
return -1;
}
while (1)
{
/* Read the next entry. */
if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp))
!= sizeof (struct utmp))
ssize_t nbytes = read_last_entry ();
if (nbytes < 0)
{
__set_errno (ESRCH);
file_offset = -1l;
file_unlock (file_fd);
*result = NULL;
goto unlock_return;
return -1;
}
if (nbytes == 0)
{
/* End of file reached. */
file_unlock (file_fd);
__set_errno (ESRCH);
*result = NULL;
return -1;
}
file_offset += sizeof (struct utmp);
/* Stop if we found a user or login entry. */
if (
#if _HAVE_UT_TYPE - 0
(last_entry.ut_type == USER_PROCESS
if ((last_entry.ut_type == USER_PROCESS
|| last_entry.ut_type == LOGIN_PROCESS)
&&
#endif
!strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line))
&& (strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)
== 0))
break;
}
file_unlock (file_fd);
memcpy (buffer, &last_entry, sizeof (struct utmp));
*result = buffer;
unlock_return:
UNLOCK_FILE (file_fd);
return ((*result == NULL) ? -1 : 0);
return 0;
}
static struct utmp *
pututline_file (const struct utmp *data)
struct utmp *
__libc_pututline (const struct utmp *data)
{
struct utmp buffer;
struct utmp *pbuf;
int found;
if (!maybe_setutent ())
return NULL;
assert (file_fd >= 0);
struct utmp *pbuf;
if (! file_writable)
{
@@ -380,8 +360,7 @@ pututline_file (const struct utmp *data)
if (new_fd == -1)
return NULL;
if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1
|| __dup2 (new_fd, file_fd) < 0)
if (__dup2 (new_fd, file_fd) < 0)
{
__close_nocancel_nostatus (new_fd);
return NULL;
@@ -390,95 +369,96 @@ pututline_file (const struct utmp *data)
file_writable = true;
}
/* Find the correct place to insert the data. */
if (file_offset > 0
&& (
#if _HAVE_UT_TYPE - 0
(last_entry.ut_type == data->ut_type
&& (last_entry.ut_type == RUN_LVL
|| last_entry.ut_type == BOOT_TIME
|| last_entry.ut_type == OLD_TIME
|| last_entry.ut_type == NEW_TIME))
||
#endif
__utmp_equal (&last_entry, data)))
found = 1;
else
{
bool lock_failed = false;
found = internal_getut_r (data, &buffer, &lock_failed);
/* Exclude other writers before validating the cache. */
if (try_file_lock (file_fd, F_WRLCK))
return NULL;
if (__builtin_expect (lock_failed, false))
/* Find the correct place to insert the data. */
bool found = false;
if (matches_last_entry (data))
{
/* Read back the entry under the write lock. */
file_offset -= sizeof (last_entry);
ssize_t nbytes = read_last_entry ();
if (nbytes < 0)
{
__set_errno (EAGAIN);
file_unlock (file_fd);
return NULL;
}
if (nbytes == 0)
/* End of file reached. */
found = false;
else
found = matches_last_entry (data);
}
LOCK_FILE (file_fd, F_WRLCK)
{
pbuf = NULL;
LOCKING_FAILED ();
}
if (!found)
/* Search forward for the entry. */
found = internal_getut_nolock (data) >= 0;
if (found < 0)
off64_t write_offset;
if (!found)
{
/* We append the next entry. */
file_offset = __lseek64 (file_fd, 0, SEEK_END);
if (file_offset % sizeof (struct utmp) != 0)
{
file_offset -= file_offset % sizeof (struct utmp);
__ftruncate64 (file_fd, file_offset);
write_offset = __lseek64 (file_fd, 0, SEEK_END);
if (__lseek64 (file_fd, 0, SEEK_END) < 0)
{
pbuf = NULL;
goto unlock_return;
}
}
/* Round down to the next multiple of the entry size. This
ensures any partially-written record is overwritten by the
new record. */
write_offset = (write_offset / sizeof (struct utmp)
* sizeof (struct utmp));
}
else
{
/* We replace the just read entry. */
file_offset -= sizeof (struct utmp);
__lseek64 (file_fd, file_offset, SEEK_SET);
}
/* Overwrite last_entry. */
write_offset = file_offset - sizeof (struct utmp);
/* Write the new data. */
if (__write_nocancel (file_fd, data, sizeof (struct utmp))
!= sizeof (struct utmp))
ssize_t nbytes;
if (__lseek64 (file_fd, write_offset, SEEK_SET) < 0
|| (nbytes = __write_nocancel (file_fd, data, sizeof (struct utmp))) < 0)
{
/* There is no need to recover the file position because all
reads use pread64, and any future write is preceded by
another seek. */
file_unlock (file_fd);
return NULL;
}
if (nbytes != sizeof (struct utmp))
{
/* If we appended a new record this is only partially written.
Remove it. */
if (found < 0)
(void) __ftruncate64 (file_fd, file_offset);
pbuf = NULL;
}
else
{
file_offset += sizeof (struct utmp);
pbuf = (struct utmp *) data;
if (!found)
(void) __ftruncate64 (file_fd, write_offset);
file_unlock (file_fd);
/* Assume that the write failure was due to missing disk
space. */
__set_errno (ENOSPC);
return NULL;
}
unlock_return:
UNLOCK_FILE (file_fd);
file_unlock (file_fd);
file_offset = write_offset + sizeof (struct utmp);
pbuf = (struct utmp *) data;
return pbuf;
}
static void
endutent_file (void)
void
__libc_endutent (void)
{
assert (file_fd >= 0);
__close_nocancel_nostatus (file_fd);
file_fd = -1;
if (file_fd >= 0)
{
__close_nocancel_nostatus (file_fd);
file_fd = -1;
}
}
static int
updwtmp_file (const char *file, const struct utmp *utmp)
int
__libc_updwtmp (const char *file, const struct utmp *utmp)
{
int result = -1;
off64_t offset;
@@ -489,8 +469,11 @@ updwtmp_file (const char *file, const struct utmp *utmp)
if (fd < 0)
return -1;
LOCK_FILE (fd, F_WRLCK)
LOCKING_FAILED ();
if (try_file_lock (fd, F_WRLCK))
{
__close_nocancel_nostatus (fd);
return -1;
}
/* Remember original size of log file. */
offset = __lseek64 (fd, 0, SEEK_END);
@@ -516,7 +499,7 @@ updwtmp_file (const char *file, const struct utmp *utmp)
result = 0;
unlock_return:
UNLOCK_FILE (fd);
file_unlock (fd);
/* Close WTMP file. */
__close_nocancel_nostatus (fd);
+1 -2
View File
@@ -42,8 +42,7 @@ __utmpname (const char *file)
__libc_lock_lock (__libc_utmp_lock);
/* Close the old file. */
(*__libc_utmp_jump_table->endutent) ();
__libc_utmp_jump_table = &__libc_utmp_unknown_functions;
__libc_endutent ();
if (strcmp (file, __libc_utmp_file_name) != 0)
{
+4 -2
View File
@@ -27,7 +27,7 @@ headers := $(dist-headers) obstack.h mcheck.h
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-mcheck tst-mallocfork tst-trim1 \
tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \
tst-pvalloc tst-memalign tst-mallopt \
tst-pvalloc tst-pvalloc-fortify tst-memalign tst-mallopt \
tst-malloc-backtrace tst-malloc-thread-exit \
tst-malloc-thread-fail tst-malloc-fork-deadlock \
tst-mallocfork2 \
@@ -54,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
@@ -196,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
@@ -236,6 +236,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>
@@ -323,6 +324,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))
+22 -9
View File
@@ -1621,7 +1621,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)
@@ -5115,6 +5115,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)
{
@@ -5134,13 +5147,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:
@@ -5406,6 +5413,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);
@@ -5491,7 +5504,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);
+1 -2
View File
@@ -71,8 +71,7 @@ extern void *valloc (size_t __size) __THROW __attribute_malloc__
/* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up
__size to nearest pagesize. */
extern void *pvalloc (size_t __size) __THROW __attribute_malloc__
__attribute_alloc_size__ ((1)) __wur;
extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ __wur;
/* Underlying allocation function; successive calls should return
contiguous pieces of memory. */
+28 -11
View File
@@ -62,6 +62,9 @@ static volatile sig_atomic_t sigusr1_received;
progress. Checked by liveness_signal_handler. */
static volatile sig_atomic_t progress_indicator = 1;
/* Set to 1 if an error occurs in the signal handler. */
static volatile sig_atomic_t error_indicator = 0;
static void
sigusr1_handler (int signo)
{
@@ -72,7 +75,8 @@ sigusr1_handler (int signo)
if (pid == -1)
{
write_message ("error: fork\n");
abort ();
error_indicator = 1;
return;
}
if (pid == 0)
_exit (0);
@@ -81,12 +85,14 @@ sigusr1_handler (int signo)
if (ret < 0)
{
write_message ("error: waitpid\n");
abort ();
error_indicator = 1;
return;
}
if (status != 0)
{
write_message ("error: unexpected exit status from subprocess\n");
abort ();
error_indicator = 1;
return;
}
}
@@ -122,9 +128,25 @@ signal_sender (int signo, bool sleep)
}
}
/* Children processes. */
static pid_t sigusr1_sender_pids[5] = { 0 };
static pid_t sigusr2_sender_pid = 0;
static void
kill_children (void)
{
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
if (sigusr1_sender_pids[i] > 0)
kill (sigusr1_sender_pids[i], SIGKILL);
if (sigusr2_sender_pid > 0)
kill (sigusr2_sender_pid, SIGKILL);
}
static int
do_test (void)
{
atexit (kill_children);
/* shared->barrier is intialized along with sigusr1_sender_pids
below. */
shared = support_shared_allocate (sizeof (*shared));
@@ -148,14 +170,13 @@ do_test (void)
return 1;
}
pid_t sigusr2_sender_pid = xfork ();
sigusr2_sender_pid = xfork ();
if (sigusr2_sender_pid == 0)
signal_sender (SIGUSR2, true);
/* Send SIGUSR1 signals from several processes. Hopefully, one
signal will hit one of the ciritical functions. Use a barrier to
avoid sending signals while not running fork/free/malloc. */
pid_t sigusr1_sender_pids[5];
{
pthread_barrierattr_t attr;
xpthread_barrierattr_init (&attr);
@@ -166,7 +187,7 @@ do_test (void)
}
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
{
sigusr1_sender_pids[i] = fork ();
sigusr1_sender_pids[i] = xfork ();
if (sigusr1_sender_pids[i] == 0)
signal_sender (SIGUSR1, false);
}
@@ -211,7 +232,7 @@ do_test (void)
++malloc_signals;
xpthread_barrier_wait (&shared->barrier);
if (objects[slot] == NULL)
if (objects[slot] == NULL || error_indicator != 0)
{
printf ("error: malloc: %m\n");
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
@@ -225,10 +246,6 @@ do_test (void)
for (int slot = 0; slot < malloc_objects; ++slot)
free (objects[slot]);
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
kill (sigusr1_sender_pids[i], SIGKILL);
kill (sigusr2_sender_pid, SIGKILL);
printf ("info: signals received during fork: %u\n", fork_signals);
printf ("info: signals received during free: %u\n", free_signals);
printf ("info: signals received during malloc: %u\n", malloc_signals);
+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>
+48
View File
@@ -0,0 +1,48 @@
/* Test fortify-source allocation size handling in pvalloc (bug 25401).
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#undef _FORTIFY_SOURCE
#define _FORTIFY_SOURCE 2
#include <malloc.h>
#include <string.h>
#include <support/check.h>
#include <support/xunistd.h>
#include <unistd.h>
static int
do_test (void)
{
/* The test below assumes that pvalloc rounds up the allocation size
to at least 8. */
TEST_VERIFY (xsysconf (_SC_PAGESIZE) >= 8);
void *p = pvalloc (5);
TEST_VERIFY_EXIT (p != NULL);
/* This is valid assuming the page size is at least 8 because
pvalloc rounds up the allocation size to a multiple of the page
size. Due to bug 25041, this used to trigger a compiler
warning. */
strcpy (p, "abcdefg");
asm ("" : : "g" (p) : "memory"); /* Optimization barrier. */
TEST_VERIFY (malloc_usable_size (p) >= xsysconf (_SC_PAGESIZE));
return 0;
}
#include <support/test-driver.c>
+12
View File
@@ -214,6 +214,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
+10 -10
View File
@@ -894,9 +894,9 @@ The @code{getlogin} function is declared in @file{unistd.h}, while
@c ttyname_r dup @ascuheap @acsmem @acsfd
@c strncpy dup ok
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->setutent dup @mtasurace:utent @acsfd
@c *libc_utmp_jump_table->getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer
@c *libc_utmp_jump_table->endutent dup @mtasurace:utent @asulock @aculock
@c __libc_setutent dup @mtasurace:utent @acsfd
@c __libc_getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer
@c __libc_endutent dup @mtasurace:utent @asulock @aculock
@c libc_lock_unlock dup ok
@c strlen dup ok
@c memcpy dup ok
@@ -1111,7 +1111,7 @@ compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for
@c setutent @mtasurace:utent @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->setutent @mtasurace:utent @acsfd
@c __libc_setutent @mtasurace:utent @acsfd
@c setutent_unknown @mtasurace:utent @acsfd
@c *libc_utmp_file_functions.setutent = setutent_file @mtasurace:utent @acsfd
@c open_not_cancel_2 dup @acsfd
@@ -1152,7 +1152,7 @@ A null pointer is returned in case no further entry is available.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
@c endutent @mtasurace:utent @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->endutent @mtasurace:utent @acsfd
@c __libc_endutent @mtasurace:utent @acsfd
@c endutent_unknown ok
@c endutent_file @mtasurace:utent @acsfd
@c close_not_cancel_no_status dup @acsfd
@@ -1230,7 +1230,7 @@ over again.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
@c pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c __libc_pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c pututline_unknown @mtasurace:utent @acsfd
@c setutent_unknown dup @mtasurace:utent @acsfd
@c pututline_file @mtascusig:ALRM @mtascutimer @acsfd
@@ -1282,7 +1282,7 @@ user-provided buffer.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
@c getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c __libc_getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c getutent_r_unknown @mtasurace:utent @acsfd
@c setutent_unknown dup @mtasurace:utent @acsfd
@c getutent_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer
@@ -1319,7 +1319,7 @@ This function is a GNU extension.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
@c getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c __libc_getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c getutid_r_unknown @mtasurace:utent @acsfd
@c setutent_unknown dup @mtasurace:utent @acsfd
@c getutid_r_file @mtascusig:ALRM @mtascutimer
@@ -1349,7 +1349,7 @@ This function is a GNU extension.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}}
@c getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c __libc_getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd
@c getutline_r_unknown @mtasurace:utent @acsfd
@c setutent_unknown dup @mtasurace:utent @acsfd
@c getutline_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer
@@ -1393,7 +1393,7 @@ be used.
@safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}}
@c utmpname @mtasurace:utent @asulock @ascuheap @aculock @acsmem
@c libc_lock_lock dup @asulock @aculock
@c *libc_utmp_jump_table->endutent dup @mtasurace:utent
@c __libc_endutent dup @mtasurace:utent
@c strcmp dup ok
@c free dup @ascuheap @acsmem
@c strdup dup @ascuheap @acsmem
+2 -1
View File
@@ -86,7 +86,8 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240 \
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
tst-syscalls
# Tests which need libdl.
ifeq (yes,$(build-shared))
-8
View File
@@ -412,14 +412,6 @@
# define __glibc_has_attribute(attr) 0
#endif
#ifdef __has_include
/* Do not use a function-like macro, so that __has_include can inhibit
macro expansion. */
# define __glibc_has_include __has_include
#else
# define __glibc_has_include(header) 0
#endif
#if (!defined _Noreturn \
&& (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
&& !__GNUC_PREREQ (4,7))
+167
View File
@@ -0,0 +1,167 @@
/* Test for syscall interfaces.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This test verifies that the x32 system call handling zero-extends
unsigned 32-bit arguments to the 64-bit argument registers for
system calls (bug 25810). The bug is specific to x32, but the test
should pass on all architectures. */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <support/check.h>
#include <support/xunistd.h>
/* On x32, this can be passed in a single 64-bit integer register. */
struct Array
{
size_t length;
void *ptr;
};
static int error_count;
__attribute__ ((noclone, noinline))
struct Array
allocate (size_t bytes)
{
if (!bytes)
return __extension__ (struct Array) {0, 0};
void *p = mmap (0x0, bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (p == MAP_FAILED)
return __extension__ (struct Array) {0, 0};
return __extension__ (struct Array) {bytes, p};
}
__attribute__ ((noclone, noinline))
void
deallocate (struct Array b)
{
/* On x32, the 64-bit integer register containing `b' may be copied
to another 64-bit integer register to pass the second argument to
munmap. */
if (b.length && munmap (b.ptr, b.length))
{
printf ("munmap error: %m\n");
error_count++;
}
}
__attribute__ ((noclone, noinline))
void *
do_mmap (void *addr, size_t length)
{
return mmap (addr, length, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
}
__attribute__ ((noclone, noinline))
void *
reallocate (struct Array b)
{
/* On x32, the 64-bit integer register containing `b' may be copied
to another 64-bit integer register to pass the second argument to
do_mmap. */
if (b.length)
return do_mmap (b.ptr, b.length);
return NULL;
}
__attribute__ ((noclone, noinline))
void
protect (struct Array b)
{
if (b.length)
{
/* On x32, the 64-bit integer register containing `b' may be copied
to another 64-bit integer register to pass the second argument
to mprotect. */
if (mprotect (b.ptr, b.length,
PROT_READ | PROT_WRITE | PROT_EXEC))
{
printf ("mprotect error: %m\n");
error_count++;
}
}
}
__attribute__ ((noclone, noinline))
ssize_t
do_read (int fd, void *ptr, struct Array b)
{
/* On x32, the 64-bit integer register containing `b' may be copied
to another 64-bit integer register to pass the second argument to
read. */
if (b.length)
return read (fd, ptr, b.length);
return 0;
}
__attribute__ ((noclone, noinline))
ssize_t
do_write (int fd, void *ptr, struct Array b)
{
/* On x32, the 64-bit integer register containing `b' may be copied
to another 64-bit integer register to pass the second argument to
write. */
if (b.length)
return write (fd, ptr, b.length);
return 0;
}
static int
do_test (void)
{
struct Array array;
array = allocate (1);
protect (array);
deallocate (array);
void *p = reallocate (array);
if (p == MAP_FAILED)
{
printf ("mmap error: %m\n");
error_count++;
}
array.ptr = p;
protect (array);
deallocate (array);
int fd = xopen ("/dev/null", O_RDWR, 0);
char buf[2];
array.ptr = buf;
if (do_read (fd, array.ptr, array) == -1)
{
printf ("read error: %m\n");
error_count++;
}
if (do_write (fd, array.ptr, array) == -1)
{
printf ("write error: %m\n");
error_count++;
}
xclose (fd);
return error_count ? EXIT_FAILURE : EXIT_SUCCESS;
}
#include <support/test-driver.c>
+2 -2
View File
@@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
: NULL);
ndomain = (ndomain ? newbuf + ndomaindiff
: NULL);
buffer = newbuf;
*tofreep = buffer = newbuf;
}
nhost = memcpy (buffer + bufused,
@@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
buflen *= 2;
buffer = xrealloc (buffer, buflen);
*tofreep = buffer = xrealloc (buffer, buflen);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
+12 -3
View File
@@ -142,7 +142,7 @@ _nss_compat_setgrent (int stayopen)
}
static enum nss_status
static enum nss_status __attribute_warn_unused_result__
internal_endgrent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -163,6 +163,15 @@ internal_endgrent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
/* Like internal_endgrent, but preserve errno in all cases. */
static void
internal_endgrent_noerror (ent_t *ent)
{
int saved_errno = errno;
enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent);
__set_errno (saved_errno);
}
enum nss_status
_nss_compat_endgrent (void)
{
@@ -483,7 +492,7 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp,
if (result == NSS_STATUS_SUCCESS)
result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
internal_endgrent (&ent);
internal_endgrent_noerror (&ent);
return result;
}
@@ -612,7 +621,7 @@ _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
if (result == NSS_STATUS_SUCCESS)
result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
internal_endgrent (&ent);
internal_endgrent_noerror (&ent);
return result;
}
+11 -2
View File
@@ -133,7 +133,7 @@ internal_setgrent (ent_t *ent)
}
static enum nss_status
static enum nss_status __attribute_warn_unused_result__
internal_endgrent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -157,6 +157,15 @@ internal_endgrent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
/* Like internal_endgrent, but preserve errno in all cases. */
static void
internal_endgrent_noerror (ent_t *ent)
{
int saved_errno = errno;
enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent);
__set_errno (saved_errno);
}
/* Add new group record. */
static void
add_group (long int *start, long int *size, gid_t **groupsp, long int limit,
@@ -501,7 +510,7 @@ _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start,
done:
scratch_buffer_free (&tmpbuf);
internal_endgrent (&intern);
internal_endgrent_noerror (&intern);
return status;
}
+12 -3
View File
@@ -259,7 +259,7 @@ _nss_compat_setpwent (int stayopen)
}
static enum nss_status
static enum nss_status __attribute_warn_unused_result__
internal_endpwent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -287,6 +287,15 @@ internal_endpwent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
/* Like internal_endpwent, but preserve errno in all cases. */
static void
internal_endpwent_noerror (ent_t *ent)
{
int saved_errno = errno;
enum nss_status unused __attribute__ ((unused)) = internal_endpwent (ent);
__set_errno (saved_errno);
}
enum nss_status
_nss_compat_endpwent (void)
{
@@ -822,7 +831,7 @@ _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
internal_endpwent (&ent);
internal_endpwent_noerror (&ent);
return result;
}
@@ -1061,7 +1070,7 @@ _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
internal_endpwent (&ent);
internal_endpwent_noerror (&ent);
return result;
}
+11 -3
View File
@@ -215,7 +215,7 @@ _nss_compat_setspent (int stayopen)
}
static enum nss_status
static enum nss_status __attribute_warn_unused_result__
internal_endspent (ent_t *ent)
{
if (ent->stream != NULL)
@@ -244,6 +244,15 @@ internal_endspent (ent_t *ent)
return NSS_STATUS_SUCCESS;
}
/* Like internal_endspent, but preserve errno in all cases. */
static void
internal_endspent_noerror (ent_t *ent)
{
int saved_errno = errno;
enum nss_status unused __attribute__ ((unused)) = internal_endspent (ent);
__set_errno (saved_errno);
}
enum nss_status
_nss_compat_endspent (void)
{
@@ -261,7 +270,6 @@ _nss_compat_endspent (void)
return result;
}
static enum nss_status
getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent,
char *group, char *buffer, size_t buflen,
@@ -786,7 +794,7 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
if (result == NSS_STATUS_SUCCESS)
result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop);
internal_endspent (&ent);
internal_endspent_noerror (&ent);
return result;
}
+13 -12
View File
@@ -827,31 +827,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
char *d;
char *d, *newp;
bool use_alloca = glob_use_alloca (alloca_used,
home_len + rest_len + 1);
if (__glibc_unlikely (malloc_dirname))
free (dirname);
malloc_dirname = 0;
if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
dirname = alloca_account (home_len + rest_len + 1,
alloca_used);
if (use_alloca)
newp = alloca_account (home_len + rest_len + 1, alloca_used);
else
{
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
newp = malloc (home_len + rest_len + 1);
if (newp == NULL)
{
scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
malloc_dirname = 1;
}
d = mempcpy (dirname, p->pw_dir, home_len);
d = mempcpy (newp, p->pw_dir, home_len);
if (end_name != NULL)
d = mempcpy (d, end_name, rest_len);
*d = '\0';
if (__glibc_unlikely (malloc_dirname))
free (dirname);
dirname = newp;
malloc_dirname = !use_alloca;
dirlen = home_len + rest_len;
dirname_modified = 1;
}
+2 -1
View File
@@ -70,7 +70,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
test-canon test-canon2 tst-strtoll tst-environ \
tst-xpg-basename tst-random tst-random2 tst-bsearch \
tst-limits tst-rand48 bug-strtod tst-setcontext \
tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \
tst-setcontext2 test-a64l tst-qsort testmb2 \
bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \
tst-rand48-2 tst-makecontext tst-strtod5 \
tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
@@ -92,6 +92,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
tst-tls-atexit tst-tls-atexit-nodelete
tests-static := tst-secure-getenv
tests-container := tst-system
ifeq ($(build-hardcoded-path-in-tests),yes)
tests += tst-empty-env
+18 -181
View File
@@ -30,167 +30,12 @@
#include <sys/wait.h>
#include <unistd.h>
#include <support/check.h>
#include <support/support.h>
#include <support/capture_subprocess.h>
#include <support/test-driver.h>
static char MAGIC_ARGUMENT[] = "run-actual-test";
#define MAGIC_STATUS 19
/* Return a GID which is not our current GID, but is present in the
supplementary group list. */
static gid_t
choose_gid (void)
{
int count = getgroups (0, NULL);
if (count < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t *groups;
groups = xcalloc (count, sizeof (*groups));
int ret = getgroups (count, groups);
if (ret < 0)
{
printf ("getgroups: %m\n");
exit (1);
}
gid_t current = getgid ();
gid_t not_current = 0;
for (int i = 0; i < ret; ++i)
{
if (groups[i] != current)
{
not_current = groups[i];
break;
}
}
free (groups);
return not_current;
}
/* Copies the executable into a restricted directory, so that we can
safely make it SGID with the TARGET group ID. Then runs the
executable. */
static int
run_executable_sgid (gid_t target)
{
char *dirname = xasprintf ("%s/secure-getenv.%jd",
test_dir, (intmax_t) getpid ());
char *execname = xasprintf ("%s/bin", dirname);
int infd = -1;
int outfd = -1;
int ret = -1;
if (mkdir (dirname, 0700) < 0)
{
printf ("mkdir: %m\n");
goto err;
}
infd = open ("/proc/self/exe", O_RDONLY);
if (infd < 0)
{
printf ("open (/proc/self/exe): %m\n");
goto err;
}
outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
if (outfd < 0)
{
printf ("open (%s): %m\n", execname);
goto err;
}
char buf[4096];
for (;;)
{
ssize_t rdcount = read (infd, buf, sizeof (buf));
if (rdcount < 0)
{
printf ("read: %m\n");
goto err;
}
if (rdcount == 0)
break;
char *p = buf;
char *end = buf + rdcount;
while (p != end)
{
ssize_t wrcount = write (outfd, buf, end - p);
if (wrcount == 0)
errno = ENOSPC;
if (wrcount <= 0)
{
printf ("write: %m\n");
goto err;
}
p += wrcount;
}
}
if (fchown (outfd, getuid (), target) < 0)
{
printf ("fchown (%s): %m\n", execname);
goto err;
}
if (fchmod (outfd, 02750) < 0)
{
printf ("fchmod (%s): %m\n", execname);
goto err;
}
if (close (outfd) < 0)
{
printf ("close (outfd): %m\n");
goto err;
}
if (close (infd) < 0)
{
printf ("close (infd): %m\n");
goto err;
}
int kid = fork ();
if (kid < 0)
{
printf ("fork: %m\n");
goto err;
}
if (kid == 0)
{
/* Child process. */
char *args[] = { execname, MAGIC_ARGUMENT, NULL };
execve (execname, args, environ);
printf ("execve (%s): %m\n", execname);
_exit (1);
}
int status;
if (waitpid (kid, &status, 0) < 0)
{
printf ("waitpid: %m\n");
goto err;
}
if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS)
{
printf ("Unexpected exit status %d from child process\n",
status);
goto err;
}
ret = 0;
err:
if (outfd >= 0)
close (outfd);
if (infd >= 0)
close (infd);
if (execname)
{
unlink (execname);
free (execname);
}
if (dirname)
{
rmdir (dirname);
free (dirname);
}
return ret;
}
static int
do_test (void)
@@ -212,15 +57,15 @@ do_test (void)
exit (1);
}
gid_t target = choose_gid ();
if (target == 0)
{
fprintf (stderr,
"Could not find a suitable GID for user %jd, skipping test\n",
(intmax_t) getuid ());
exit (0);
}
return run_executable_sgid (target);
int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT);
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
return EXIT_UNSUPPORTED;
if (!WIFEXITED (status))
FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status);
return 0;
}
static void
@@ -229,23 +74,15 @@ alternative_main (int argc, char **argv)
if (argc == 2 && strcmp (argv[1], MAGIC_ARGUMENT) == 0)
{
if (getgid () == getegid ())
{
/* This can happen if the file system is mounted nosuid. */
fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
exit (MAGIC_STATUS);
}
/* This can happen if the file system is mounted nosuid. */
FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n",
(intmax_t) getgid ());
if (getenv ("PATH") == NULL)
{
printf ("PATH variable not present\n");
exit (3);
}
FAIL_EXIT (3, "PATH variable not present\n");
if (secure_getenv ("PATH") != NULL)
{
printf ("PATH variable not filtered out\n");
exit (4);
}
exit (MAGIC_STATUS);
FAIL_EXIT (4, "PATH variable not filtered out\n");
exit (EXIT_SUCCESS);
}
}
+120 -4
View File
@@ -17,14 +17,130 @@
<http://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <paths.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/temp_file.h>
#include <support/support.h>
static char *tmpdir;
static long int namemax;
static void
do_prepare (int argc, char *argv[])
{
tmpdir = support_create_temp_directory ("tst-system-");
/* Include the last '/0'. */
namemax = pathconf (tmpdir, _PC_NAME_MAX) + 1;
TEST_VERIFY_EXIT (namemax != -1);
}
#define PREPARE do_prepare
struct args
{
const char *command;
int exit_status;
int term_sig;
const char *path;
};
static void
call_system (void *closure)
{
struct args *args = (struct args *) closure;
int ret;
if (args->path != NULL)
TEST_COMPARE (setenv ("PATH", args->path, 1), 0);
ret = system (args->command);
if (args->term_sig == 0)
{
/* Expect regular termination. */
TEST_VERIFY (WIFEXITED (ret) != 0);
TEST_COMPARE (WEXITSTATUS (ret), args->exit_status);
}
else
{
/* status_or_signal < 0. Expect termination by signal. */
TEST_VERIFY (WIFSIGNALED (ret) != 0);
TEST_COMPARE (WTERMSIG (ret), args->term_sig);
}
}
static int
do_test (void)
{
return system (":");
TEST_VERIFY (system (NULL) != 0);
{
char cmd[namemax];
memset (cmd, 'a', sizeof(cmd));
cmd[sizeof(cmd) - 1] = '\0';
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) {
cmd, 127, 0, tmpdir
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
char *returnerr = xasprintf ("%s: execing %s failed: "
"No such file or directory",
basename(_PATH_BSHELL), cmd);
TEST_COMPARE_STRING (result.err.buffer, returnerr);
free (returnerr);
}
{
char cmd[namemax + 1];
memset (cmd, 'a', sizeof(cmd));
cmd[sizeof(cmd) - 1] = '\0';
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) {
cmd, 127, 0, tmpdir
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
char *returnerr = xasprintf ("%s: execing %s failed: "
"File name too long",
basename(_PATH_BSHELL), cmd);
TEST_COMPARE_STRING (result.err.buffer, returnerr);
free (returnerr);
}
{
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) {
"kill $$", 0, SIGTERM
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
}
{
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) { "echo ...", 0 });
support_capture_subprocess_check (&result, "system", 0, sc_allow_stdout);
TEST_COMPARE_STRING (result.out.buffer, "...\n");
}
{
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) { "exit 1", 1 });
support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
}
TEST_COMPARE (system (""), 0);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
#include <support/test-driver.c>
+2 -1
View File
@@ -33,7 +33,8 @@ __BEGIN_DECLS
#include <stddef.h>
/* Tell the caller that we provide correct C++ prototypes. */
#if defined __cplusplus && __GNUC_PREREQ (4, 4)
#if defined __cplusplus && (__GNUC_PREREQ (4, 4) \
|| __glibc_clang_prereq (3, 5))
# define __CORRECT_ISO_CPP_STRING_H_PROTO
#endif
+36 -3
View File
@@ -65,8 +65,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, size_t n, CHAR *exp_res)
CHAR *res = CALL (impl, s, c, n);
if (res != exp_res)
{
error (0, 0, "Wrong result in function %s %p %p", impl->name,
res, exp_res);
error (0, 0, "Wrong result in function %s (%p, %d, %zu) -> %p != %p",
impl->name, s, c, n, res, exp_res);
ret = 1;
return;
}
@@ -91,7 +91,7 @@ do_test (size_t align, size_t pos, size_t len, size_t n, int seek_char)
}
buf[align + len] = 0;
if (pos < len)
if (pos < MIN(n, len))
{
buf[align + pos] = seek_char;
buf[align + len] = -seek_char;
@@ -107,6 +107,38 @@ do_test (size_t align, size_t pos, size_t len, size_t n, int seek_char)
do_one_test (impl, (CHAR *) (buf + align), seek_char, n, result);
}
static void
do_overflow_tests (void)
{
size_t i, j, len;
const size_t one = 1;
uintptr_t buf_addr = (uintptr_t) buf1;
for (i = 0; i < 750; ++i)
{
do_test (0, i, 751, SIZE_MAX - i, BIG_CHAR);
do_test (0, i, 751, i - buf_addr, BIG_CHAR);
do_test (0, i, 751, -buf_addr - i, BIG_CHAR);
do_test (0, i, 751, SIZE_MAX - buf_addr - i, BIG_CHAR);
do_test (0, i, 751, SIZE_MAX - buf_addr + i, BIG_CHAR);
len = 0;
for (j = 8 * sizeof(size_t) - 1; j ; --j)
{
len |= one << j;
do_test (0, i, 751, len - i, BIG_CHAR);
do_test (0, i, 751, len + i, BIG_CHAR);
do_test (0, i, 751, len - buf_addr - i, BIG_CHAR);
do_test (0, i, 751, len - buf_addr + i, BIG_CHAR);
do_test (0, i, 751, ~len - i, BIG_CHAR);
do_test (0, i, 751, ~len + i, BIG_CHAR);
do_test (0, i, 751, ~len - buf_addr - i, BIG_CHAR);
do_test (0, i, 751, ~len - buf_addr + i, BIG_CHAR);
}
}
}
static void
do_random_tests (void)
{
@@ -221,6 +253,7 @@ test_main (void)
do_test (page_size / 2 - i, i, i, 1, 0x9B);
do_random_tests ();
do_overflow_tests ();
return ret;
}
+61
View File
@@ -134,6 +134,66 @@ do_test (size_t align1, size_t align2, size_t len1, size_t len2,
}
}
static void
do_overflow_tests (void)
{
size_t i, j, len;
const size_t one = 1;
CHAR *s1, *s2;
uintptr_t s1_addr;
s1 = (CHAR *) buf1;
s2 = (CHAR *) buf2;
s1_addr = (uintptr_t)s1;
for (j = 0; j < 200; ++j)
s2[j] = 32 + 23 * j % (BIG_CHAR - 32);
s2[200] = 0;
for (i = 0; i < 750; ++i) {
for (j = 0; j < i; ++j)
s1[j] = 32 + 23 * j % (BIG_CHAR - 32);
s1[i] = '\0';
FOR_EACH_IMPL (impl, 0)
{
s2[200] = '\0';
do_one_test (impl, s2, s1, SIZE_MAX - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, i - s1_addr);
s2[200] = '\0';
do_one_test (impl, s2, s1, -s1_addr - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, SIZE_MAX - s1_addr - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, SIZE_MAX - s1_addr + i);
}
len = 0;
for (j = 8 * sizeof(size_t) - 1; j ; --j)
{
len |= one << j;
FOR_EACH_IMPL (impl, 0)
{
s2[200] = '\0';
do_one_test (impl, s2, s1, len - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, len + i);
s2[200] = '\0';
do_one_test (impl, s2, s1, len - s1_addr - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, len - s1_addr + i);
s2[200] = '\0';
do_one_test (impl, s2, s1, ~len - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, ~len + i);
s2[200] = '\0';
do_one_test (impl, s2, s1, ~len - s1_addr - i);
s2[200] = '\0';
do_one_test (impl, s2, s1, ~len - s1_addr + i);
}
}
}
}
static void
do_random_tests (void)
{
@@ -316,6 +376,7 @@ test_main (void)
}
do_random_tests ();
do_overflow_tests ();
return ret;
}
+13
View File
@@ -403,6 +403,18 @@ check2 (void)
free (s2);
}
static void
check3 (void)
{
const CHAR *s1 = L ("abc");
CHAR *s2 = STRDUP (s1);
FOR_EACH_IMPL (impl, 0)
check_result (impl, s1, s2, SIZE_MAX, 0);
free (s2);
}
int
test_main (void)
{
@@ -412,6 +424,7 @@ test_main (void)
check1 ();
check2 ();
check3 ();
printf ("%23s", "");
FOR_EACH_IMPL (impl, 0)
+66 -1
View File
@@ -27,6 +27,7 @@
#ifndef WIDE
# define STRNLEN strnlen
# define MEMSET memset
# define CHAR char
# define BIG_CHAR CHAR_MAX
# define MIDDLE_CHAR 127
@@ -34,6 +35,7 @@
#else
# include <wchar.h>
# define STRNLEN wcsnlen
# define MEMSET wmemset
# define CHAR wchar_t
# define BIG_CHAR WCHAR_MAX
# define MIDDLE_CHAR 1121
@@ -87,6 +89,38 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
do_one_test (impl, (CHAR *) (buf + align), maxlen, MIN (len, maxlen));
}
static void
do_overflow_tests (void)
{
size_t i, j, len;
const size_t one = 1;
uintptr_t buf_addr = (uintptr_t) buf1;
for (i = 0; i < 750; ++i)
{
do_test (0, i, SIZE_MAX - i, BIG_CHAR);
do_test (0, i, i - buf_addr, BIG_CHAR);
do_test (0, i, -buf_addr - i, BIG_CHAR);
do_test (0, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
do_test (0, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
len = 0;
for (j = 8 * sizeof(size_t) - 1; j ; --j)
{
len |= one << j;
do_test (0, i, len - i, BIG_CHAR);
do_test (0, i, len + i, BIG_CHAR);
do_test (0, i, len - buf_addr - i, BIG_CHAR);
do_test (0, i, len - buf_addr + i, BIG_CHAR);
do_test (0, i, ~len - i, BIG_CHAR);
do_test (0, i, ~len + i, BIG_CHAR);
do_test (0, i, ~len - buf_addr - i, BIG_CHAR);
do_test (0, i, ~len - buf_addr + i, BIG_CHAR);
}
}
}
static void
do_random_tests (void)
{
@@ -153,7 +187,7 @@ do_page_tests (void)
size_t last_offset = (page_size / sizeof (CHAR)) - 1;
CHAR *s = (CHAR *) buf2;
memset (s, 65, (last_offset - 1));
MEMSET (s, 65, (last_offset - 1));
s[last_offset] = 0;
/* Place short strings ending at page boundary. */
@@ -196,6 +230,35 @@ do_page_tests (void)
}
}
/* Tests meant to unveil fail on implementations that access bytes
beyond the maxium length. */
static void
do_page_2_tests (void)
{
size_t i, exp_len, offset;
size_t last_offset = page_size / sizeof (CHAR);
CHAR *s = (CHAR *) buf2;
MEMSET (s, 65, last_offset);
/* Place short strings ending at page boundary without the null
byte. */
offset = last_offset;
for (i = 0; i < 128; i++)
{
/* Decrease offset to stress several sizes and alignments. */
offset--;
exp_len = last_offset - offset;
FOR_EACH_IMPL (impl, 0)
{
/* If an implementation goes beyond EXP_LEN, it will trigger
the segfault. */
do_one_test (impl, (CHAR *) (s + offset), exp_len, exp_len);
}
}
}
int
test_main (void)
{
@@ -242,6 +305,8 @@ test_main (void)
do_random_tests ();
do_page_tests ();
do_page_2_tests ();
do_overflow_tests ();
return ret;
}
+35 -6
View File
@@ -139,16 +139,45 @@ check1 (void)
static void
check2 (void)
{
const char s1[] = ", enable_static, \0, enable_shared, ";
const char s1_stack[] = ", enable_static, \0, enable_shared, ";
const size_t s1_byte_count = 18;
const char *s2_stack = &(s1_stack[s1_byte_count]);
const size_t s2_byte_count = 18;
char *exp_result;
char *s2 = (void *) buf1 + page_size - 18;
const size_t page_size_real = getpagesize ();
strcpy (s2, s1);
exp_result = stupid_strstr (s1, s1 + 18);
/* Haystack at end of page. The following page is protected. */
char *s1_page_end = (void *) buf1 + page_size - s1_byte_count;
strcpy (s1_page_end, s1_stack);
/* Haystack which crosses a page boundary.
Note: page_size is at least 2 * getpagesize. See test_init. */
char *s1_page_cross = (void *) buf1 + page_size_real - 8;
strcpy (s1_page_cross, s1_stack);
/* Needle at end of page. The following page is protected. */
char *s2_page_end = (void *) buf2 + page_size - s2_byte_count;
strcpy (s2_page_end, s2_stack);
/* Needle which crosses a page boundary.
Note: page_size is at least 2 * getpagesize. See test_init. */
char *s2_page_cross = (void *) buf2 + page_size_real - 8;
strcpy (s2_page_cross, s2_stack);
exp_result = stupid_strstr (s1_stack, s2_stack);
FOR_EACH_IMPL (impl, 0)
{
check_result (impl, s1, s1 + 18, exp_result);
check_result (impl, s2, s1 + 18, exp_result);
check_result (impl, s1_stack, s2_stack, exp_result);
check_result (impl, s1_stack, s2_page_end, exp_result);
check_result (impl, s1_stack, s2_page_cross, exp_result);
check_result (impl, s1_page_end, s2_stack, exp_result);
check_result (impl, s1_page_end, s2_page_end, exp_result);
check_result (impl, s1_page_end, s2_page_cross, exp_result);
check_result (impl, s1_page_cross, s2_stack, exp_result);
check_result (impl, s1_page_cross, s2_page_end, exp_result);
check_result (impl, s1_page_cross, s2_page_cross, exp_result);
}
}
+6
View File
@@ -41,6 +41,12 @@ struct support_capture_subprocess support_capture_subprocess
struct support_capture_subprocess support_capture_subprogram
(const char *file, char *const argv[]);
/* Copy the running program into a setgid binary and run it with CHILD_ID
argument. If execution is successful, return the exit status of the child
program, otherwise return a non-zero failure exit code. */
int support_capture_subprogram_self_sgid
(char *child_id);
/* Deallocate the subprocess data captured by
support_capture_subprocess. */
void support_capture_subprocess_free (struct support_capture_subprocess *);
+39 -1
View File
@@ -135,6 +135,37 @@ copy_func (char **argv)
}
/* Emulate the 'exit' builtin. The exit value is optional. */
static int
exit_func (char **argv)
{
int exit_val = 0;
if (argv[0] != 0)
exit_val = atoi (argv[0]) & 0xff;
exit (exit_val);
return 0;
}
/* Emulate the "/bin/kill" command. Options are ignored. */
static int
kill_func (char **argv)
{
int signum = SIGTERM;
int i;
for (i = 0; argv[i]; i++)
{
pid_t pid;
if (strcmp (argv[i], "$$") == 0)
pid = getpid ();
else
pid = atoi (argv[i]);
kill (pid, signum);
}
return 0;
}
/* This is a list of all the built-in commands we understand. */
static struct {
const char *name;
@@ -143,6 +174,8 @@ static struct {
{ "true", true_func },
{ "echo", echo_func },
{ "cp", copy_func },
{ "exit", exit_func },
{ "kill", kill_func },
{ NULL, NULL }
};
@@ -238,7 +271,7 @@ run_command_array (char **argv)
fprintf (stderr, "sh: execing %s failed: %s",
argv[0], strerror (errno));
exit (1);
exit (127);
}
waitpid (pid, &status, 0);
@@ -251,6 +284,11 @@ run_command_array (char **argv)
if (rv)
exit (rv);
}
else if (WIFSIGNALED (status))
{
int sig = WTERMSIG (status);
raise (sig);
}
else
exit (1);
}
+5
View File
@@ -38,6 +38,11 @@ struct support_subprocess support_subprocess
struct support_subprocess support_subprogram
(const char *file, char *const argv[]);
/* Invoke program FILE with ARGV arguments by using posix_spawn and wait for it
to complete. Return program exit status. */
int support_subprogram_wait
(const char *file, char *const argv[]);
/* Wait for the subprocess indicated by PROC::PID. Return the status
indicate by waitpid call. */
int support_process_wait (struct support_subprocess *proc);
+127 -1
View File
@@ -20,11 +20,14 @@
#include <support/capture_subprocess.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <support/check.h>
#include <support/xunistd.h>
#include <support/xsocket.h>
#include <support/xspawn.h>
#include <support/support.h>
#include <support/test-driver.h>
static void
transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
@@ -36,7 +39,7 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
if (ret < 0)
{
support_record_failure ();
printf ("error: reading from subprocess %s: %m", what);
printf ("error: reading from subprocess %s: %m\n", what);
pfd->events = 0;
pfd->revents = 0;
}
@@ -102,6 +105,129 @@ support_capture_subprogram (const char *file, char *const argv[])
return result;
}
/* 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
copy_and_spawn_sgid (char *child_id, gid_t gid)
{
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 = 1, status = 1;
TEST_VERIFY (mkdir (dirname, 0700) == 0);
if (support_record_failure_is_failed ())
goto err;
infd = open ("/proc/self/exe", O_RDONLY);
if (infd < 0)
FAIL_UNSUPPORTED ("unsupported: Cannot read binary from procfs\n");
outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700);
TEST_VERIFY (outfd >= 0);
if (support_record_failure_is_failed ())
goto err;
char buf[4096];
for (;;)
{
ssize_t rdcount = read (infd, buf, sizeof (buf));
TEST_VERIFY (rdcount >= 0);
if (support_record_failure_is_failed ())
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;
TEST_VERIFY (wrcount > 0);
if (support_record_failure_is_failed ())
goto err;
p += wrcount;
}
}
TEST_VERIFY (fchown (outfd, getuid (), gid) == 0);
if (support_record_failure_is_failed ())
goto err;
TEST_VERIFY (fchmod (outfd, 02750) == 0);
if (support_record_failure_is_failed ())
goto err;
TEST_VERIFY (close (outfd) == 0);
if (support_record_failure_is_failed ())
goto err;
TEST_VERIFY (close (infd) == 0);
if (support_record_failure_is_failed ())
goto err;
/* We have the binary, now spawn the subprocess. Avoid using
support_subprogram because we only want the program exit status, not the
contents. */
ret = 0;
char * const args[] = {execname, child_id, NULL};
status = support_subprogram_wait (args[0], args);
err:
if (outfd >= 0)
close (outfd);
if (infd >= 0)
close (infd);
if (execname != NULL)
{
unlink (execname);
free (execname);
}
if (dirname != NULL)
{
rmdir (dirname);
free (dirname);
}
if (ret != 0)
FAIL_EXIT1("Failed to make sgid executable for test\n");
return status;
}
int
support_capture_subprogram_self_sgid (char *child_id)
{
gid_t target = 0;
const int count = 64;
gid_t groups[count];
/* Get a GID which is not our current GID, but is present in the
supplementary group list. */
int ret = getgroups (count, groups);
if (ret < 0)
FAIL_UNSUPPORTED("Could not get group list for user %jd\n",
(intmax_t) getuid ());
gid_t current = getgid ();
for (int i = 0; i < ret; ++i)
{
if (groups[i] != current)
{
target = groups[i];
break;
}
}
if (target == 0)
FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n",
(intmax_t) getuid ());
return copy_and_spawn_sgid (child_id, target);
}
void
support_capture_subprocess_free (struct support_capture_subprocess *p)
{
+17 -4
View File
@@ -27,7 +27,7 @@
#include <support/subprocess.h>
static struct support_subprocess
support_suprocess_init (void)
support_subprocess_init (void)
{
struct support_subprocess result;
@@ -48,7 +48,7 @@ support_suprocess_init (void)
struct support_subprocess
support_subprocess (void (*callback) (void *), void *closure)
{
struct support_subprocess result = support_suprocess_init ();
struct support_subprocess result = support_subprocess_init ();
result.pid = xfork ();
if (result.pid == 0)
@@ -71,7 +71,7 @@ support_subprocess (void (*callback) (void *), void *closure)
struct support_subprocess
support_subprogram (const char *file, char *const argv[])
{
struct support_subprocess result = support_suprocess_init ();
struct support_subprocess result = support_subprocess_init ();
posix_spawn_file_actions_t fa;
/* posix_spawn_file_actions_init does not fail. */
@@ -84,7 +84,7 @@ support_subprogram (const char *file, char *const argv[])
xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]);
xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]);
result.pid = xposix_spawn (file, &fa, NULL, argv, NULL);
result.pid = xposix_spawn (file, &fa, NULL, argv, environ);
xclose (result.stdout_pipe[1]);
xclose (result.stderr_pipe[1]);
@@ -92,6 +92,19 @@ support_subprogram (const char *file, char *const argv[])
return result;
}
int
support_subprogram_wait (const char *file, char *const argv[])
{
posix_spawn_file_actions_t fa;
posix_spawn_file_actions_init (&fa);
struct support_subprocess res = support_subprocess_init ();
res.pid = xposix_spawn (file, &fa, NULL, argv, environ);
return support_process_wait (&res);
}
int
support_process_wait (struct support_subprocess *proc)
{
+4 -8
View File
@@ -391,13 +391,6 @@ elf_machine_lazy_rel (struct link_map *map,
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
{
if (map->l_mach.plt == 0)
{
/* Prelinking. */
*reloc_addr += l_addr;
return;
}
if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
{
/* Check the symbol table for variant PCS symbols. */
@@ -421,7 +414,10 @@ elf_machine_lazy_rel (struct link_map *map,
}
}
*reloc_addr = map->l_mach.plt;
if (map->l_mach.plt == 0)
*reloc_addr += l_addr;
else
*reloc_addr = map->l_mach.plt;
}
else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1))
{
+122 -105
View File
@@ -33,32 +33,24 @@
#define A_l x6
#define A_lw w6
#define A_h x7
#define A_hw w7
#define B_l x8
#define B_lw w8
#define B_h x9
#define C_l x10
#define C_lw w10
#define C_h x11
#define D_l x12
#define D_h x13
#define E_l src
#define E_h count
#define F_l srcend
#define F_h dst
#define E_l x14
#define E_h x15
#define F_l x16
#define F_h x17
#define G_l count
#define G_h dst
#define H_l src
#define H_h srcend
#define tmp1 x14
/* Copies are split into 3 main cases: small copies of up to 16 bytes,
medium copies of 17..96 bytes which are fully unrolled. Large copies
of more than 96 bytes align the destination and use an unrolled loop
processing 64 bytes per iteration.
In order to share code with memmove, small and medium copies read all
data before writing, allowing any kind of overlap. So small, medium
and large backwards memmoves are handled by falling through into memcpy.
Overlapping large forward memmoves use a loop that copies backwards.
*/
#ifndef MEMMOVE
# define MEMMOVE memmove
#endif
@@ -66,108 +58,115 @@
# define MEMCPY memcpy
#endif
ENTRY_ALIGN (MEMMOVE, 6)
/* This implementation supports both memcpy and memmove and shares most code.
It uses unaligned accesses and branchless sequences to keep the code small,
simple and improve performance.
Copies are split into 3 main cases: small copies of up to 32 bytes, medium
copies of up to 128 bytes, and large copies. The overhead of the overlap
check in memmove is negligible since it is only required for large copies.
Large copies use a software pipelined loop processing 64 bytes per
iteration. The destination pointer is 16-byte aligned to minimize
unaligned accesses. The loop tail is handled by always copying 64 bytes
from the end.
*/
ENTRY_ALIGN (MEMCPY, 6)
DELOUSE (0)
DELOUSE (1)
DELOUSE (2)
sub tmp1, dstin, src
cmp count, 96
ccmp tmp1, count, 2, hi
b.lo L(move_long)
/* Common case falls through into memcpy. */
END (MEMMOVE)
libc_hidden_builtin_def (MEMMOVE)
ENTRY (MEMCPY)
DELOUSE (0)
DELOUSE (1)
DELOUSE (2)
prfm PLDL1KEEP, [src]
add srcend, src, count
add dstend, dstin, count
cmp count, 16
b.ls L(copy16)
cmp count, 96
cmp count, 128
b.hi L(copy_long)
cmp count, 32
b.hi L(copy32_128)
/* Medium copies: 17..96 bytes. */
sub tmp1, count, 1
/* Small copies: 0..32 bytes. */
cmp count, 16
b.lo L(copy16)
ldp A_l, A_h, [src]
tbnz tmp1, 6, L(copy96)
ldp D_l, D_h, [srcend, -16]
tbz tmp1, 5, 1f
ldp B_l, B_h, [src, 16]
ldp C_l, C_h, [srcend, -32]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstend, -32]
1:
stp A_l, A_h, [dstin]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
/* Small copies: 0..16 bytes. */
/* Copy 8-15 bytes. */
L(copy16):
cmp count, 8
b.lo 1f
tbz count, 3, L(copy8)
ldr A_l, [src]
ldr A_h, [srcend, -8]
str A_l, [dstin]
str A_h, [dstend, -8]
ret
.p2align 4
1:
tbz count, 2, 1f
.p2align 3
/* Copy 4-7 bytes. */
L(copy8):
tbz count, 2, L(copy4)
ldr A_lw, [src]
ldr A_hw, [srcend, -4]
ldr B_lw, [srcend, -4]
str A_lw, [dstin]
str A_hw, [dstend, -4]
str B_lw, [dstend, -4]
ret
/* Copy 0..3 bytes. Use a branchless sequence that copies the same
byte 3 times if count==1, or the 2nd byte twice if count==2. */
1:
cbz count, 2f
/* Copy 0..3 bytes using a branchless sequence. */
L(copy4):
cbz count, L(copy0)
lsr tmp1, count, 1
ldrb A_lw, [src]
ldrb A_hw, [srcend, -1]
ldrb C_lw, [srcend, -1]
ldrb B_lw, [src, tmp1]
strb A_lw, [dstin]
strb B_lw, [dstin, tmp1]
strb A_hw, [dstend, -1]
2: ret
.p2align 4
/* Copy 64..96 bytes. Copy 64 bytes from the start and
32 bytes from the end. */
L(copy96):
ldp B_l, B_h, [src, 16]
ldp C_l, C_h, [src, 32]
ldp D_l, D_h, [src, 48]
ldp E_l, E_h, [srcend, -32]
ldp F_l, F_h, [srcend, -16]
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstin, 32]
stp D_l, D_h, [dstin, 48]
stp E_l, E_h, [dstend, -32]
stp F_l, F_h, [dstend, -16]
strb C_lw, [dstend, -1]
L(copy0):
ret
/* Align DST to 16 byte alignment so that we don't cross cache line
boundaries on both loads and stores. There are at least 96 bytes
to copy, so copy 16 bytes unaligned and then align. The loop
copies 64 bytes per iteration and prefetches one iteration ahead. */
.p2align 4
/* Medium copies: 33..128 bytes. */
L(copy32_128):
ldp A_l, A_h, [src]
ldp B_l, B_h, [src, 16]
ldp C_l, C_h, [srcend, -32]
ldp D_l, D_h, [srcend, -16]
cmp count, 64
b.hi L(copy128)
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstend, -32]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
/* Copy 65..128 bytes. */
L(copy128):
ldp E_l, E_h, [src, 32]
ldp F_l, F_h, [src, 48]
cmp count, 96
b.ls L(copy96)
ldp G_l, G_h, [srcend, -64]
ldp H_l, H_h, [srcend, -48]
stp G_l, G_h, [dstend, -64]
stp H_l, H_h, [dstend, -48]
L(copy96):
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp E_l, E_h, [dstin, 32]
stp F_l, F_h, [dstin, 48]
stp C_l, C_h, [dstend, -32]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
/* Copy more than 128 bytes. */
L(copy_long):
/* Copy 16 bytes and then align dst to 16-byte alignment. */
ldp D_l, D_h, [src]
and tmp1, dstin, 15
bic dst, dstin, 15
ldp D_l, D_h, [src]
sub src, src, tmp1
add count, count, tmp1 /* Count is now 16 too large. */
ldp A_l, A_h, [src, 16]
@@ -176,7 +175,8 @@ L(copy_long):
ldp C_l, C_h, [src, 48]
ldp D_l, D_h, [src, 64]!
subs count, count, 128 + 16 /* Test and readjust count. */
b.ls L(last64)
b.ls L(copy64_from_end)
L(loop64):
stp A_l, A_h, [dst, 16]
ldp A_l, A_h, [src, 16]
@@ -189,10 +189,8 @@ L(loop64):
subs count, count, 64
b.hi L(loop64)
/* Write the last full set of 64 bytes. The remainder is at most 64
bytes, so it is safe to always copy 64 bytes from the end even if
there is just 1 byte left. */
L(last64):
/* Write the last iteration and copy 64 bytes from the end. */
L(copy64_from_end):
ldp E_l, E_h, [srcend, -64]
stp A_l, A_h, [dst, 16]
ldp A_l, A_h, [srcend, -48]
@@ -207,20 +205,42 @@ L(last64):
stp C_l, C_h, [dstend, -16]
ret
.p2align 4
L(move_long):
cbz tmp1, 3f
END (MEMCPY)
libc_hidden_builtin_def (MEMCPY)
ENTRY_ALIGN (MEMMOVE, 4)
DELOUSE (0)
DELOUSE (1)
DELOUSE (2)
add srcend, src, count
add dstend, dstin, count
cmp count, 128
b.hi L(move_long)
cmp count, 32
b.hi L(copy32_128)
/* Align dstend to 16 byte alignment so that we don't cross cache line
boundaries on both loads and stores. There are at least 96 bytes
to copy, so copy 16 bytes unaligned and then align. The loop
copies 64 bytes per iteration and prefetches one iteration ahead. */
and tmp1, dstend, 15
/* Small copies: 0..32 bytes. */
cmp count, 16
b.lo L(copy16)
ldp A_l, A_h, [src]
ldp D_l, D_h, [srcend, -16]
stp A_l, A_h, [dstin]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
L(move_long):
/* Only use backward copy if there is an overlap. */
sub tmp1, dstin, src
cbz tmp1, L(copy0)
cmp tmp1, count
b.hs L(copy_long)
/* Large backwards copy for overlapping copies.
Copy 16 bytes and then align dst to 16-byte alignment. */
ldp D_l, D_h, [srcend, -16]
and tmp1, dstend, 15
sub srcend, srcend, tmp1
sub count, count, tmp1
ldp A_l, A_h, [srcend, -16]
@@ -230,10 +250,9 @@ L(move_long):
ldp D_l, D_h, [srcend, -64]!
sub dstend, dstend, tmp1
subs count, count, 128
b.ls 2f
b.ls L(copy64_from_start)
nop
1:
L(loop64_backwards):
stp A_l, A_h, [dstend, -16]
ldp A_l, A_h, [srcend, -16]
stp B_l, B_h, [dstend, -32]
@@ -243,12 +262,10 @@ L(move_long):
stp D_l, D_h, [dstend, -64]!
ldp D_l, D_h, [srcend, -64]!
subs count, count, 64
b.hi 1b
b.hi L(loop64_backwards)
/* Write the last full set of 64 bytes. The remainder is at most 64
bytes, so it is safe to always copy 64 bytes from the start even if
there is just 1 byte left. */
2:
/* Write the last iteration and copy 64 bytes from the start. */
L(copy64_from_start):
ldp G_l, G_h, [src, 48]
stp A_l, A_h, [dstend, -16]
ldp A_l, A_h, [src, 32]
@@ -261,7 +278,7 @@ L(move_long):
stp A_l, A_h, [dstin, 32]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstin]
3: ret
ret
END (MEMCPY)
libc_hidden_builtin_def (MEMCPY)
END (MEMMOVE)
libc_hidden_builtin_def (MEMMOVE)
+1 -1
View File
@@ -1,5 +1,5 @@
ifeq ($(subdir),string)
sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \
sysdep_routines += memcpy_generic memcpy_advsimd memcpy_thunderx memcpy_thunderx2 \
memcpy_falkor memmove_falkor \
memset_generic memset_falkor memset_emag \
memchr_generic memchr_nosimd \
@@ -42,11 +42,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_simd)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic))
IFUNC_IMPL (i, name, memmove,
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx)
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx2)
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor)
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_simd)
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic))
IFUNC_IMPL (i, name, memset,
/* Enable this on non-falkor processors too so that other cores
+6 -2
View File
@@ -29,6 +29,7 @@
extern __typeof (__redirect_memcpy) __libc_memcpy;
extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
extern __typeof (__redirect_memcpy) __memcpy_simd attribute_hidden;
extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden;
extern __typeof (__redirect_memcpy) __memcpy_thunderx2 attribute_hidden;
extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
@@ -36,11 +37,14 @@ extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
libc_ifunc (__libc_memcpy,
(IS_THUNDERX (midr)
? __memcpy_thunderx
: (IS_FALKOR (midr) || IS_PHECDA (midr) || IS_ARES (midr)
: (IS_FALKOR (midr) || IS_PHECDA (midr)
? __memcpy_falkor
: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr)
? __memcpy_thunderx2
: __memcpy_generic))));
: (IS_NEOVERSE_N1 (midr) || IS_NEOVERSE_N2 (midr)
|| IS_NEOVERSE_V1 (midr)
? __memcpy_simd
: __memcpy_generic)))));
# undef memcpy
strong_alias (__libc_memcpy, memcpy);
+248
View File
@@ -0,0 +1,248 @@
/* Generic optimized memcpy using SIMD.
Copyright (C) 2020 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 <sysdep.h>
/* Assumptions:
*
* ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
*
*/
#define dstin x0
#define src x1
#define count x2
#define dst x3
#define srcend x4
#define dstend x5
#define A_l x6
#define A_lw w6
#define A_h x7
#define B_l x8
#define B_lw w8
#define B_h x9
#define C_lw w10
#define tmp1 x14
#define A_q q0
#define B_q q1
#define C_q q2
#define D_q q3
#define E_q q4
#define F_q q5
#define G_q q6
#define H_q q7
/* This implementation supports both memcpy and memmove and shares most code.
It uses unaligned accesses and branchless sequences to keep the code small,
simple and improve performance.
Copies are split into 3 main cases: small copies of up to 32 bytes, medium
copies of up to 128 bytes, and large copies. The overhead of the overlap
check in memmove is negligible since it is only required for large copies.
Large copies use a software pipelined loop processing 64 bytes per
iteration. The destination pointer is 16-byte aligned to minimize
unaligned accesses. The loop tail is handled by always copying 64 bytes
from the end. */
ENTRY (__memcpy_simd)
DELOUSE (0)
DELOUSE (1)
DELOUSE (2)
add srcend, src, count
add dstend, dstin, count
cmp count, 128
b.hi L(copy_long)
cmp count, 32
b.hi L(copy32_128)
/* Small copies: 0..32 bytes. */
cmp count, 16
b.lo L(copy16)
ldr A_q, [src]
ldr B_q, [srcend, -16]
str A_q, [dstin]
str B_q, [dstend, -16]
ret
/* Copy 8-15 bytes. */
L(copy16):
tbz count, 3, L(copy8)
ldr A_l, [src]
ldr A_h, [srcend, -8]
str A_l, [dstin]
str A_h, [dstend, -8]
ret
/* Copy 4-7 bytes. */
L(copy8):
tbz count, 2, L(copy4)
ldr A_lw, [src]
ldr B_lw, [srcend, -4]
str A_lw, [dstin]
str B_lw, [dstend, -4]
ret
/* Copy 0..3 bytes using a branchless sequence. */
L(copy4):
cbz count, L(copy0)
lsr tmp1, count, 1
ldrb A_lw, [src]
ldrb C_lw, [srcend, -1]
ldrb B_lw, [src, tmp1]
strb A_lw, [dstin]
strb B_lw, [dstin, tmp1]
strb C_lw, [dstend, -1]
L(copy0):
ret
.p2align 4
/* Medium copies: 33..128 bytes. */
L(copy32_128):
ldp A_q, B_q, [src]
ldp C_q, D_q, [srcend, -32]
cmp count, 64
b.hi L(copy128)
stp A_q, B_q, [dstin]
stp C_q, D_q, [dstend, -32]
ret
.p2align 4
/* Copy 65..128 bytes. */
L(copy128):
ldp E_q, F_q, [src, 32]
cmp count, 96
b.ls L(copy96)
ldp G_q, H_q, [srcend, -64]
stp G_q, H_q, [dstend, -64]
L(copy96):
stp A_q, B_q, [dstin]
stp E_q, F_q, [dstin, 32]
stp C_q, D_q, [dstend, -32]
ret
/* Align loop64 below to 16 bytes. */
nop
/* Copy more than 128 bytes. */
L(copy_long):
/* Copy 16 bytes and then align src to 16-byte alignment. */
ldr D_q, [src]
and tmp1, src, 15
bic src, src, 15
sub dst, dstin, tmp1
add count, count, tmp1 /* Count is now 16 too large. */
ldp A_q, B_q, [src, 16]
str D_q, [dstin]
ldp C_q, D_q, [src, 48]
subs count, count, 128 + 16 /* Test and readjust count. */
b.ls L(copy64_from_end)
L(loop64):
stp A_q, B_q, [dst, 16]
ldp A_q, B_q, [src, 80]
stp C_q, D_q, [dst, 48]
ldp C_q, D_q, [src, 112]
add src, src, 64
add dst, dst, 64
subs count, count, 64
b.hi L(loop64)
/* Write the last iteration and copy 64 bytes from the end. */
L(copy64_from_end):
ldp E_q, F_q, [srcend, -64]
stp A_q, B_q, [dst, 16]
ldp A_q, B_q, [srcend, -32]
stp C_q, D_q, [dst, 48]
stp E_q, F_q, [dstend, -64]
stp A_q, B_q, [dstend, -32]
ret
END (__memcpy_simd)
libc_hidden_builtin_def (__memcpy_simd)
ENTRY (__memmove_simd)
DELOUSE (0)
DELOUSE (1)
DELOUSE (2)
add srcend, src, count
add dstend, dstin, count
cmp count, 128
b.hi L(move_long)
cmp count, 32
b.hi L(copy32_128)
/* Small moves: 0..32 bytes. */
cmp count, 16
b.lo L(copy16)
ldr A_q, [src]
ldr B_q, [srcend, -16]
str A_q, [dstin]
str B_q, [dstend, -16]
ret
L(move_long):
/* Only use backward copy if there is an overlap. */
sub tmp1, dstin, src
cbz tmp1, L(move0)
cmp tmp1, count
b.hs L(copy_long)
/* Large backwards copy for overlapping copies.
Copy 16 bytes and then align srcend to 16-byte alignment. */
L(copy_long_backwards):
ldr D_q, [srcend, -16]
and tmp1, srcend, 15
bic srcend, srcend, 15
sub count, count, tmp1
ldp A_q, B_q, [srcend, -32]
str D_q, [dstend, -16]
ldp C_q, D_q, [srcend, -64]
sub dstend, dstend, tmp1
subs count, count, 128
b.ls L(copy64_from_start)
L(loop64_backwards):
str B_q, [dstend, -16]
str A_q, [dstend, -32]
ldp A_q, B_q, [srcend, -96]
str D_q, [dstend, -48]
str C_q, [dstend, -64]!
ldp C_q, D_q, [srcend, -128]
sub srcend, srcend, 64
subs count, count, 64
b.hi L(loop64_backwards)
/* Write the last iteration and copy 64 bytes from the start. */
L(copy64_from_start):
ldp E_q, F_q, [src, 32]
stp A_q, B_q, [dstend, -32]
ldp A_q, B_q, [src]
stp C_q, D_q, [dstend, -64]
stp E_q, F_q, [dstin, 32]
stp A_q, B_q, [dstin]
L(move0):
ret
END (__memmove_simd)
libc_hidden_builtin_def (__memmove_simd)
+5 -1
View File
@@ -29,6 +29,7 @@
extern __typeof (__redirect_memmove) __libc_memmove;
extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_simd attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_thunderx2 attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden;
@@ -40,7 +41,10 @@ libc_ifunc (__libc_memmove,
? __memmove_falkor
: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr)
? __memmove_thunderx2
: __memmove_generic))));
: (IS_NEOVERSE_N1 (midr) || IS_NEOVERSE_N2 (midr)
|| IS_NEOVERSE_V1 (midr)
? __memmove_simd
: __memmove_generic)))));
# undef memmove
strong_alias (__libc_memmove, memmove);
+1 -1
View File
@@ -45,7 +45,7 @@
#define ENTRY(name) \
.globl C_SYMBOL_NAME(name); \
.type C_SYMBOL_NAME(name),%function; \
.align 4; \
.p2align 6; \
C_LABEL(name) \
cfi_startproc; \
CALL_MCOUNT
+8 -8
View File
@@ -1084,10 +1084,10 @@ ildouble: 1
ldouble: 1
Function: Real part of "cpow_downward":
double: 2
float: 4
idouble: 2
ifloat: 4
double: 5
float: 8
idouble: 5
ifloat: 8
ildouble: 6
ldouble: 6
@@ -1100,10 +1100,10 @@ ildouble: 2
ldouble: 2
Function: Real part of "cpow_towardzero":
double: 2
float: 4
idouble: 2
ifloat: 4
double: 5
float: 8
idouble: 5
ifloat: 8
ildouble: 6
ldouble: 6
+11 -11
View File
@@ -268,7 +268,7 @@ ENTRY(memcpy)
mov dst, dstin /* Preserve dstin, we need to return it. */
cmp count, #64
bge .Lcpy_not_short
bhs .Lcpy_not_short
/* Deal with small copies quickly by dropping straight into the
exit block. */
@@ -351,10 +351,10 @@ ENTRY(memcpy)
1:
subs tmp2, count, #64 /* Use tmp2 for count. */
blt .Ltail63aligned
blo .Ltail63aligned
cmp tmp2, #512
bge .Lcpy_body_long
bhs .Lcpy_body_long
.Lcpy_body_medium: /* Count in tmp2. */
#ifdef USE_VFP
@@ -378,7 +378,7 @@ ENTRY(memcpy)
add src, src, #64
vstr d1, [dst, #56]
add dst, dst, #64
bge 1b
bhs 1b
tst tmp2, #0x3f
beq .Ldone
@@ -412,7 +412,7 @@ ENTRY(memcpy)
ldrd A_l, A_h, [src, #64]!
strd A_l, A_h, [dst, #64]!
subs tmp2, tmp2, #64
bge 1b
bhs 1b
tst tmp2, #0x3f
bne 1f
ldr tmp2,[sp], #FRAME_SIZE
@@ -482,7 +482,7 @@ ENTRY(memcpy)
add src, src, #32
subs tmp2, tmp2, #prefetch_lines * 64 * 2
blt 2f
blo 2f
1:
cpy_line_vfp d3, 0
cpy_line_vfp d4, 64
@@ -494,7 +494,7 @@ ENTRY(memcpy)
add dst, dst, #2 * 64
add src, src, #2 * 64
subs tmp2, tmp2, #prefetch_lines * 64
bge 1b
bhs 1b
2:
cpy_tail_vfp d3, 0
@@ -615,8 +615,8 @@ ENTRY(memcpy)
1:
pld [src, #(3 * 64)]
subs count, count, #64
ldrmi tmp2, [sp], #FRAME_SIZE
bmi .Ltail63unaligned
ldrlo tmp2, [sp], #FRAME_SIZE
blo .Ltail63unaligned
pld [src, #(4 * 64)]
#ifdef USE_NEON
@@ -633,7 +633,7 @@ ENTRY(memcpy)
neon_load_multi d0-d3, src
neon_load_multi d4-d7, src
subs count, count, #64
bmi 2f
blo 2f
1:
pld [src, #(4 * 64)]
neon_store_multi d0-d3, dst
@@ -641,7 +641,7 @@ ENTRY(memcpy)
neon_store_multi d4-d7, dst
neon_load_multi d4-d7, src
subs count, count, #64
bpl 1b
bhs 1b
2:
neon_store_multi d0-d3, dst
neon_store_multi d4-d7, dst
+1
View File
@@ -0,0 +1 @@
arm/nofpu
+1
View File
@@ -0,0 +1 @@
arm/nofpu
+10 -14
View File
@@ -68,7 +68,7 @@ ENTRY(memcpy)
cfi_remember_state
subs r2, r2, #4
blt 8f
blo 8f
ands ip, r0, #3
PLD( pld [r1, #0] )
bne 9f
@@ -82,7 +82,7 @@ ENTRY(memcpy)
cfi_rel_offset (r6, 4)
cfi_rel_offset (r7, 8)
cfi_rel_offset (r8, 12)
blt 5f
blo 5f
CALGN( ands ip, r1, #31 )
CALGN( rsb r3, ip, #32 )
@@ -98,9 +98,9 @@ ENTRY(memcpy)
#endif
PLD( pld [r1, #0] )
2: PLD( subs r2, r2, #96 )
2: PLD( cmp r2, #96 )
PLD( pld [r1, #28] )
PLD( blt 4f )
PLD( blo 4f )
PLD( pld [r1, #60] )
PLD( pld [r1, #92] )
@@ -108,9 +108,7 @@ ENTRY(memcpy)
4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
subs r2, r2, #32
stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
bge 3b
PLD( cmn r2, #96 )
PLD( bge 4b )
bhs 3b
5: ands ip, r2, #28
rsb ip, ip, #32
@@ -222,7 +220,7 @@ ENTRY(memcpy)
strbge r4, [r0], #1
subs r2, r2, ip
strb lr, [r0], #1
blt 8b
blo 8b
ands ip, r1, #3
beq 1b
@@ -236,7 +234,7 @@ ENTRY(memcpy)
.macro forward_copy_shift pull push
subs r2, r2, #28
blt 14f
blo 14f
CALGN( ands ip, r1, #31 )
CALGN( rsb ip, ip, #32 )
@@ -253,9 +251,9 @@ ENTRY(memcpy)
cfi_rel_offset (r10, 16)
PLD( pld [r1, #0] )
PLD( subs r2, r2, #96 )
PLD( cmp r2, #96 )
PLD( pld [r1, #28] )
PLD( blt 13f )
PLD( blo 13f )
PLD( pld [r1, #60] )
PLD( pld [r1, #92] )
@@ -280,9 +278,7 @@ ENTRY(memcpy)
mov ip, ip, PULL #\pull
orr ip, ip, lr, PUSH #\push
stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip}
bge 12b
PLD( cmn r2, #96 )
PLD( bge 13b )
bhs 12b
pop {r5 - r8, r10}
cfi_adjust_cfa_offset (-20)
+10 -14
View File
@@ -85,7 +85,7 @@ ENTRY(memmove)
add r1, r1, r2
add r0, r0, r2
subs r2, r2, #4
blt 8f
blo 8f
ands ip, r0, #3
PLD( pld [r1, #-4] )
bne 9f
@@ -99,7 +99,7 @@ ENTRY(memmove)
cfi_rel_offset (r6, 4)
cfi_rel_offset (r7, 8)
cfi_rel_offset (r8, 12)
blt 5f
blo 5f
CALGN( ands ip, r1, #31 )
CALGN( sbcsne r4, ip, r2 ) @ C is always set here
@@ -114,9 +114,9 @@ ENTRY(memmove)
#endif
PLD( pld [r1, #-4] )
2: PLD( subs r2, r2, #96 )
2: PLD( cmp r2, #96 )
PLD( pld [r1, #-32] )
PLD( blt 4f )
PLD( blo 4f )
PLD( pld [r1, #-64] )
PLD( pld [r1, #-96] )
@@ -124,9 +124,7 @@ ENTRY(memmove)
4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
subs r2, r2, #32
stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
bge 3b
PLD( cmn r2, #96 )
PLD( bge 4b )
bhs 3b
5: ands ip, r2, #28
rsb ip, ip, #32
@@ -237,7 +235,7 @@ ENTRY(memmove)
strbge r4, [r0, #-1]!
subs r2, r2, ip
strb lr, [r0, #-1]!
blt 8b
blo 8b
ands ip, r1, #3
beq 1b
@@ -251,7 +249,7 @@ ENTRY(memmove)
.macro backward_copy_shift push pull
subs r2, r2, #28
blt 14f
blo 14f
CALGN( ands ip, r1, #31 )
CALGN( rsb ip, ip, #32 )
@@ -268,9 +266,9 @@ ENTRY(memmove)
cfi_rel_offset (r10, 16)
PLD( pld [r1, #-4] )
PLD( subs r2, r2, #96 )
PLD( cmp r2, #96 )
PLD( pld [r1, #-32] )
PLD( blt 13f )
PLD( blo 13f )
PLD( pld [r1, #-64] )
PLD( pld [r1, #-96] )
@@ -295,9 +293,7 @@ ENTRY(memmove)
mov r4, r4, PUSH #\push
orr r4, r4, r3, PULL #\pull
stmdb r0!, {r4 - r8, r10, ip, lr}
bge 12b
PLD( cmn r2, #96 )
PLD( bge 13b )
bhs 12b
pop {r5 - r8, r10}
cfi_adjust_cfa_offset (-20)
+2
View File
@@ -41,6 +41,8 @@
(void) __close (fd)
#define __read_nocancel(fd, buf, n) \
__read (fd, buf, n)
#define __pread64_nocancel(fd, buf, count, offset) \
__pread64 (fd, buf, count, offset)
#define __write_nocancel(fd, buf, n) \
__write (fd, buf, n)
#define __writev_nocancel_nostatus(fd, iov, n) \
+12 -22
View File
@@ -27,26 +27,16 @@
static int
__utmp_equal (const struct utmp *entry, const struct utmp *match)
{
return
(
#if _HAVE_UT_TYPE - 0
(entry->ut_type == INIT_PROCESS
|| entry->ut_type == LOGIN_PROCESS
|| entry->ut_type == USER_PROCESS
|| entry->ut_type == DEAD_PROCESS)
&&
(match->ut_type == INIT_PROCESS
|| match->ut_type == LOGIN_PROCESS
|| match->ut_type == USER_PROCESS
|| match->ut_type == DEAD_PROCESS)
&&
#endif
#if _HAVE_UT_ID - 0
(entry->ut_id[0] && match->ut_id[0]
? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
: strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0)
#else
strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0
#endif
);
return (entry->ut_type == INIT_PROCESS
|| entry->ut_type == LOGIN_PROCESS
|| entry->ut_type == USER_PROCESS
|| entry->ut_type == DEAD_PROCESS)
&& (match->ut_type == INIT_PROCESS
|| match->ut_type == LOGIN_PROCESS
|| match->ut_type == USER_PROCESS
|| match->ut_type == DEAD_PROCESS)
&& (entry->ut_id[0] && match->ut_id[0]
? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
: (strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line)
== 0));
}
-126
View File
@@ -1,126 +0,0 @@
/* The `struct utmp' type, describing entries in the utmp file. GNU version.
Copyright (C) 1993-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/>. */
#ifndef _UTMP_H
# error "Never include <bits/utmp.h> directly; use <utmp.h> instead."
#endif
#include <paths.h>
#include <sys/time.h>
#include <sys/types.h>
#include <bits/wordsize.h>
#define UT_LINESIZE 32
#define UT_NAMESIZE 32
#define UT_HOSTSIZE 256
/* The structure describing an entry in the database of
previous logins. */
struct lastlog
{
#if __WORDSIZE_TIME64_COMPAT32
int32_t ll_time;
#else
__time_t ll_time;
#endif
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
/* The structure describing the status of a terminated process. This
type is used in `struct utmp' below. */
struct exit_status
{
short int e_termination; /* Process termination status. */
short int e_exit; /* Process exit status. */
};
/* The structure describing an entry in the user accounting database. */
struct utmp
{
short int ut_type; /* Type of login. */
pid_t ut_pid; /* Process ID of login process. */
char ut_line[UT_LINESIZE]
__attribute_nonstring__; /* Devicename. */
char ut_id[4]; /* Inittab ID. */
char ut_user[UT_NAMESIZE]
__attribute_nonstring__; /* Username. */
char ut_host[UT_HOSTSIZE]
__attribute_nonstring__; /* Hostname for remote login. */
struct exit_status ut_exit; /* Exit status of a process marked
as DEAD_PROCESS. */
/* The ut_session and ut_tv fields must be the same size when compiled
32- and 64-bit. This allows data files and shared memory to be
shared between 32- and 64-bit applications. */
#if __WORDSIZE_TIME64_COMPAT32
int32_t ut_session; /* Session ID, used for windowing. */
struct
{
int32_t tv_sec; /* Seconds. */
int32_t tv_usec; /* Microseconds. */
} ut_tv; /* Time entry was made. */
#else
long int ut_session; /* Session ID, used for windowing. */
struct timeval ut_tv; /* Time entry was made. */
#endif
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
char __glibc_reserved[20]; /* Reserved for future use. */
};
/* Backwards compatibility hacks. */
#define ut_name ut_user
#ifndef _NO_UT_TIME
/* We have a problem here: `ut_time' is also used otherwise. Define
_NO_UT_TIME if the compiler complains. */
# define ut_time ut_tv.tv_sec
#endif
#define ut_xtime ut_tv.tv_sec
#define ut_addr ut_addr_v6[0]
/* Values for the `ut_type' field of a `struct utmp'. */
#define EMPTY 0 /* No valid user accounting information. */
#define RUN_LVL 1 /* The system's runlevel. */
#define BOOT_TIME 2 /* Time of system boot. */
#define NEW_TIME 3 /* Time after system clock changed. */
#define OLD_TIME 4 /* Time when system clock changed. */
#define INIT_PROCESS 5 /* Process spawned by the init process. */
#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
#define USER_PROCESS 7 /* Normal process. */
#define DEAD_PROCESS 8 /* Terminated process. */
#define ACCOUNTING 9
/* Old Linux name for the EMPTY type. */
#define UT_UNKNOWN EMPTY
/* Tell the user that we have a modern system with UT_HOST, UT_PID,
UT_TYPE, UT_ID and UT_TV fields. */
#define _HAVE_UT_TYPE 1
#define _HAVE_UT_PID 1
#define _HAVE_UT_ID 1
#define _HAVE_UT_TV 1
#define _HAVE_UT_HOST 1
+8 -4
View File
@@ -56,10 +56,14 @@ struct utmpx
{
short int ut_type; /* Type of login. */
__pid_t ut_pid; /* Process ID of login process. */
char ut_line[__UT_LINESIZE]; /* Devicename. */
char ut_id[4]; /* Inittab ID. */
char ut_user[__UT_NAMESIZE]; /* Username. */
char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */
char ut_line[__UT_LINESIZE]
__attribute_nonstring__; /* Devicename. */
char ut_id[4]
__attribute_nonstring__; /* Inittab ID. */
char ut_user[__UT_NAMESIZE]
__attribute_nonstring__; /* Username. */
char ut_host[__UT_HOSTSIZE]
__attribute_nonstring__; /* Hostname for remote login. */
struct __exit_status ut_exit; /* Exit status of a process marked
as DEAD_PROCESS. */
+20 -6
View File
@@ -172,8 +172,8 @@ make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp)
}
install:
fdesc->ip = ip;
fdesc->gp = gp;
fdesc->ip = ip;
return (ElfW(Addr)) fdesc;
}
@@ -350,7 +350,9 @@ ElfW(Addr)
_dl_lookup_address (const void *address)
{
ElfW(Addr) addr = (ElfW(Addr)) address;
unsigned int *desc, *gptr;
ElfW(Word) reloc_arg;
volatile unsigned int *desc;
unsigned int *gptr;
/* Return ADDR if the least-significant two bits of ADDR are not consistent
with ADDR being a linker defined function pointer. The normal value for
@@ -367,7 +369,11 @@ _dl_lookup_address (const void *address)
if (!_dl_read_access_allowed (desc))
return addr;
/* Load first word of candidate descriptor. It should be a pointer
/* First load the relocation offset. */
reloc_arg = (ElfW(Word)) desc[1];
atomic_full_barrier();
/* Then load first word of candidate descriptor. It should be a pointer
with word alignment and point to memory that can be read. */
gptr = (unsigned int *) desc[0];
if (((unsigned int) gptr & 3) != 0
@@ -377,8 +383,8 @@ _dl_lookup_address (const void *address)
/* See if descriptor requires resolution. The following trampoline is
used in each global offset table for function resolution:
ldw 0(r20),r22
bv r0(r22)
ldw 0(r20),r21
bv r0(r21)
ldw 4(r20),r21
tramp: b,l .-12,r20
depwi 0,31,2,r20
@@ -389,7 +395,15 @@ _dl_lookup_address (const void *address)
if (gptr[0] == 0xea9f1fdd /* b,l .-12,r20 */
&& gptr[1] == 0xd6801c1e /* depwi 0,31,2,r20 */
&& (ElfW(Addr)) gptr[2] == elf_machine_resolve ())
_dl_fixup ((struct link_map *) gptr[5], (ElfW(Word)) desc[1]);
{
struct link_map *l = (struct link_map *) gptr[5];
/* If gp has been resolved, we need to hunt for relocation offset. */
if (!(reloc_arg & PA_GP_RELOC))
reloc_arg = _dl_fix_reloc_arg (addr, l);
_dl_fixup (l, reloc_arg);
}
return (ElfW(Addr)) desc[0];
}
+31 -5
View File
@@ -48,6 +48,14 @@
#define GOT_FROM_PLT_STUB (4*4)
#define PLT_ENTRY_SIZE (2*4)
/* The gp slot in the function descriptor contains the relocation offset
before resolution. To distinguish between a resolved gp value and an
unresolved relocation offset we set an unused bit in the relocation
offset. This would allow us to do a synchronzied two word update
using this bit (interlocked update), but instead of waiting for the
update we simply recompute the gp value given that we know the ip. */
#define PA_GP_RELOC 1
/* Initialize the function descriptor table before relocations */
static inline void
__hppa_init_bootstrap_fdesc_table (struct link_map *map)
@@ -117,10 +125,28 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t,
volatile Elf32_Addr *rfdesc = reloc_addr;
/* map is the link_map for the caller, t is the link_map for the object
being called */
rfdesc[1] = value.gp;
/* Need to ensure that the gp is visible before the code
entry point is updated */
rfdesc[0] = value.ip;
/* We would like the function descriptor to be double word aligned. This
helps performance (ip and gp then reside on the same cache line) and
we can update the pair atomically with a single store. The linker
now ensures this alignment but we still have to handle old code. */
if ((unsigned int)reloc_addr & 7)
{
/* Need to ensure that the gp is visible before the code
entry point is updated */
rfdesc[1] = value.gp;
atomic_full_barrier();
rfdesc[0] = value.ip;
}
else
{
/* Update pair atomically with floating point store. */
union { ElfW(Word) v[2]; double d; } u;
u.v[0] = value.ip;
u.v[1] = value.gp;
*(volatile double *)rfdesc = u.d;
}
return value;
}
@@ -265,7 +291,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
here. The trampoline code will load the proper
LTP and pass the reloc offset to the fixup
function. */
fptr->gp = iplt - jmprel;
fptr->gp = (iplt - jmprel) | PA_GP_RELOC;
} /* r_sym != 0 */
else
{
+58
View File
@@ -0,0 +1,58 @@
/* On-demand PLT fixup for shared objects. HPPA version.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Clear PA_GP_RELOC bit in relocation offset. */
#define reloc_offset (reloc_arg & ~PA_GP_RELOC)
#define reloc_index (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL)
#include <elf/dl-runtime.c>
/* The caller has encountered a partially relocated function descriptor.
The gp of the descriptor has been updated, but not the ip. We find
the function descriptor again and compute the relocation offset and
return that to the caller. The caller will continue on to call
_dl_fixup with the relocation offset. */
ElfW(Word)
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l)
{
Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type;
const Elf32_Rela *reloc;
l_addr = l->l_addr;
jmprel = D_PTR(l, l_info[DT_JMPREL]);
end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val;
/* Look for the entry... */
for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
{
reloc = (const Elf32_Rela *) iplt;
r_type = ELF32_R_TYPE (reloc->r_info);
if (__builtin_expect (r_type == R_PARISC_IPLT, 1)
&& fptr == (struct fdesc *) (reloc->r_offset + l_addr))
/* Found entry. Return the reloc offset. */
return iplt - jmprel;
}
/* Crash if we weren't passed a valid function pointer. */
ABORT_INSTRUCTION;
return 0;
}
+63 -11
View File
@@ -31,7 +31,7 @@
slow down __cffc when it attempts to call fixup to resolve function
descriptor references. Please refer to gcc/gcc/config/pa/fptr.c
Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */
Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp, r22 = fp. */
/* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */
.text
@@ -61,17 +61,20 @@ _dl_runtime_resolve:
copy %sp, %r1 /* Copy previous sp */
/* Save function result address (on entry) */
stwm %r28,128(%sp)
/* Fillin some frame info to follow ABI */
/* Fill in some frame info to follow ABI */
stw %r1,-4(%sp) /* Previous sp */
stw %r21,-32(%sp) /* PIC register value */
/* Save input floating point registers. This must be done
in the new frame since the previous frame doesn't have
enough space */
ldo -56(%sp),%r1
ldo -64(%sp),%r1
fstd,ma %fr4,-8(%r1)
fstd,ma %fr5,-8(%r1)
fstd,ma %fr6,-8(%r1)
/* Test PA_GP_RELOC bit. */
bb,>= %r19,31,2f /* branch if not reloc offset */
fstd,ma %fr7,-8(%r1)
/* Set up args to fixup func, needs only two arguments */
@@ -79,7 +82,7 @@ _dl_runtime_resolve:
copy %r19,%r25 /* (2) reloc offset */
/* Call the real address resolver. */
bl _dl_fixup,%rp
3: bl _dl_fixup,%rp
copy %r21,%r19 /* set fixup func ltp */
/* While the linker will set a function pointer to NULL when it
@@ -102,7 +105,7 @@ _dl_runtime_resolve:
copy %r29, %r19
/* Reload arguments fp args */
ldo -56(%sp),%r1
ldo -64(%sp),%r1
fldd,ma -8(%r1),%fr4
fldd,ma -8(%r1),%fr5
fldd,ma -8(%r1),%fr6
@@ -129,6 +132,25 @@ _dl_runtime_resolve:
bv %r0(%rp)
ldo -128(%sp),%sp
2:
/* Set up args for _dl_fix_reloc_arg. */
copy %r22,%r26 /* (1) function pointer */
depi 0,31,2,%r26 /* clear least significant bits */
ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */
/* Save ltp and link map arg for _dl_fixup. */
stw %r21,-56(%sp) /* ltp */
stw %r25,-60(%sp) /* struct link map */
/* Find reloc offset. */
bl _dl_fix_reloc_arg,%rp
copy %r21,%r19 /* set func ltp */
/* Set up args for _dl_fixup. */
ldw -56(%sp),%r21 /* ltp */
ldw -60(%sp),%r26 /* (1) struct link map */
b 3b
copy %ret0,%r25 /* (2) reloc offset */
.EXIT
.PROCEND
cfi_endproc
@@ -153,7 +175,7 @@ _dl_runtime_profile:
copy %sp, %r1 /* Copy previous sp */
/* Save function result address (on entry) */
stwm %r28,192(%sp)
/* Fillin some frame info to follow ABI */
/* Fill in some frame info to follow ABI */
stw %r1,-4(%sp) /* Previous sp */
stw %r21,-32(%sp) /* PIC register value */
@@ -181,10 +203,11 @@ _dl_runtime_profile:
fstd,ma %fr5,8(%r1)
fstd,ma %fr6,8(%r1)
fstd,ma %fr7,8(%r1)
/* 32-bit stack pointer and return register */
stw %sp,-56(%sp)
stw %r2,-52(%sp)
/* Test PA_GP_RELOC bit. */
bb,>= %r19,31,2f /* branch if not reloc offset */
/* 32-bit stack pointer */
stw %sp,-56(%sp)
/* Set up args to fixup func, needs five arguments */
ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */
@@ -197,7 +220,7 @@ _dl_runtime_profile:
stw %r1, -52(%sp) /* (5) long int *framesizep */
/* Call the real address resolver. */
bl _dl_profile_fixup,%rp
3: bl _dl_profile_fixup,%rp
copy %r21,%r19 /* set fixup func ltp */
/* Load up the returned function descriptor */
@@ -215,7 +238,9 @@ _dl_runtime_profile:
fldd,ma 8(%r1),%fr5
fldd,ma 8(%r1),%fr6
fldd,ma 8(%r1),%fr7
ldw -52(%sp),%rp
/* Reload rp register -(192+20) without adjusting stack */
ldw -212(%sp),%rp
/* Reload static link register -(192+16) without adjusting stack */
ldw -208(%sp),%r29
@@ -303,6 +328,33 @@ L(cont):
ldw -20(%sp),%rp
/* Return */
bv,n 0(%r2)
2:
/* Set up args for _dl_fix_reloc_arg. */
copy %r22,%r26 /* (1) function pointer */
depi 0,31,2,%r26 /* clear least significant bits */
ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */
/* Save ltp and link map arg for _dl_fixup. */
stw %r21,-92(%sp) /* ltp */
stw %r25,-116(%sp) /* struct link map */
/* Find reloc offset. */
bl _dl_fix_reloc_arg,%rp
copy %r21,%r19 /* set func ltp */
/* Restore fixup ltp. */
ldw -92(%sp),%r21 /* ltp */
/* Set up args to fixup func, needs five arguments */
ldw -116(%sp),%r26 /* (1) struct link map */
copy %ret0,%r25 /* (2) reloc offset */
stw %r25,-120(%sp) /* Save reloc offset */
ldw -212(%sp),%r24 /* (3) profile_fixup needs rp */
ldo -56(%sp),%r23 /* (4) La_hppa_regs */
ldo -112(%sp), %r1
b 3b
stw %r1, -52(%sp) /* (5) long int *framesizep */
.EXIT
.PROCEND
cfi_endproc
+46 -46
View File
@@ -544,9 +544,9 @@ idouble: 1
ifloat: 1
Function: Imaginary part of "ccos_downward":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Real part of "ccos_towardzero":
@@ -556,9 +556,9 @@ idouble: 1
ifloat: 2
Function: Imaginary part of "ccos_towardzero":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Real part of "ccos_upward":
@@ -588,29 +588,29 @@ idouble: 1
ifloat: 1
Function: Real part of "ccosh_downward":
double: 1
double: 2
float: 3
idouble: 1
idouble: 2
ifloat: 3
Function: Imaginary part of "ccosh_downward":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Real part of "ccosh_towardzero":
double: 1
float: 3
idouble: 1
ifloat: 3
Function: Imaginary part of "ccosh_towardzero":
double: 2
float: 3
idouble: 2
ifloat: 3
Function: Imaginary part of "ccosh_towardzero":
double: 3
float: 3
idouble: 3
ifloat: 3
Function: Real part of "ccosh_upward":
double: 1
float: 2
@@ -636,27 +636,27 @@ idouble: 1
ifloat: 2
Function: Real part of "cexp_downward":
double: 1
double: 2
float: 2
idouble: 1
idouble: 2
ifloat: 2
Function: Imaginary part of "cexp_downward":
double: 1
double: 3
float: 3
idouble: 1
idouble: 3
ifloat: 3
Function: Real part of "cexp_towardzero":
double: 1
double: 2
float: 2
idouble: 1
idouble: 2
ifloat: 2
Function: Imaginary part of "cexp_towardzero":
double: 1
double: 3
float: 3
idouble: 1
idouble: 3
ifloat: 3
Function: Real part of "cexp_upward":
@@ -666,9 +666,9 @@ idouble: 1
ifloat: 2
Function: Imaginary part of "cexp_upward":
double: 1
double: 3
float: 2
idouble: 1
idouble: 3
ifloat: 2
Function: Real part of "clog":
@@ -800,21 +800,21 @@ idouble: 1
ifloat: 1
Function: "cosh_downward":
double: 1
double: 2
float: 1
idouble: 1
idouble: 2
ifloat: 1
Function: "cosh_towardzero":
double: 1
double: 2
float: 1
idouble: 1
idouble: 2
ifloat: 1
Function: "cosh_upward":
double: 1
double: 2
float: 2
idouble: 1
idouble: 2
ifloat: 2
Function: Real part of "cpow":
@@ -834,9 +834,9 @@ ildouble: 2
ldouble: 2
Function: Real part of "cpow_downward":
double: 4
double: 5
float: 8
idouble: 4
idouble: 5
ifloat: 8
Function: Imaginary part of "cpow_downward":
@@ -846,9 +846,9 @@ idouble: 2
ifloat: 2
Function: Real part of "cpow_towardzero":
double: 4
double: 5
float: 8
idouble: 4
idouble: 5
ifloat: 8
Function: Imaginary part of "cpow_towardzero":
@@ -876,9 +876,9 @@ idouble: 1
ifloat: 1
Function: Real part of "csin_downward":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Imaginary part of "csin_downward":
@@ -888,9 +888,9 @@ idouble: 1
ifloat: 2
Function: Real part of "csin_towardzero":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Imaginary part of "csin_towardzero":
@@ -930,9 +930,9 @@ idouble: 2
ifloat: 2
Function: Imaginary part of "csinh_downward":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Real part of "csinh_towardzero":
@@ -942,9 +942,9 @@ idouble: 2
ifloat: 2
Function: Imaginary part of "csinh_towardzero":
double: 2
double: 3
float: 3
idouble: 2
idouble: 3
ifloat: 3
Function: Real part of "csinh_upward":
@@ -1172,15 +1172,15 @@ ildouble: 6
ldouble: 6
Function: "exp10_downward":
double: 2
double: 3
float: 1
idouble: 2
idouble: 3
ifloat: 1
Function: "exp10_towardzero":
double: 2
double: 3
float: 1
idouble: 2
idouble: 3
ifloat: 1
Function: "exp10_upward":

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