forked from rpms/glibc
Sync with Fedora f34 branch (glibc-2.33-11)
Fedora commit: 4f55bd2df5c705c99f21e1d35941843212b3e3a1 Related: #1945473 Resolves: #1945472 Resolves: #1915330
This commit is contained in:
parent
0d047500d2
commit
83835daada
9595
ChangeLog.old
9595
ChangeLog.old
File diff suppressed because it is too large
Load Diff
64
glibc-cpu-check-1.patch
Normal file
64
glibc-cpu-check-1.patch
Normal file
@ -0,0 +1,64 @@
|
||||
Downstream-only patch to enhance CPU detection. Review thread:
|
||||
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-May/125916.html>
|
||||
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu May 6 11:54:52 2021 +0200
|
||||
|
||||
elf: Add hook for checking HWCAP bits after auxiliary vector parsing
|
||||
|
||||
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
|
||||
index 0658c17da632efa5..657d74597e64045f 100644
|
||||
--- a/elf/dl-sysdep.c
|
||||
+++ b/elf/dl-sysdep.c
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include <dl-tunables.h>
|
||||
#include <dl-auxv.h>
|
||||
+#include <dl-hwcap-check.h>
|
||||
|
||||
extern char **_environ attribute_hidden;
|
||||
extern char _end[] attribute_hidden;
|
||||
@@ -182,6 +183,8 @@ _dl_sysdep_start (void **start_argptr,
|
||||
DL_PLATFORM_AUXV
|
||||
}
|
||||
|
||||
+ dl_hwcap_check ();
|
||||
+
|
||||
#ifndef HAVE_AUX_SECURE
|
||||
if (seen != -1)
|
||||
{
|
||||
diff --git a/sysdeps/generic/dl-hwcap-check.h b/sysdeps/generic/dl-hwcap-check.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..8db7a86256c9c724
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/generic/dl-hwcap-check.h
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* Check for hardware capabilities after HWCAP parsing. Generic version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _DL_HWCAP_CHECK_H
|
||||
+#define _DL_HWCAP_CHECK_H
|
||||
+
|
||||
+static inline void
|
||||
+dl_hwcap_check (void)
|
||||
+{
|
||||
+ /* The generic implementation does not perform any checks. */
|
||||
+}
|
||||
+
|
||||
+#endif /* _DL_HWCAP_CHECK_H */
|
73
glibc-cpu-check-2.patch
Normal file
73
glibc-cpu-check-2.patch
Normal file
@ -0,0 +1,73 @@
|
||||
Downstream-only patch to enhance CPU detection. Review thread:
|
||||
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-May/125916.html>
|
||||
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu May 6 11:55:09 2021 +0200
|
||||
|
||||
powerpc64le: Check HWCAP bits against compiler build flags
|
||||
|
||||
When built with GCC 11.1 and -mcpu=power9, ld.so prints this error
|
||||
message when running on POWER8:
|
||||
|
||||
Fatal glibc error: CPU lacks ISA 3.00 support (POWER9 or later required)
|
||||
|
||||
This approach does not work for the POWER10 because the bootstrap
|
||||
relocation already uses PCREL instructions, so the detection code does
|
||||
not actually run.
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..6c7949c6d27ab0b4
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
|
||||
@@ -0,0 +1,49 @@
|
||||
+/* Check for hardware capabilities after HWCAP parsing. powerpc64le version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _DL_HWCAP_CHECK_H
|
||||
+#define _DL_HWCAP_CHECK_H
|
||||
+
|
||||
+#include <ldsodefs.h>
|
||||
+
|
||||
+static inline void
|
||||
+dl_hwcap_check (void)
|
||||
+{
|
||||
+#ifdef _ARCH_PWR9
|
||||
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_00) == 0)
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks ISA 3.00 support (POWER9 or later required)\n");
|
||||
+#endif
|
||||
+#ifdef __FLOAT128_HARDWARE__
|
||||
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_IEEE128) == 0)
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks float128 support (POWER 9 or later required)\n");
|
||||
+#endif
|
||||
+#if defined _ARCH_PWR10 || defined __PCREL__
|
||||
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_1) == 0)
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks ISA 3.10 support (POWER10 or later required)\n");
|
||||
+#endif
|
||||
+#ifdef __MMA__
|
||||
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_MMA) == 0)
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks MMA support (POWER10 or later required)\n");
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#endif /* _DL_HWCAP_CHECK_H */
|
62
glibc-cpu-check-3.patch
Normal file
62
glibc-cpu-check-3.patch
Normal file
@ -0,0 +1,62 @@
|
||||
Downstream-only patch to enhance CPU detection. Review thread:
|
||||
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-May/125916.html>
|
||||
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu May 6 11:58:02 2021 +0200
|
||||
|
||||
s390x: Check HWCAP bits against compiler flags
|
||||
|
||||
When compiled with GCC 11.1 and -march=z14 -O3 build flags, running
|
||||
ld.so (or any dynamically linked program) prints:
|
||||
|
||||
Fatal glibc error: CPU lacks VXE support (z14 or later required)
|
||||
|
||||
Co-Authored-By: Stefan Liebler <stli@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..87e18be6bd0c512b
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
|
||||
@@ -0,0 +1,40 @@
|
||||
+/* Check for hardware capabilities after HWCAP parsing. S390 version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _DL_HWCAP_CHECK_H
|
||||
+#define _DL_HWCAP_CHECK_H
|
||||
+
|
||||
+#include <ldsodefs.h>
|
||||
+
|
||||
+static inline void
|
||||
+dl_hwcap_check (void)
|
||||
+{
|
||||
+#if defined __ARCH__
|
||||
+# if __ARCH__ >= 13
|
||||
+ if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_EXT2))
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n");
|
||||
+# elif __ARCH__ >= 12
|
||||
+ if (!(GLRO(dl_hwcap) & HWCAP_S390_VXE))
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");
|
||||
+# endif
|
||||
+#endif /* __ARCH__ */
|
||||
+}
|
||||
+
|
||||
+#endif /* _DL_HWCAP_CHECK_H */
|
@ -1,28 +0,0 @@
|
||||
Add diagnostics for missing z14 support. Not yet upstream. Discussion
|
||||
is here:
|
||||
|
||||
s390x: Diagnose missing VXE at run time if required at build time
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-April/124834.html>
|
||||
|
||||
The approach implemented by upstream will likely be slightly different
|
||||
(if upstream takes the patch at all). dl_platform_init does not work
|
||||
for POWER because POWER9 instructions are used in __tunables_init,
|
||||
which is called before DL_PLATFORM_INIT/dl_platform_init.
|
||||
|
||||
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
|
||||
index 543361c83637c071..deaf37951206fb7c 100644
|
||||
--- a/sysdeps/s390/s390-64/dl-machine.h
|
||||
+++ b/sysdeps/s390/s390-64/dl-machine.h
|
||||
@@ -235,6 +235,12 @@ _dl_start_user:\n\
|
||||
static inline void __attribute__ ((unused))
|
||||
dl_platform_init (void)
|
||||
{
|
||||
+#ifdef __LONG_DOUBLE_VX__
|
||||
+ if (!(GLRO(dl_hwcap) & HWCAP_S390_VXE))
|
||||
+ _dl_fatal_printf ("\
|
||||
+Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");
|
||||
+#endif
|
||||
+
|
||||
if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
|
||||
/* Avoid an empty string which would disturb us. */
|
||||
GLRO(dl_platform) = NULL;
|
100
glibc-upstream-2.33-20.patch
Normal file
100
glibc-upstream-2.33-20.patch
Normal file
@ -0,0 +1,100 @@
|
||||
commit fc4ecce85b5ce10f64ae1328f4105ace8d7b7b67
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Mar 23 17:29:26 2021 +0100
|
||||
|
||||
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 7759be2593b689cb1eafc0f52ee7f59c639e5d2f)
|
||||
|
||||
diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure
|
||||
index 5f98640d0fc54264..7eaefbabcfebdce7 100644
|
||||
--- a/sysdeps/s390/configure
|
||||
+++ b/sysdeps/s390/configure
|
||||
@@ -123,7 +123,9 @@ void testinsn (char *buf)
|
||||
__asm__ (".machine \"arch13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"lghi %%r0,16 \n\t"
|
||||
- "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
|
||||
+ "mvcrl 0(%0),32(%0) \n\t"
|
||||
+ "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
|
||||
+ : : "a" (buf) : "memory", "r0");
|
||||
}
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
@@ -271,7 +273,9 @@ else
|
||||
void testinsn (char *buf)
|
||||
{
|
||||
__asm__ ("lghi %%r0,16 \n\t"
|
||||
- "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
|
||||
+ "mvcrl 0(%0),32(%0) \n\t"
|
||||
+ "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
|
||||
+ : : "a" (buf) : "memory", "r0");
|
||||
}
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac
|
||||
index dfe007a774d7e1ed..e6df62491907c8b5 100644
|
||||
--- a/sysdeps/s390/configure.ac
|
||||
+++ b/sysdeps/s390/configure.ac
|
||||
@@ -88,7 +88,9 @@ void testinsn (char *buf)
|
||||
__asm__ (".machine \"arch13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"lghi %%r0,16 \n\t"
|
||||
- "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
|
||||
+ "mvcrl 0(%0),32(%0) \n\t"
|
||||
+ "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
|
||||
+ : : "a" (buf) : "memory", "r0");
|
||||
}
|
||||
EOF
|
||||
dnl test, if assembler supports S390 arch13 instructions
|
||||
@@ -195,7 +197,9 @@ cat > conftest.c <<\EOF
|
||||
void testinsn (char *buf)
|
||||
{
|
||||
__asm__ ("lghi %%r0,16 \n\t"
|
||||
- "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0");
|
||||
+ "mvcrl 0(%0),32(%0) \n\t"
|
||||
+ "vstrs %%v20,%%v20,%%v20,%%v20,0,2"
|
||||
+ : : "a" (buf) : "memory", "r0");
|
||||
}
|
||||
EOF
|
||||
dnl test, if assembler supports S390 arch13 zarch instructions as default
|
||||
diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c
|
||||
index f88ea79d97a3b547..1a7d3369f21e4a4e 100644
|
||||
--- a/sysdeps/s390/memmove.c
|
||||
+++ b/sysdeps/s390/memmove.c
|
||||
@@ -43,7 +43,7 @@ extern __typeof (__redirect_memmove) MEMMOVE_ARCH13 attribute_hidden;
|
||||
s390_libc_ifunc_expr (__redirect_memmove, memmove,
|
||||
({
|
||||
s390_libc_ifunc_expr_stfle_init ();
|
||||
- (HAVE_MEMMOVE_ARCH13
|
||||
+ (HAVE_MEMMOVE_ARCH13 && (hwcap & HWCAP_S390_VXRS_EXT2)
|
||||
&& S390_IS_ARCH13_MIE3 (stfle_bits))
|
||||
? MEMMOVE_ARCH13
|
||||
: (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 4b170e4459d917dc..2ef38b72ddac7c18 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -171,7 +171,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, memmove,
|
||||
# if HAVE_MEMMOVE_ARCH13
|
||||
IFUNC_IMPL_ADD (array, i, memmove,
|
||||
- S390_IS_ARCH13_MIE3 (stfle_bits),
|
||||
+ ((dl_hwcap & HWCAP_S390_VXRS_EXT2)
|
||||
+ && S390_IS_ARCH13_MIE3 (stfle_bits)),
|
||||
MEMMOVE_ARCH13)
|
||||
# endif
|
||||
# if HAVE_MEMMOVE_Z13
|
32
glibc-upstream-2.33-21.patch
Normal file
32
glibc-upstream-2.33-21.patch
Normal file
@ -0,0 +1,32 @@
|
||||
commit 98bb18f52a7c576e6068f4b42dea5b24fa6fd81e
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 25 14:49:58 2021 +0000
|
||||
|
||||
malloc: Fix a realloc crash with heap tagging [BZ 27468]
|
||||
|
||||
_int_free must be called with a chunk that has its tag reset. This was
|
||||
missing in a rare case that could crash when heap tagging is enabled:
|
||||
when in a multi-threaded process the current arena runs out of memory
|
||||
during realloc, but another arena still has space to finish the realloc
|
||||
then _int_free was called without clearing the user allocation tags.
|
||||
|
||||
Fixes bug 27468.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 42cc96066b22ba065db11096c78881a55e45def4)
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 1f4bbd8edf8b9770..8f8f12c276812405 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -3446,7 +3446,9 @@ __libc_realloc (void *oldmem, size_t bytes)
|
||||
newp = __libc_malloc (bytes);
|
||||
if (newp != NULL)
|
||||
{
|
||||
- memcpy (newp, oldmem, oldsize - SIZE_SZ);
|
||||
+ size_t sz = CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ;
|
||||
+ memcpy (newp, oldmem, sz);
|
||||
+ (void) TAG_REGION (chunk2rawmem (oldp), sz);
|
||||
_int_free (ar_ptr, oldp, 0);
|
||||
}
|
||||
}
|
62
glibc-upstream-2.33-22.patch
Normal file
62
glibc-upstream-2.33-22.patch
Normal file
@ -0,0 +1,62 @@
|
||||
commit e78ea9bd26199497b9f047e421f16284297629cf
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Thu Apr 1 20:14:50 2021 +0000
|
||||
|
||||
Update Nios II libm-test-ulps.
|
||||
|
||||
This has a subset of the changes in the version applied to master
|
||||
(only those that actually appear in a regeneration on 2.33 branch).
|
||||
|
||||
diff --git a/sysdeps/nios2/libm-test-ulps b/sysdeps/nios2/libm-test-ulps
|
||||
index 8c3e9df547804b9d..9315ba82fab5bd5a 100644
|
||||
--- a/sysdeps/nios2/libm-test-ulps
|
||||
+++ b/sysdeps/nios2/libm-test-ulps
|
||||
@@ -12,7 +12,7 @@ Function: "asin":
|
||||
float: 1
|
||||
|
||||
Function: "asinh":
|
||||
-double: 1
|
||||
+double: 2
|
||||
float: 2
|
||||
|
||||
Function: "atan":
|
||||
@@ -80,7 +80,7 @@ double: 1
|
||||
float: 1
|
||||
|
||||
Function: "cbrt":
|
||||
-double: 3
|
||||
+double: 4
|
||||
float: 1
|
||||
|
||||
Function: Real part of "ccos":
|
||||
@@ -127,7 +127,7 @@ double: 1
|
||||
float: 1
|
||||
|
||||
Function: "cosh":
|
||||
-double: 1
|
||||
+double: 2
|
||||
float: 2
|
||||
|
||||
Function: Real part of "cpow":
|
||||
@@ -177,10 +177,11 @@ double: 1
|
||||
float: 1
|
||||
|
||||
Function: "erfc":
|
||||
-double: 3
|
||||
+double: 5
|
||||
float: 3
|
||||
|
||||
Function: "exp":
|
||||
+double: 1
|
||||
float: 1
|
||||
|
||||
Function: "exp10":
|
||||
@@ -256,7 +257,7 @@ double: 2
|
||||
float: 2
|
||||
|
||||
Function: "tgamma":
|
||||
-double: 5
|
||||
+double: 9
|
||||
float: 8
|
||||
|
||||
Function: "y0":
|
110
glibc-upstream-2.33-23.patch
Normal file
110
glibc-upstream-2.33-23.patch
Normal file
@ -0,0 +1,110 @@
|
||||
commit 830674605ffaa6213f951198501d585fff1b15fe
|
||||
Author: Lukasz Majewski <lukma@denx.de>
|
||||
Date: Sat Mar 13 23:34:21 2021 +0100
|
||||
|
||||
tst: Provide test for select
|
||||
|
||||
This change adds new test to assess select()'s timeout related
|
||||
functionality (the rdfs set provides valid fd - stderr - but during
|
||||
normal program operation there is no data to be read, so one just
|
||||
waits for timeout).
|
||||
|
||||
To be more specific - two use cases are checked:
|
||||
- if select() times out immediately when passed struct timeval has
|
||||
zero values of tv_usec and tv_sec.
|
||||
- if select() times out after timeout specified in passed argument
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
(cherry picked from commit bff3019afc77eb51634471827daaa1c17a6dc5bd)
|
||||
|
||||
diff --git a/misc/Makefile b/misc/Makefile
|
||||
index b08d7c68ab25d5a8..05ad034bafdc4ec7 100644
|
||||
--- a/misc/Makefile
|
||||
+++ b/misc/Makefile
|
||||
@@ -88,7 +88,7 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
|
||||
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
|
||||
tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
|
||||
tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
|
||||
- tst-mntent-autofs tst-syscalls tst-mntent-escape
|
||||
+ tst-mntent-autofs tst-syscalls tst-mntent-escape tst-select
|
||||
|
||||
# Tests which need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
diff --git a/misc/tst-select.c b/misc/tst-select.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7c310256c5c6c25a
|
||||
--- /dev/null
|
||||
+++ b/misc/tst-select.c
|
||||
@@ -0,0 +1,71 @@
|
||||
+/* Test for select timeout.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <time.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <sys/select.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xtime.h>
|
||||
+#include <support/timespec.h>
|
||||
+
|
||||
+#define TST_SELECT_TIMEOUT 1
|
||||
+#define TST_SELECT_FD_ERR 2
|
||||
+
|
||||
+static int
|
||||
+test_select_timeout (bool zero_tmo)
|
||||
+{
|
||||
+ const int fds = TST_SELECT_FD_ERR;
|
||||
+ int timeout = TST_SELECT_TIMEOUT;
|
||||
+ struct timeval to = { 0, 0 };
|
||||
+ struct timespec ts;
|
||||
+ fd_set rfds;
|
||||
+
|
||||
+ FD_ZERO (&rfds);
|
||||
+ FD_SET (fds, &rfds);
|
||||
+
|
||||
+ if (zero_tmo)
|
||||
+ timeout = 0;
|
||||
+
|
||||
+ to.tv_sec = timeout;
|
||||
+ ts = xclock_now (CLOCK_REALTIME);
|
||||
+ ts = timespec_add (ts, (struct timespec) { timeout, 0 });
|
||||
+
|
||||
+ /* Wait for timeout. */
|
||||
+ int ret = select (fds + 1, &rfds, NULL, NULL, &to);
|
||||
+ if (ret == -1)
|
||||
+ FAIL_EXIT1 ("select failed: %m\n");
|
||||
+
|
||||
+ TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Check if select exits immediately. */
|
||||
+ test_select_timeout (true);
|
||||
+
|
||||
+ /* Check if select exits after specified timeout. */
|
||||
+ test_select_timeout (false);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
128
glibc-upstream-2.33-24.patch
Normal file
128
glibc-upstream-2.33-24.patch
Normal file
@ -0,0 +1,128 @@
|
||||
commit 3d525dd63926bb28517b3bf452da17fb3c4ee24c
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Mar 25 16:57:45 2021 -0300
|
||||
|
||||
misc: Fix tst-select timeout handling (BZ#27648)
|
||||
|
||||
Instead of polling the stderr, create two pipes and fork to check
|
||||
if child timeout as expected similar to tst-pselect.c. Also lower
|
||||
the timeout value.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
(cherry picked from commit 1b53b5d970c232b48843c778ac4566ff5b566c3b)
|
||||
|
||||
diff --git a/misc/tst-select.c b/misc/tst-select.c
|
||||
index 7c310256c5c6c25a..5ad057cd51d0f45c 100644
|
||||
--- a/misc/tst-select.c
|
||||
+++ b/misc/tst-select.c
|
||||
@@ -16,54 +16,79 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
-#include <time.h>
|
||||
#include <errno.h>
|
||||
-#include <stdbool.h>
|
||||
-#include <sys/select.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
-#include <support/xtime.h>
|
||||
#include <support/timespec.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <support/xtime.h>
|
||||
|
||||
-#define TST_SELECT_TIMEOUT 1
|
||||
-#define TST_SELECT_FD_ERR 2
|
||||
+struct child_args
|
||||
+{
|
||||
+ int fds[2][2];
|
||||
+ struct timeval tmo;
|
||||
+};
|
||||
|
||||
-static int
|
||||
-test_select_timeout (bool zero_tmo)
|
||||
+static void
|
||||
+do_test_child (void *clousure)
|
||||
{
|
||||
- const int fds = TST_SELECT_FD_ERR;
|
||||
- int timeout = TST_SELECT_TIMEOUT;
|
||||
- struct timeval to = { 0, 0 };
|
||||
- struct timespec ts;
|
||||
- fd_set rfds;
|
||||
+ struct child_args *args = (struct child_args *) clousure;
|
||||
|
||||
- FD_ZERO (&rfds);
|
||||
- FD_SET (fds, &rfds);
|
||||
+ close (args->fds[0][1]);
|
||||
+ close (args->fds[1][0]);
|
||||
|
||||
- if (zero_tmo)
|
||||
- timeout = 0;
|
||||
+ fd_set rfds;
|
||||
+ FD_ZERO (&rfds);
|
||||
+ FD_SET (args->fds[0][0], &rfds);
|
||||
|
||||
- to.tv_sec = timeout;
|
||||
- ts = xclock_now (CLOCK_REALTIME);
|
||||
- ts = timespec_add (ts, (struct timespec) { timeout, 0 });
|
||||
+ struct timespec ts = xclock_now (CLOCK_REALTIME);
|
||||
+ ts = timespec_add (ts, (struct timespec) { args->tmo.tv_sec, 0 });
|
||||
|
||||
- /* Wait for timeout. */
|
||||
- int ret = select (fds + 1, &rfds, NULL, NULL, &to);
|
||||
- if (ret == -1)
|
||||
- FAIL_EXIT1 ("select failed: %m\n");
|
||||
+ int r = select (args->fds[0][0] + 1, &rfds, NULL, NULL, &args->tmo);
|
||||
+ TEST_COMPARE (r, 0);
|
||||
|
||||
TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
|
||||
|
||||
- return 0;
|
||||
+ xwrite (args->fds[1][1], "foo", 3);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- /* Check if select exits immediately. */
|
||||
- test_select_timeout (true);
|
||||
-
|
||||
- /* Check if select exits after specified timeout. */
|
||||
- test_select_timeout (false);
|
||||
+ struct child_args args;
|
||||
+
|
||||
+ xpipe (args.fds[0]);
|
||||
+ xpipe (args.fds[1]);
|
||||
+
|
||||
+ /* The child select should timeout and write on its pipe end. */
|
||||
+ args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 250000 };
|
||||
+ {
|
||||
+ struct support_capture_subprocess result;
|
||||
+ result = support_capture_subprocess (do_test_child, &args);
|
||||
+ support_capture_subprocess_check (&result, "tst-select-child", 0,
|
||||
+ sc_allow_none);
|
||||
+ }
|
||||
+
|
||||
+ /* Same as before, but simulating polling. */
|
||||
+ args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
|
||||
+ {
|
||||
+ struct support_capture_subprocess result;
|
||||
+ result = support_capture_subprocess (do_test_child, &args);
|
||||
+ support_capture_subprocess_check (&result, "tst-select-child", 0,
|
||||
+ sc_allow_none);
|
||||
+ }
|
||||
+
|
||||
+ xclose (args.fds[0][0]);
|
||||
+ xclose (args.fds[1][1]);
|
||||
+
|
||||
+ {
|
||||
+ fd_set rfds;
|
||||
+ FD_ZERO (&rfds);
|
||||
+ FD_SET (args.fds[1][0], &rfds);
|
||||
+
|
||||
+ int r = select (args.fds[1][0] + 1, &rfds, NULL, NULL, &args.tmo);
|
||||
+ TEST_COMPARE (r, 1);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
80
glibc-upstream-2.33-25.patch
Normal file
80
glibc-upstream-2.33-25.patch
Normal file
@ -0,0 +1,80 @@
|
||||
commit b5b4aa62c124cf5c6c8d7a520137acbc0f3dc525
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Apr 9 10:02:30 2021 -0300
|
||||
|
||||
libsupport: Add support_select_modifies_timeout
|
||||
|
||||
It will be used on a select() test.
|
||||
|
||||
(cherry picked from commit 5628f103f5937611730845390928cb43ef716012)
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index bb9889efb4be3630..4fd76b0e5e4add3f 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -67,6 +67,7 @@ libsupport-routines = \
|
||||
support_quote_string \
|
||||
support_record_failure \
|
||||
support_run_diff \
|
||||
+ support_select_modifies_timeout \
|
||||
support_set_small_thread_stack_size \
|
||||
support_shared_allocate \
|
||||
support_small_stack_thread_attribute \
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 9cbc45572054fd90..9c9612644a70e46f 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef SUPPORT_H
|
||||
#define SUPPORT_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
/* For mode_t. */
|
||||
@@ -129,6 +130,10 @@ extern void support_copy_file (const char *from, const char *to);
|
||||
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||
size_t, unsigned int);
|
||||
|
||||
+/* Return true if select modify the timeout to reflect the amount of time
|
||||
+ no slept. */
|
||||
+extern bool support_select_modifies_timeout (void);
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_H */
|
||||
diff --git a/support/support_select_modifies_timeout.c b/support/support_select_modifies_timeout.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..653ea2cc9850b005
|
||||
--- /dev/null
|
||||
+++ b/support/support_select_modifies_timeout.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* Return whether select modifies the timeout.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+bool
|
||||
+support_select_modifies_timeout (void)
|
||||
+{
|
||||
+#ifdef __linux__
|
||||
+ return true;
|
||||
+#else
|
||||
+ return false;
|
||||
+#endif
|
||||
+}
|
72
glibc-upstream-2.33-26.patch
Normal file
72
glibc-upstream-2.33-26.patch
Normal file
@ -0,0 +1,72 @@
|
||||
commit 85e4dc415a9ae70eebb167f04d5fda2cc8cd5461
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Apr 9 10:05:13 2021 -0300
|
||||
|
||||
libsupport: Add support_select_normalizes_timeout
|
||||
|
||||
It will be used on a select() test.
|
||||
|
||||
(cherry-pick from commit 49a40ba18e2cb948259771317fe6ff6f5eb68683)
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 4fd76b0e5e4add3f..fc5d9d4c7933b111 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -68,6 +68,7 @@ libsupport-routines = \
|
||||
support_record_failure \
|
||||
support_run_diff \
|
||||
support_select_modifies_timeout \
|
||||
+ support_select_normalizes_timeout \
|
||||
support_set_small_thread_stack_size \
|
||||
support_shared_allocate \
|
||||
support_small_stack_thread_attribute \
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 9c9612644a70e46f..8c7890e0a6f94f8a 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -134,6 +134,10 @@ extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||
no slept. */
|
||||
extern bool support_select_modifies_timeout (void);
|
||||
|
||||
+/* Return true if select normalize the timeout input by taking in account
|
||||
+ tv_usec larger than 1000000. */
|
||||
+extern bool support_select_normalizes_timeout (void);
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_H */
|
||||
diff --git a/support/support_select_normalizes_timeout.c b/support/support_select_normalizes_timeout.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..987f9b035e251602
|
||||
--- /dev/null
|
||||
+++ b/support/support_select_normalizes_timeout.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* Return whether select normalizes the timeout.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+bool
|
||||
+support_select_normalizes_timeout (void)
|
||||
+{
|
||||
+#ifdef __linux__
|
||||
+ return true;
|
||||
+#else
|
||||
+ return false;
|
||||
+#endif
|
||||
+}
|
171
glibc-upstream-2.33-27.patch
Normal file
171
glibc-upstream-2.33-27.patch
Normal file
@ -0,0 +1,171 @@
|
||||
commit 8380ca5833ef2a11bf0162f2290f4f8c85ce3b90
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Mar 31 13:53:34 2021 -0300
|
||||
|
||||
linux: Normalize and return timeout on select (BZ #27651)
|
||||
|
||||
The commit 2433d39b697, which added time64 support to select, changed
|
||||
the function to use __NR_pselect6 (or __NR_pelect6_time64) on all
|
||||
architectures. However, on architectures where the symbol was
|
||||
implemented with __NR_select the kernel normalizes the passed timeout
|
||||
instead of return EINVAL. For instance, the input timeval
|
||||
{ 0, 5000000 } is interpreted as { 5, 0 }.
|
||||
|
||||
And as indicated by BZ #27651, this semantic seems to be expected
|
||||
and changing it results in some performance issues (most likely
|
||||
the program does not check the return code and keeps issuing
|
||||
select with unormalized tv_usec argument).
|
||||
|
||||
To avoid a different semantic depending whether which syscall the
|
||||
architecture used to issue, select now always normalize the timeout
|
||||
input. This is a slight change for some ABIs (for instance aarch64).
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
(cherry picked from commit 9d7c5cc38e58fb0923e88901f87174a511b61552)
|
||||
|
||||
diff --git a/include/time.h b/include/time.h
|
||||
index caf2af5e74ed6179..e0636132a6ee3fe9 100644
|
||||
--- a/include/time.h
|
||||
+++ b/include/time.h
|
||||
@@ -502,6 +502,11 @@ time_now (void)
|
||||
__clock_gettime (TIME_CLOCK_GETTIME_CLOCKID, &ts);
|
||||
return ts.tv_sec;
|
||||
}
|
||||
+
|
||||
+#define NSEC_PER_SEC 1000000000L /* Nanoseconds per second. */
|
||||
+#define USEC_PER_SEC 1000000L /* Microseconds per second. */
|
||||
+#define NSEC_PER_USEC 1000L /* Nanoseconds per microsecond. */
|
||||
+
|
||||
#endif
|
||||
|
||||
#endif
|
||||
diff --git a/misc/tst-select.c b/misc/tst-select.c
|
||||
index 5ad057cd51d0f45c..534105b50020fa44 100644
|
||||
--- a/misc/tst-select.c
|
||||
+++ b/misc/tst-select.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <errno.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
#include <support/timespec.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <support/xtime.h>
|
||||
@@ -47,6 +48,12 @@ do_test_child (void *clousure)
|
||||
int r = select (args->fds[0][0] + 1, &rfds, NULL, NULL, &args->tmo);
|
||||
TEST_COMPARE (r, 0);
|
||||
|
||||
+ if (support_select_modifies_timeout ())
|
||||
+ {
|
||||
+ TEST_COMPARE (args->tmo.tv_sec, 0);
|
||||
+ TEST_COMPARE (args->tmo.tv_usec, 0);
|
||||
+ }
|
||||
+
|
||||
TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
|
||||
|
||||
xwrite (args->fds[1][1], "foo", 3);
|
||||
@@ -69,6 +76,16 @@ do_test (void)
|
||||
sc_allow_none);
|
||||
}
|
||||
|
||||
+ if (support_select_normalizes_timeout ())
|
||||
+ {
|
||||
+ /* This is handled as 1 second instead of failing with EINVAL. */
|
||||
+ args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 1000000 };
|
||||
+ struct support_capture_subprocess result;
|
||||
+ result = support_capture_subprocess (do_test_child, &args);
|
||||
+ support_capture_subprocess_check (&result, "tst-select-child", 0,
|
||||
+ sc_allow_none);
|
||||
+ }
|
||||
+
|
||||
/* Same as before, but simulating polling. */
|
||||
args.tmo = (struct timeval) { .tv_sec = 0, .tv_usec = 0 };
|
||||
{
|
||||
diff --git a/sunrpc/svcauth_des.c b/sunrpc/svcauth_des.c
|
||||
index 7607abc8186813f6..25a85c90970d4ced 100644
|
||||
--- a/sunrpc/svcauth_des.c
|
||||
+++ b/sunrpc/svcauth_des.c
|
||||
@@ -58,7 +58,6 @@
|
||||
|
||||
#define debug(msg) /*printf("svcauth_des: %s\n", msg) */
|
||||
|
||||
-#define USEC_PER_SEC ((uint32_t) 1000000L)
|
||||
#define BEFORE(t1, t2) timercmp(t1, t2, <)
|
||||
|
||||
/*
|
||||
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
|
||||
index 415aa87d3c87d70c..3b67ff44765ededf 100644
|
||||
--- a/sysdeps/unix/sysv/linux/select.c
|
||||
+++ b/sysdeps/unix/sysv/linux/select.c
|
||||
@@ -33,12 +33,34 @@ int
|
||||
__select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
struct __timeval64 *timeout)
|
||||
{
|
||||
- struct __timespec64 ts64, *pts64 = NULL;
|
||||
- if (timeout != NULL)
|
||||
+ __time64_t s = timeout != NULL ? timeout->tv_sec : 0;
|
||||
+ int32_t us = timeout != NULL ? timeout->tv_usec : 0;
|
||||
+ int32_t ns;
|
||||
+
|
||||
+ if (s < 0 || us < 0)
|
||||
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
|
||||
+
|
||||
+ /* Normalize the timeout, as legacy Linux __NR_select and __NR__newselect.
|
||||
+ Different than syscall, it also handle possible overflow. */
|
||||
+ if (us / USEC_PER_SEC > INT64_MAX - s)
|
||||
{
|
||||
- ts64 = timeval64_to_timespec64 (*timeout);
|
||||
- pts64 = &ts64;
|
||||
+ s = INT64_MAX;
|
||||
+ ns = NSEC_PER_SEC - 1;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ s += us / USEC_PER_SEC;
|
||||
+ us = us % USEC_PER_SEC;
|
||||
+ ns = us * NSEC_PER_USEC;
|
||||
+ }
|
||||
+
|
||||
+ struct __timespec64 ts64, *pts64 = NULL;
|
||||
+ if (timeout != NULL)
|
||||
+ {
|
||||
+ ts64.tv_sec = s;
|
||||
+ ts64.tv_nsec = ns;
|
||||
+ pts64 = &ts64;
|
||||
+ }
|
||||
|
||||
#ifndef __NR_pselect6_time64
|
||||
# define __NR_pselect6_time64 __NR_pselect6
|
||||
@@ -52,10 +74,10 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
(though the pselect() glibc call suppresses this behavior).
|
||||
Since select() on Linux has the same behavior as the pselect6
|
||||
syscall, we update the timeout here. */
|
||||
- if (r == 0 || errno != ENOSYS)
|
||||
+ if (r >= 0 || errno != ENOSYS)
|
||||
{
|
||||
if (timeout != NULL)
|
||||
- TIMEVAL_TO_TIMESPEC (timeout, &ts64);
|
||||
+ TIMESPEC_TO_TIMEVAL (timeout, &ts64);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -64,14 +86,15 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
|
||||
#ifndef __ASSUME_TIME64_SYSCALLS
|
||||
struct timespec ts32, *pts32 = NULL;
|
||||
- if (timeout != NULL)
|
||||
+ if (pts64 != NULL)
|
||||
{
|
||||
- if (! in_time_t_range (timeout->tv_sec))
|
||||
+ if (! in_time_t_range (pts64->tv_sec))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
- ts32 = valid_timespec64_to_timespec (ts64);
|
||||
+ ts32.tv_sec = s;
|
||||
+ ts32.tv_nsec = ns;
|
||||
pts32 = &ts32;
|
||||
}
|
||||
# ifndef __ASSUME_PSELECT
|
96
glibc-upstream-2.33-28.patch
Normal file
96
glibc-upstream-2.33-28.patch
Normal file
@ -0,0 +1,96 @@
|
||||
commit 3e9ca60a580e2b6854cd5314ebb0866a1f387ca8
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Apr 8 07:39:32 2021 -0300
|
||||
|
||||
linux: always update select timeout (BZ #27706)
|
||||
|
||||
The timeout should be updated even on failure for time64 support.
|
||||
|
||||
Checked on i686-linux-gnu.
|
||||
|
||||
(cherry-pick from commit cedbf6d5f3f70ca911176de87d6e453eeab4b7a1)
|
||||
|
||||
diff --git a/misc/tst-select.c b/misc/tst-select.c
|
||||
index 534105b50020fa44..52aa26651f612701 100644
|
||||
--- a/misc/tst-select.c
|
||||
+++ b/misc/tst-select.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <support/timespec.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <support/xtime.h>
|
||||
+#include <support/xsignal.h>
|
||||
|
||||
struct child_args
|
||||
{
|
||||
@@ -30,6 +31,12 @@ struct child_args
|
||||
struct timeval tmo;
|
||||
};
|
||||
|
||||
+static void
|
||||
+alarm_handler (int signum)
|
||||
+{
|
||||
+ /* Do nothing. */
|
||||
+}
|
||||
+
|
||||
static void
|
||||
do_test_child (void *clousure)
|
||||
{
|
||||
@@ -59,6 +66,22 @@ do_test_child (void *clousure)
|
||||
xwrite (args->fds[1][1], "foo", 3);
|
||||
}
|
||||
|
||||
+static void
|
||||
+do_test_child_alarm (void *clousure)
|
||||
+{
|
||||
+ struct sigaction act = { .sa_handler = alarm_handler };
|
||||
+ xsigaction (SIGALRM, &act, NULL);
|
||||
+ alarm (1);
|
||||
+
|
||||
+ struct timeval tv = { .tv_sec = 10, .tv_usec = 0 };
|
||||
+ int r = select (0, NULL, NULL, NULL, &tv);
|
||||
+ TEST_COMPARE (r, -1);
|
||||
+ TEST_COMPARE (errno, EINTR);
|
||||
+
|
||||
+ if (support_select_modifies_timeout ())
|
||||
+ TEST_VERIFY (tv.tv_sec < 10);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -98,6 +121,13 @@ do_test (void)
|
||||
xclose (args.fds[0][0]);
|
||||
xclose (args.fds[1][1]);
|
||||
|
||||
+ {
|
||||
+ struct support_capture_subprocess result;
|
||||
+ result = support_capture_subprocess (do_test_child_alarm, NULL);
|
||||
+ support_capture_subprocess_check (&result, "tst-select-child", 0,
|
||||
+ sc_allow_none);
|
||||
+ }
|
||||
+
|
||||
{
|
||||
fd_set rfds;
|
||||
FD_ZERO (&rfds);
|
||||
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
|
||||
index 3b67ff44765ededf..dc16a816ed9e5f9b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/select.c
|
||||
+++ b/sysdeps/unix/sysv/linux/select.c
|
||||
@@ -107,7 +107,7 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
r = SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, pts32,
|
||||
NULL);
|
||||
# endif
|
||||
- if (r >= 0 && timeout != NULL)
|
||||
+ if (timeout != NULL)
|
||||
*timeout = valid_timespec_to_timeval64 (ts32);
|
||||
#endif
|
||||
|
||||
@@ -128,7 +128,7 @@ __select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
ptv64 = &tv64;
|
||||
}
|
||||
int r = __select64 (nfds, readfds, writefds, exceptfds, ptv64);
|
||||
- if (r >= 0 && timeout != NULL)
|
||||
+ if (timeout != NULL)
|
||||
/* The remanining timeout will be always less the input TIMEOUT. */
|
||||
*timeout = valid_timeval64_to_timeval (tv64);
|
||||
return r;
|
122
glibc-upstream-2.33-29.patch
Normal file
122
glibc-upstream-2.33-29.patch
Normal file
@ -0,0 +1,122 @@
|
||||
commit e07abf59b28dc4406f8462aef4fb28b38f1cbd3b
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Mar 16 18:31:02 2021 +0530
|
||||
|
||||
tunables: Fix comparison of tunable values
|
||||
|
||||
The simplification of tunable_set interfaces took care of
|
||||
signed/unsigned conversions while setting values, but comparison with
|
||||
bounds ended up being incorrect; comparing TUNABLE_SIZE_T values for
|
||||
example will fail because SIZE_MAX is seen as -1.
|
||||
|
||||
Add comparison helpers that take tunable types into account and use
|
||||
them to do comparison instead.
|
||||
|
||||
(cherry picked from commit d1a3dcabf2f89233a99a4a9be08f9f407da0b6b4)
|
||||
|
||||
diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
|
||||
index 626ca334be105e69..39bf738d930efca2 100644
|
||||
--- a/elf/dl-tunable-types.h
|
||||
+++ b/elf/dl-tunable-types.h
|
||||
@@ -81,4 +81,21 @@ struct _tunable
|
||||
|
||||
typedef struct _tunable tunable_t;
|
||||
|
||||
+static __always_inline bool
|
||||
+unsigned_tunable_type (tunable_type_code_t t)
|
||||
+{
|
||||
+ switch (t)
|
||||
+ {
|
||||
+ case TUNABLE_TYPE_INT_32:
|
||||
+ return false;
|
||||
+ case TUNABLE_TYPE_UINT_64:
|
||||
+ case TUNABLE_TYPE_SIZE_T:
|
||||
+ return true;
|
||||
+ case TUNABLE_TYPE_STRING:
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ __builtin_unreachable ();
|
||||
+}
|
||||
+
|
||||
#endif
|
||||
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
|
||||
index a2be9cde2f7333ea..8b751dcf0deb0d01 100644
|
||||
--- a/elf/dl-tunables.c
|
||||
+++ b/elf/dl-tunables.c
|
||||
@@ -107,32 +107,35 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
|
||||
return;
|
||||
}
|
||||
|
||||
+ bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
|
||||
+
|
||||
val = valp->numval;
|
||||
min = minp != NULL ? *minp : cur->type.min;
|
||||
max = maxp != NULL ? *maxp : cur->type.max;
|
||||
|
||||
/* We allow only increasingly restrictive bounds. */
|
||||
- if (min < cur->type.min)
|
||||
+ if (tunable_val_lt (min, cur->type.min, unsigned_cmp))
|
||||
min = cur->type.min;
|
||||
|
||||
- if (max > cur->type.max)
|
||||
+ if (tunable_val_gt (max, cur->type.max, unsigned_cmp))
|
||||
max = cur->type.max;
|
||||
|
||||
/* Skip both bounds if they're inconsistent. */
|
||||
- if (min > max)
|
||||
+ if (tunable_val_gt (min, max, unsigned_cmp))
|
||||
{
|
||||
min = cur->type.min;
|
||||
max = cur->type.max;
|
||||
}
|
||||
|
||||
- /* Write everything out if the value and the bounds are valid. */
|
||||
- if (min <= val && val <= max)
|
||||
- {
|
||||
- cur->val.numval = val;
|
||||
- cur->type.min = min;
|
||||
- cur->type.max = max;
|
||||
- cur->initialized = true;
|
||||
- }
|
||||
+ /* Bail out if the bounds are not valid. */
|
||||
+ if (tunable_val_lt (val, min, unsigned_cmp)
|
||||
+ || tunable_val_lt (max, val, unsigned_cmp))
|
||||
+ return;
|
||||
+
|
||||
+ cur->val.numval = val;
|
||||
+ cur->type.min = min;
|
||||
+ cur->type.max = max;
|
||||
+ cur->initialized = true;
|
||||
}
|
||||
|
||||
/* Validate range of the input value and initialize the tunable CUR if it looks
|
||||
diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
|
||||
index ba7ae6b52ecea7a3..3880e4aab623771e 100644
|
||||
--- a/elf/dl-tunables.h
|
||||
+++ b/elf/dl-tunables.h
|
||||
@@ -115,6 +115,24 @@ rtld_hidden_proto (__tunable_set_val)
|
||||
/* The default value for TUNABLES_FRONTEND. */
|
||||
# define TUNABLES_FRONTEND_yes TUNABLES_FRONTEND_valstring
|
||||
|
||||
+static __always_inline bool
|
||||
+tunable_val_lt (tunable_num_t lhs, tunable_num_t rhs, bool unsigned_cmp)
|
||||
+{
|
||||
+ if (unsigned_cmp)
|
||||
+ return (uintmax_t) lhs < (uintmax_t) rhs;
|
||||
+ else
|
||||
+ return lhs < rhs;
|
||||
+}
|
||||
+
|
||||
+static __always_inline bool
|
||||
+tunable_val_gt (tunable_num_t lhs, tunable_num_t rhs, bool unsigned_cmp)
|
||||
+{
|
||||
+ if (unsigned_cmp)
|
||||
+ return (uintmax_t) lhs > (uintmax_t) rhs;
|
||||
+ else
|
||||
+ return lhs > rhs;
|
||||
+}
|
||||
+
|
||||
/* Compare two name strings, bounded by the name hardcoded in glibc. */
|
||||
static __always_inline bool
|
||||
tunable_is_name (const char *orig, const char *envname)
|
55
glibc-upstream-2.33-30.patch
Normal file
55
glibc-upstream-2.33-30.patch
Normal file
@ -0,0 +1,55 @@
|
||||
commit 45b2c57d345092e8a6a9f065a44c9801e09c24c5
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 15 16:00:06 2021 +0530
|
||||
|
||||
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 95c68080a3ded882789b1629f872c3ad531efda0)
|
||||
|
||||
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
|
||||
index a7afa0e70b48f649..3eb825b9afc0b5e6 100644
|
||||
--- a/support/support_capture_subprocess.c
|
||||
+++ b/support/support_capture_subprocess.c
|
||||
@@ -36,7 +36,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;
|
||||
}
|
||||
diff --git a/support/support_subprocess.c b/support/support_subprocess.c
|
||||
index 88489a3357f6aae0..838eda96ffd6eb9a 100644
|
||||
--- a/support/support_subprocess.c
|
||||
+++ b/support/support_subprocess.c
|
||||
@@ -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. */
|
24
glibc-upstream-2.33-31.patch
Normal file
24
glibc-upstream-2.33-31.patch
Normal file
@ -0,0 +1,24 @@
|
||||
commit 249c486ce8e80a9e94d51b4bbf3ccf5d0af57e5e
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 15 17:23:30 2021 +0530
|
||||
|
||||
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 e958490f8c74e660bd93c128b3bea746e268f3f6)
|
||||
|
||||
diff --git a/support/support_subprocess.c b/support/support_subprocess.c
|
||||
index 838eda96ffd6eb9a..2acfc57b7e70732d 100644
|
||||
--- a/support/support_subprocess.c
|
||||
+++ b/support/support_subprocess.c
|
||||
@@ -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]);
|
462
glibc-upstream-2.33-32.patch
Normal file
462
glibc-upstream-2.33-32.patch
Normal file
@ -0,0 +1,462 @@
|
||||
commit 267e174f198532d950a6f419681689d73b2c633c
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri Apr 9 20:55:45 2021 +0530
|
||||
|
||||
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 716a3bdc41b2b4b864dc64475015ba51e35e1273)
|
||||
|
||||
diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c
|
||||
index c9ec03866ff8ac3b..5567c9ae215fd924 100644
|
||||
--- a/stdlib/tst-secure-getenv.c
|
||||
+++ b/stdlib/tst-secure-getenv.c
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
|
||||
index 8969d4a99a093657..4be430f099bcc8cd 100644
|
||||
--- a/support/capture_subprocess.h
|
||||
+++ b/support/capture_subprocess.h
|
||||
@@ -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 *);
|
||||
diff --git a/support/subprocess.h b/support/subprocess.h
|
||||
index 11cfc6a07f5ad94a..40d82c7e4db27090 100644
|
||||
--- a/support/subprocess.h
|
||||
+++ b/support/subprocess.h
|
||||
@@ -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);
|
||||
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
|
||||
index 3eb825b9afc0b5e6..27bfd19c9374a183 100644
|
||||
--- a/support/support_capture_subprocess.c
|
||||
+++ b/support/support_capture_subprocess.c
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
{
|
||||
diff --git a/support/support_subprocess.c b/support/support_subprocess.c
|
||||
index 2acfc57b7e70732d..89e767ae47e454f1 100644
|
||||
--- a/support/support_subprocess.c
|
||||
+++ b/support/support_subprocess.c
|
||||
@@ -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)
|
||||
{
|
244
glibc-upstream-2.33-33.patch
Normal file
244
glibc-upstream-2.33-33.patch
Normal file
@ -0,0 +1,244 @@
|
||||
commit ee16c81063d85582091702b6a3a736002b76f397
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Mar 16 12:37:53 2021 +0530
|
||||
|
||||
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 ca335281068a1ed549a75ee64f90a8310755956f)
|
||||
|
||||
diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c
|
||||
index 60ae0ca38050a871..49b5e319e27c2404 100644
|
||||
--- a/elf/tst-env-setuid.c
|
||||
+++ b/elf/tst-env-setuid.c
|
||||
@@ -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);
|
||||
|
||||
- /* Something went wrong and our argv was corrupted. */
|
||||
- _exit (1);
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
154
glibc-upstream-2.33-34.patch
Normal file
154
glibc-upstream-2.33-34.patch
Normal file
@ -0,0 +1,154 @@
|
||||
commit a7b8e8ec9b21c7c6d4ec0ba2229abd63dc3a00b2
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Mar 16 12:37:54 2021 +0530
|
||||
|
||||
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 061fe3f8add46a89b7453e87eabb9c4695005ced)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 4b92f8b3054b556e..28e18aea5d412222 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -1658,8 +1658,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
|
||||
diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
|
||||
index 50bef8683df0e9c1..3d523875b1e07a74 100644
|
||||
--- a/elf/tst-env-setuid-tunables.c
|
||||
+++ b/elf/tst-env-setuid-tunables.c
|
||||
@@ -25,35 +25,50 @@
|
||||
#include "config.h"
|
||||
#undef _LIBC
|
||||
|
||||
-#define test_parent test_parent_tunables
|
||||
-#define test_child test_child_tunables
|
||||
-
|
||||
-static int test_child_tunables (void);
|
||||
-static int test_parent_tunables (void);
|
||||
-
|
||||
-#include "tst-env-setuid.c"
|
||||
+#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>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+
|
||||
+const char *teststrings[] =
|
||||
+{
|
||||
+ "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096",
|
||||
+};
|
||||
|
||||
-#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",
|
||||
+};
|
||||
|
||||
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 +76,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>
|
164
glibc-upstream-2.33-35.patch
Normal file
164
glibc-upstream-2.33-35.patch
Normal file
@ -0,0 +1,164 @@
|
||||
commit 1bf38e7260c2cd3e40e118c1f1ea28de182dc751
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Mar 16 12:37:55 2021 +0530
|
||||
|
||||
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 2ed18c5b534d9e92fc006202a5af0df6b72e7aca)
|
||||
|
||||
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
|
||||
index 8b751dcf0deb0d01..8009e54ee5db32be 100644
|
||||
--- a/elf/dl-tunables.c
|
||||
+++ b/elf/dl-tunables.c
|
||||
@@ -174,6 +174,7 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
return;
|
||||
|
||||
char *p = tunestr;
|
||||
+ size_t off = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -187,7 +188,11 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
/* If we reach the end of the string before getting a valid name-value
|
||||
pair, bail out. */
|
||||
if (p[len] == '\0')
|
||||
- return;
|
||||
+ {
|
||||
+ if (__libc_enable_secure)
|
||||
+ tunestr[off] = '\0';
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
/* We did not find a valid name-value pair before encountering the
|
||||
colon. */
|
||||
@@ -213,35 +218,28 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
|
||||
if (tunable_is_name (cur->name, name))
|
||||
{
|
||||
- /* If we are in a secure context (AT_SECURE) then ignore the tunable
|
||||
- unless it is explicitly marked as secure. Tunable values take
|
||||
- precedence over their envvar aliases. */
|
||||
+ /* If we are in a secure context (AT_SECURE) then ignore the
|
||||
+ tunable unless it is explicitly marked as secure. Tunable
|
||||
+ values take precedence over their envvar aliases. We write
|
||||
+ the tunables that are not SXID_ERASE back to TUNESTR, thus
|
||||
+ dropping all SXID_ERASE tunables and any invalid or
|
||||
+ unrecognized tunables. */
|
||||
if (__libc_enable_secure)
|
||||
{
|
||||
- if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
|
||||
+ if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
|
||||
{
|
||||
- if (p[len] == '\0')
|
||||
- {
|
||||
- /* Last tunable in the valstring. Null-terminate and
|
||||
- return. */
|
||||
- *name = '\0';
|
||||
- return;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Remove the current tunable from the string. We do
|
||||
- this by overwriting the string starting from NAME
|
||||
- (which is where the current tunable begins) with
|
||||
- the remainder of the string. We then have P point
|
||||
- to NAME so that we continue in the correct
|
||||
- position in the valstring. */
|
||||
- char *q = &p[len + 1];
|
||||
- p = name;
|
||||
- while (*q != '\0')
|
||||
- *name++ = *q++;
|
||||
- name[0] = '\0';
|
||||
- len = 0;
|
||||
- }
|
||||
+ if (off > 0)
|
||||
+ tunestr[off++] = ':';
|
||||
+
|
||||
+ const char *n = cur->name;
|
||||
+
|
||||
+ while (*n != '\0')
|
||||
+ tunestr[off++] = *n++;
|
||||
+
|
||||
+ tunestr[off++] = '=';
|
||||
+
|
||||
+ for (size_t j = 0; j < len; j++)
|
||||
+ tunestr[off++] = value[j];
|
||||
}
|
||||
|
||||
if (cur->security_level != TUNABLE_SECLEVEL_NONE)
|
||||
@@ -254,9 +252,7 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
}
|
||||
}
|
||||
|
||||
- if (p[len] == '\0')
|
||||
- return;
|
||||
- else
|
||||
+ if (p[len] != '\0')
|
||||
p += len + 1;
|
||||
}
|
||||
}
|
||||
diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
|
||||
index 3d523875b1e07a74..05619c9adc8b2698 100644
|
||||
--- a/elf/tst-env-setuid-tunables.c
|
||||
+++ b/elf/tst-env-setuid-tunables.c
|
||||
@@ -45,11 +45,37 @@
|
||||
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",
|
||||
};
|
||||
|
||||
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
|
34
glibc-upstream-2.33-36.patch
Normal file
34
glibc-upstream-2.33-36.patch
Normal file
@ -0,0 +1,34 @@
|
||||
commit 12ff80b312c11b0284df7a1c5cb9be6418f85228
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Tue Feb 2 15:02:09 2021 +0000
|
||||
|
||||
Remove PR_TAGGED_ADDR_ENABLE from sys/prctl.h
|
||||
|
||||
The value of PR_TAGGED_ADDR_ENABLE was incorrect in the installed
|
||||
headers and the prctl command macros were missing that are needed
|
||||
for it to be useful (PR_SET_TAGGED_ADDR_CTRL). Linux headers have
|
||||
the definitions since 5.4 so it's widely available, we don't need
|
||||
to repeat these definitions. The remaining definitions are from
|
||||
Linux 5.10.
|
||||
|
||||
To build glibc with --enable-memory-tagging, Linux 5.4 headers and
|
||||
binutils 2.33.1 or newer is needed.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit f4596d9540021265a99697fceef8a434c47e8bcf)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h
|
||||
index 00817ff0f14c617d..c9048c7cdb3e4d26 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sys/prctl.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sys/prctl.h
|
||||
@@ -25,10 +25,6 @@
|
||||
we're picking up... */
|
||||
|
||||
/* Memory tagging control operations (for AArch64). */
|
||||
-#ifndef PR_TAGGED_ADDR_ENABLE
|
||||
-# define PR_TAGGED_ADDR_ENABLE (1UL << 8)
|
||||
-#endif
|
||||
-
|
||||
#ifndef PR_MTE_TCF_SHIFT
|
||||
# define PR_MTE_TCF_SHIFT 1
|
||||
# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
|
28
glibc-upstream-2.33-37.patch
Normal file
28
glibc-upstream-2.33-37.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit 162df872f0dfc2b124a18e1a8c33be63f70d9a1c
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Wed Apr 21 18:40:08 2021 -0700
|
||||
|
||||
x86: tst-cpu-features-supports.c: Update AMX check
|
||||
|
||||
Pass "amx-bf16", "amx-int8" and "amx-tile", instead of "amx_bf16",
|
||||
"amx_int8" and "amx_tile", to __builtin_cpu_supports for GCC 11.
|
||||
|
||||
(cherry picked from commit 7fc9152e831fb24091c0ceabdcecb9b07dd29dd6)
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
|
||||
index 79d803eb291c188a..cc0d2b2d569a376b 100644
|
||||
--- a/sysdeps/x86/tst-cpu-features-supports.c
|
||||
+++ b/sysdeps/x86/tst-cpu-features-supports.c
|
||||
@@ -59,9 +59,9 @@ do_test (int argc, char **argv)
|
||||
fails += CHECK_SUPPORTS (aes, AES);
|
||||
#endif
|
||||
#if __GNUC_PREREQ (11, 1)
|
||||
- fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16);
|
||||
- fails += CHECK_SUPPORTS (amx_int8, AMX_INT8);
|
||||
- fails += CHECK_SUPPORTS (amx_tile, AMX_TILE);
|
||||
+ fails += CHECK_SUPPORTS (amx-bf16, AMX_BF16);
|
||||
+ fails += CHECK_SUPPORTS (amx-int8, AMX_INT8);
|
||||
+ fails += CHECK_SUPPORTS (amx-tile, AMX_TILE);
|
||||
#endif
|
||||
fails += CHECK_SUPPORTS (avx, AVX);
|
||||
fails += CHECK_SUPPORTS (avx2, AVX2);
|
295
glibc-upstream-2.33-38.patch
Normal file
295
glibc-upstream-2.33-38.patch
Normal file
@ -0,0 +1,295 @@
|
||||
commit ea299b62e83cc38b0d910bbd1a879f7d1f836e96
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Apr 21 11:50:43 2021 +0200
|
||||
|
||||
nptl_db: Support different libpthread/ld.so load orders (bug 27744)
|
||||
|
||||
libthread_db is loaded once GDB encounters libpthread, and at this
|
||||
point, ld.so may not have been processed by GDB yet. As a result,
|
||||
_rtld_global cannot be accessed by regular means from libthread_db.
|
||||
To make this work until GDB can be fixed, acess _rtld_global through
|
||||
a pointer stored in libpthread.
|
||||
|
||||
The new test does not reproduce bug 27744 with
|
||||
--disable-hardcoded-path-in-tests, but is still a valid smoke test.
|
||||
With --enable-hardcoded-path-in-tests, it is necessary to avoid
|
||||
add-symbol-file because this can tickle a GDB bug.
|
||||
|
||||
Fixes commit 1daccf403b1bd86370eb94edca794dc106d02039 ("nptl: Move
|
||||
stack list variables into _rtld_global").
|
||||
|
||||
Tested-by: Emil Velikov <emil.velikov@collabora.com>
|
||||
(cherry picked from commit a64afc225240b2b27129ccfb0516d7c958b98040)
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index 5b036eb8a7b5d8b3..1ca23385d4de9000 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -294,7 +294,8 @@ tests = tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-thread-affinity-sched \
|
||||
tst-pthread-defaultattr-free \
|
||||
tst-pthread-attr-sigmask \
|
||||
- tst-pthread-timedlock-lockloop
|
||||
+ tst-pthread-timedlock-lockloop \
|
||||
+ tst-pthread-gdb-attach tst-pthread-gdb-attach-static
|
||||
|
||||
tests-container = tst-pthread-getattr
|
||||
|
||||
@@ -340,6 +341,19 @@ CPPFLAGS-test-cond-printers.c := $(CFLAGS-printers-tests)
|
||||
CPPFLAGS-test-rwlockattr-printers.c := $(CFLAGS-printers-tests)
|
||||
CPPFLAGS-test-rwlock-printers.c := $(CFLAGS-printers-tests)
|
||||
|
||||
+# Reuse the CFLAGS setting for the GDB attaching test. It needs
|
||||
+# debugging information.
|
||||
+CFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests)
|
||||
+CPPFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests)
|
||||
+ifeq ($(build-shared)$(build-hardcoded-path-in-tests),yesno)
|
||||
+CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=1
|
||||
+else
|
||||
+CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=0
|
||||
+endif
|
||||
+CFLAGS-tst-pthread-gdb-attach-static.c := $(CFLAGS-printers-tests)
|
||||
+CPPFLAGS-tst-pthread-gdb-attach-static.c := \
|
||||
+ $(CFLAGS-printers-tests) -DDO_ADD_SYMBOL_FILE=0
|
||||
+
|
||||
ifeq ($(build-shared),yes)
|
||||
tests-printers-libs := $(shared-thread-library)
|
||||
else
|
||||
@@ -411,7 +425,8 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
|
||||
tests-static += tst-stackguard1-static \
|
||||
tst-cancel24-static \
|
||||
tst-mutex8-static tst-mutexpi8-static tst-sem11-static \
|
||||
- tst-sem12-static tst-cond11-static
|
||||
+ tst-sem12-static tst-cond11-static \
|
||||
+ tst-pthread-gdb-attach-static
|
||||
|
||||
tests += tst-cancel24-static
|
||||
|
||||
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
|
||||
index 6c645aff48ed7dd7..f13d8e44a4b5b693 100644
|
||||
--- a/nptl/pthread_create.c
|
||||
+++ b/nptl/pthread_create.c
|
||||
@@ -51,6 +51,14 @@ static td_thr_events_t __nptl_threads_events __attribute_used__;
|
||||
/* Pointer to descriptor with the last event. */
|
||||
static struct pthread *__nptl_last_event __attribute_used__;
|
||||
|
||||
+#ifdef SHARED
|
||||
+/* This variable is used to access _rtld_global from libthread_db. If
|
||||
+ GDB loads libpthread before ld.so, it is not possible to resolve
|
||||
+ _rtld_global directly during libpthread initialization. */
|
||||
+static struct rtld_global *__nptl_rtld_global __attribute_used__
|
||||
+ = &_rtld_global;
|
||||
+#endif
|
||||
+
|
||||
/* Number of threads running. */
|
||||
unsigned int __nptl_nthreads = 1;
|
||||
|
||||
diff --git a/nptl/tst-pthread-gdb-attach-static.c b/nptl/tst-pthread-gdb-attach-static.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e159632cac57faff
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-pthread-gdb-attach-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-pthread-gdb-attach.c"
|
||||
diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0603ad844defb8de
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-pthread-gdb-attach.c
|
||||
@@ -0,0 +1,143 @@
|
||||
+/* Smoke testing GDB process attach with thread-local variable access.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This test runs GDB against a forked copy of itself, to check
|
||||
+ whether libthread_db can be loaded, and that access to thread-local
|
||||
+ variables works. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+/* Starts out as zero, changed to 1 or 2 by the debugger, depending on
|
||||
+ the thread. */
|
||||
+__thread volatile int altered_by_debugger;
|
||||
+
|
||||
+/* Writes the GDB script to run the test to PATH. */
|
||||
+static void
|
||||
+write_gdbscript (const char *path, int tested_pid)
|
||||
+{
|
||||
+ FILE *fp = xfopen (path, "w");
|
||||
+ fprintf (fp,
|
||||
+ "set trace-commands on\n"
|
||||
+ "set debug libthread-db 1\n"
|
||||
+#if DO_ADD_SYMBOL_FILE
|
||||
+ /* Do not do this unconditionally to work around a GDB
|
||||
+ assertion failure: ../../gdb/symtab.c:6404:
|
||||
+ internal-error: CORE_ADDR get_msymbol_address(objfile*,
|
||||
+ const minimal_symbol*): Assertion `(objf->flags &
|
||||
+ OBJF_MAINLINE) == 0' failed. */
|
||||
+ "add-symbol-file %1$s/nptl/tst-pthread-gdb-attach\n"
|
||||
+#endif
|
||||
+ "set auto-load safe-path %1$s/nptl_db\n"
|
||||
+ "set libthread-db-search-path %1$s/nptl_db\n"
|
||||
+ "attach %2$d\n",
|
||||
+ support_objdir_root, tested_pid);
|
||||
+ fputs ("break debugger_inspection_point\n"
|
||||
+ "continue\n"
|
||||
+ "thread 1\n"
|
||||
+ "print altered_by_debugger\n"
|
||||
+ "print altered_by_debugger = 1\n"
|
||||
+ "thread 2\n"
|
||||
+ "print altered_by_debugger\n"
|
||||
+ "print altered_by_debugger = 2\n"
|
||||
+ "continue\n",
|
||||
+ fp);
|
||||
+ xfclose (fp);
|
||||
+}
|
||||
+
|
||||
+/* The test sets a breakpoint on this function and alters the
|
||||
+ altered_by_debugger thread-local variable. */
|
||||
+void __attribute__ ((weak))
|
||||
+debugger_inspection_point (void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+/* Thread function for the test thread in the subprocess. */
|
||||
+static void *
|
||||
+subprocess_thread (void *closure)
|
||||
+{
|
||||
+ /* Wait until altered_by_debugger changes the value away from 0. */
|
||||
+ while (altered_by_debugger == 0)
|
||||
+ {
|
||||
+ usleep (100 * 1000);
|
||||
+ debugger_inspection_point ();
|
||||
+ }
|
||||
+
|
||||
+ TEST_COMPARE (altered_by_debugger, 2);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* This function implements the subprocess under test. It creates a
|
||||
+ second thread, waiting for its value to change to 2, and checks
|
||||
+ that the main thread also changed its value to 1. */
|
||||
+static void
|
||||
+in_subprocess (void)
|
||||
+{
|
||||
+ pthread_t thr = xpthread_create (NULL, subprocess_thread, NULL);
|
||||
+ TEST_VERIFY (xpthread_join (thr) == NULL);
|
||||
+ TEST_COMPARE (altered_by_debugger, 1);
|
||||
+ _exit (0);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ pid_t tested_pid = xfork ();
|
||||
+ if (tested_pid == 0)
|
||||
+ in_subprocess ();
|
||||
+ char *tested_pid_string = xasprintf ("%d", tested_pid);
|
||||
+
|
||||
+ char *gdbscript;
|
||||
+ xclose (create_temp_file ("tst-pthread-gdb-attach-", &gdbscript));
|
||||
+ write_gdbscript (gdbscript, tested_pid);
|
||||
+
|
||||
+ pid_t gdb_pid = xfork ();
|
||||
+ if (gdb_pid == 0)
|
||||
+ {
|
||||
+ clearenv ();
|
||||
+ xdup2 (STDOUT_FILENO, STDERR_FILENO);
|
||||
+ execlp ("gdb", "gdb", "-nx", "-batch", "-x", gdbscript, NULL);
|
||||
+ if (errno == ENOENT)
|
||||
+ _exit (EXIT_UNSUPPORTED);
|
||||
+ else
|
||||
+ _exit (1);
|
||||
+ }
|
||||
+
|
||||
+ int status;
|
||||
+ TEST_COMPARE (xwaitpid (gdb_pid, &status, 0), gdb_pid);
|
||||
+ if (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_UNSUPPORTED)
|
||||
+ /* gdb is not installed. */
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+ TEST_COMPARE (status, 0);
|
||||
+ TEST_COMPARE (xwaitpid (tested_pid, &status, 0), tested_pid);
|
||||
+ TEST_COMPARE (status, 0);
|
||||
+
|
||||
+ free (tested_pid_string);
|
||||
+ free (gdbscript);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nptl_db/structs.def b/nptl_db/structs.def
|
||||
index 999a9fc35a0c742f..8a613dd2f5fc016b 100644
|
||||
--- a/nptl_db/structs.def
|
||||
+++ b/nptl_db/structs.def
|
||||
@@ -100,8 +100,7 @@ DB_STRUCT_FIELD (pthread, dtvp)
|
||||
#endif
|
||||
|
||||
#if !(IS_IN (libpthread) && !defined SHARED)
|
||||
-DB_STRUCT (rtld_global)
|
||||
-DB_RTLD_VARIABLE (_rtld_global)
|
||||
+DB_VARIABLE (__nptl_rtld_global)
|
||||
#endif
|
||||
DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
|
||||
DB_RTLD_GLOBAL_FIELD (dl_stack_user)
|
||||
diff --git a/nptl_db/td_init.c b/nptl_db/td_init.c
|
||||
index 1d15681228470c3a..06b5adc5c2941841 100644
|
||||
--- a/nptl_db/td_init.c
|
||||
+++ b/nptl_db/td_init.c
|
||||
@@ -33,13 +33,14 @@ td_init (void)
|
||||
bool
|
||||
__td_ta_rtld_global (td_thragent_t *ta)
|
||||
{
|
||||
- if (ta->ta_addr__rtld_global == 0
|
||||
- && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
|
||||
- &ta->ta_addr__rtld_global) != PS_OK)
|
||||
+ if (ta->ta_addr__rtld_global == 0)
|
||||
{
|
||||
- ta->ta_addr__rtld_global = (void*)-1;
|
||||
- return false;
|
||||
+ psaddr_t rtldglobalp;
|
||||
+ if (DB_GET_VALUE (rtldglobalp, ta, __nptl_rtld_global, 0) == TD_OK)
|
||||
+ ta->ta_addr__rtld_global = rtldglobalp;
|
||||
+ else
|
||||
+ ta->ta_addr__rtld_global = (void *) -1;
|
||||
}
|
||||
- else
|
||||
- return ta->ta_addr__rtld_global != (void*)-1;
|
||||
+
|
||||
+ return ta->ta_addr__rtld_global != (void *)-1;
|
||||
}
|
||||
diff --git a/nptl_db/thread_dbP.h b/nptl_db/thread_dbP.h
|
||||
index 580a70c471d45982..712fa3aeb6bd67de 100644
|
||||
--- a/nptl_db/thread_dbP.h
|
||||
+++ b/nptl_db/thread_dbP.h
|
||||
@@ -108,6 +108,8 @@ struct td_thragent
|
||||
# undef DB_SYMBOL
|
||||
# undef DB_VARIABLE
|
||||
|
||||
+ psaddr_t ta_addr__rtld_global;
|
||||
+
|
||||
/* The method of locating a thread's th_unique value. */
|
||||
enum
|
||||
{
|
131
glibc-upstream-2.33-39.patch
Normal file
131
glibc-upstream-2.33-39.patch
Normal file
@ -0,0 +1,131 @@
|
||||
commit 36783141cf090412e3e6f042f25f7f6c63d6a14a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 22 11:07:43 2021 +0200
|
||||
|
||||
nptl: Check for compatible GDB in nptl/tst-pthread-gdb-attach
|
||||
|
||||
Also do not clear the subprocess environment, in case running
|
||||
GDB needs certain environment variables.
|
||||
|
||||
(cherry picked from commit f553dc066071a4465321fbc122bed8a75afd996b)
|
||||
|
||||
diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c
|
||||
index 0603ad844defb8de..901a12003426d342 100644
|
||||
--- a/nptl/tst-pthread-gdb-attach.c
|
||||
+++ b/nptl/tst-pthread-gdb-attach.c
|
||||
@@ -20,8 +20,12 @@
|
||||
whether libthread_db can be loaded, and that access to thread-local
|
||||
variables works. */
|
||||
|
||||
+#include <elf.h>
|
||||
#include <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
@@ -35,6 +39,49 @@
|
||||
the thread. */
|
||||
__thread volatile int altered_by_debugger;
|
||||
|
||||
+/* Common prefix between 32-bit and 64-bit ELF. */
|
||||
+struct elf_prefix
|
||||
+{
|
||||
+ unsigned char e_ident[EI_NIDENT];
|
||||
+ uint16_t e_type;
|
||||
+ uint16_t e_machine;
|
||||
+ uint32_t e_version;
|
||||
+};
|
||||
+_Static_assert (sizeof (struct elf_prefix) == EI_NIDENT + 8,
|
||||
+ "padding in struct elf_prefix");
|
||||
+
|
||||
+/* Reads the ELF header from PATH. Returns true if the header can be
|
||||
+ read, false if the file is too short. */
|
||||
+static bool
|
||||
+read_elf_header (const char *path, struct elf_prefix *elf)
|
||||
+{
|
||||
+ int fd = xopen (path, O_RDONLY, 0);
|
||||
+ bool result = read (fd, elf, sizeof (*elf)) == sizeof (*elf);
|
||||
+ xclose (fd);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+/* Searches for "gdb" alongside the path variable. See execvpe. */
|
||||
+static char *
|
||||
+find_gdb (void)
|
||||
+{
|
||||
+ const char *path = getenv ("PATH");
|
||||
+ if (path == NULL)
|
||||
+ return NULL;
|
||||
+ while (true)
|
||||
+ {
|
||||
+ const char *colon = strchrnul (path, ':');
|
||||
+ char *candidate = xasprintf ("%.*s/gdb", (int) (colon - path), path);
|
||||
+ if (access (candidate, X_OK) == 0)
|
||||
+ return candidate;
|
||||
+ free (candidate);
|
||||
+ if (*colon == '\0')
|
||||
+ break;
|
||||
+ path = colon + 1;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/* Writes the GDB script to run the test to PATH. */
|
||||
static void
|
||||
write_gdbscript (const char *path, int tested_pid)
|
||||
@@ -105,6 +152,33 @@ in_subprocess (void)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
+ char *gdb_path = find_gdb ();
|
||||
+ if (gdb_path == NULL)
|
||||
+ FAIL_UNSUPPORTED ("gdb command not found in PATH: %s", getenv ("PATH"));
|
||||
+
|
||||
+ /* Check that libthread_db is compatible with the gdb architecture
|
||||
+ because gdb loads it via dlopen. */
|
||||
+ {
|
||||
+ char *threaddb_path = xasprintf ("%s/nptl_db/libthread_db.so",
|
||||
+ support_objdir_root);
|
||||
+ struct elf_prefix elf_threaddb;
|
||||
+ TEST_VERIFY_EXIT (read_elf_header (threaddb_path, &elf_threaddb));
|
||||
+ struct elf_prefix elf_gdb;
|
||||
+ /* If the ELF header cannot be read or "gdb" is not an ELF file,
|
||||
+ assume this is a wrapper script that can run. */
|
||||
+ if (read_elf_header (gdb_path, &elf_gdb)
|
||||
+ && memcmp (&elf_gdb, ELFMAG, SELFMAG) == 0)
|
||||
+ {
|
||||
+ if (elf_gdb.e_ident[EI_CLASS] != elf_threaddb.e_ident[EI_CLASS])
|
||||
+ FAIL_UNSUPPORTED ("GDB at %s has wrong class", gdb_path);
|
||||
+ if (elf_gdb.e_ident[EI_DATA] != elf_threaddb.e_ident[EI_DATA])
|
||||
+ FAIL_UNSUPPORTED ("GDB at %s has wrong data", gdb_path);
|
||||
+ if (elf_gdb.e_machine != elf_threaddb.e_machine)
|
||||
+ FAIL_UNSUPPORTED ("GDB at %s has wrong machine", gdb_path);
|
||||
+ }
|
||||
+ free (threaddb_path);
|
||||
+ }
|
||||
+
|
||||
pid_t tested_pid = xfork ();
|
||||
if (tested_pid == 0)
|
||||
in_subprocess ();
|
||||
@@ -117,9 +191,8 @@ do_test (void)
|
||||
pid_t gdb_pid = xfork ();
|
||||
if (gdb_pid == 0)
|
||||
{
|
||||
- clearenv ();
|
||||
xdup2 (STDOUT_FILENO, STDERR_FILENO);
|
||||
- execlp ("gdb", "gdb", "-nx", "-batch", "-x", gdbscript, NULL);
|
||||
+ execl (gdb_path, "gdb", "-nx", "-batch", "-x", gdbscript, NULL);
|
||||
if (errno == ENOENT)
|
||||
_exit (EXIT_UNSUPPORTED);
|
||||
else
|
||||
@@ -137,6 +210,7 @@ do_test (void)
|
||||
|
||||
free (tested_pid_string);
|
||||
free (gdbscript);
|
||||
+ free (gdb_path);
|
||||
return 0;
|
||||
}
|
||||
|
22
glibc-upstream-2.33-40.patch
Normal file
22
glibc-upstream-2.33-40.patch
Normal file
@ -0,0 +1,22 @@
|
||||
commit 3f5080aedd164c1f92a53552dd3e0b82ac6d2bd3
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 22 19:53:15 2021 +0200
|
||||
|
||||
nptl: Do not build nptl/tst-pthread-gdb-attach as PIE
|
||||
|
||||
(cherry picked from commit 6f3e54d404cfe1ba7d1444e6dfcfd77b102d9287)
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index 1ca23385d4de9000..a1a8ef254b3c3b17 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -353,6 +353,9 @@ endif
|
||||
CFLAGS-tst-pthread-gdb-attach-static.c := $(CFLAGS-printers-tests)
|
||||
CPPFLAGS-tst-pthread-gdb-attach-static.c := \
|
||||
$(CFLAGS-printers-tests) -DDO_ADD_SYMBOL_FILE=0
|
||||
+# As of version 9.2, GDB cannot attach properly to PIE programs that
|
||||
+# were launched with an explicit ld.so invocation.
|
||||
+tst-pthread-gdb-attach-no-pie = yes
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
tests-printers-libs := $(shared-thread-library)
|
2499
glibc.spec
2499
glibc.spec
File diff suppressed because it is too large
Load Diff
63
wrap-find-debuginfo.sh
Normal file
63
wrap-find-debuginfo.sh
Normal file
@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# Wrapper script for find-debuginfo.sh
|
||||
#
|
||||
# Usage:
|
||||
# wrap-find-debuginfo.sh LDSO-PATH SCRIPT-PATH SCRIPT-ARGS...
|
||||
#
|
||||
# The wrapper saves the original versions of the file at LDSO-PATH,
|
||||
# invokes SCRIPT-PATH with SCRIPT-ARGS, and then restores the
|
||||
# LDSO-PATH file. As a result, LDSO-PATH has unchanged debuginfo even
|
||||
# after debuginfo extraction.
|
||||
|
||||
set -ex
|
||||
|
||||
ldso_tmp="$(mktemp)"
|
||||
|
||||
cleanup () {
|
||||
rm -f "$ldso_tmp"
|
||||
}
|
||||
trap cleanup 0
|
||||
|
||||
ldso_path="$1"
|
||||
shift
|
||||
script_path="$1"
|
||||
shift
|
||||
|
||||
# Preserve the original file.
|
||||
cp "$ldso_path" "$ldso_tmp"
|
||||
|
||||
# Run the debuginfo extraction.
|
||||
"$script_path" "$@"
|
||||
|
||||
# Restore the original file.
|
||||
cp "$ldso_tmp" "$ldso_path"
|
||||
|
||||
# Reduce the size of notes. Primarily for annobin.
|
||||
objcopy --merge-notes "$ldso_path"
|
||||
|
||||
# Rewrite the source file paths to match the extracted locations.
|
||||
# First compute the arguments for invoking debugedit. See
|
||||
# find-debuginfo.sh.
|
||||
debug_dest_name="/usr/src/debug"
|
||||
last_arg=
|
||||
while true ; do
|
||||
arg="$1"
|
||||
shift || break
|
||||
case "$arg" in
|
||||
(--unique-debug-src-base)
|
||||
debug_dest_name="/usr/src/debug/$1"
|
||||
shift
|
||||
;;
|
||||
(-*)
|
||||
;;
|
||||
(*)
|
||||
last_arg="$arg"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
debug_base_name=${last_arg:-$RPM_BUILD_ROOT}
|
||||
/usr/lib/rpm/debugedit -b "$debug_base_name" -d "$debug_dest_name" -n \
|
||||
$ldso_path
|
||||
|
||||
# Apply single-file DWARF optimization.
|
||||
dwz $ldso_path
|
Loading…
Reference in New Issue
Block a user