Make __rseq_size useful for feature detection (RHEL-65280)
Resolves: RHEL-65280
This commit is contained in:
parent
025c5d4ac2
commit
6e489a733f
29
glibc-RHEL-65280-1.patch
Normal file
29
glibc-RHEL-65280-1.patch
Normal file
@ -0,0 +1,29 @@
|
||||
commit 8754a4133e154ca853e6765a3fe5c7a904c77626
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Fri May 26 15:03:31 2023 +0000
|
||||
|
||||
Add AT_RSEQ_* from Linux 6.3 to elf.h
|
||||
|
||||
Linux 6.3 adds constants AT_RSEQ_FEATURE_SIZE and AT_RSEQ_ALIGN; add
|
||||
them to glibc's elf.h. (Recall that, although elf.h is a
|
||||
system-independent header, so far we've put AT_* constants there even
|
||||
if Linux-specific, as discussed in bug 15794. So rather than making
|
||||
any attempt to fix that issue, the new constants are just added there
|
||||
alongside the existing ones.)
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/elf/elf.h b/elf/elf.h
|
||||
index 4738dfa28f6549fc..076d8e3f696c58f7 100644
|
||||
--- a/elf/elf.h
|
||||
+++ b/elf/elf.h
|
||||
@@ -1205,6 +1205,9 @@ typedef struct
|
||||
#define AT_HWCAP2 26 /* More machine-dependent hints about
|
||||
processor capabilities. */
|
||||
|
||||
+#define AT_RSEQ_FEATURE_SIZE 27 /* rseq supported feature size. */
|
||||
+#define AT_RSEQ_ALIGN 28 /* rseq allocation alignment. */
|
||||
+
|
||||
#define AT_EXECFN 31 /* Filename of executable. */
|
||||
|
||||
/* Pointer to the global system page used for system calls and other
|
152
glibc-RHEL-65280-2.patch
Normal file
152
glibc-RHEL-65280-2.patch
Normal file
@ -0,0 +1,152 @@
|
||||
commit 2b92982e2369d292560793bee8e730f695f48ff3
|
||||
Author: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Wed Jul 3 12:35:34 2024 -0400
|
||||
|
||||
nptl: fix potential merge of __rseq_* relro symbols
|
||||
|
||||
While working on a patch to add support for the extensible rseq ABI, we
|
||||
came across an issue where a new 'const' variable would be merged with
|
||||
the existing '__rseq_size' variable. We tracked this to the use of
|
||||
'-fmerge-all-constants' which allows the compiler to merge identical
|
||||
constant variables. This means that all 'const' variables in a compile
|
||||
unit that are of the same size and are initialized to the same value can
|
||||
be merged.
|
||||
|
||||
In this specific case, on 32 bit systems 'unsigned int' and 'ptrdiff_t'
|
||||
are both 4 bytes and initialized to 0 which should trigger the merge.
|
||||
However for reasons we haven't delved into when the attribute 'section
|
||||
(".data.rel.ro")' is added to the mix, only variables of the same exact
|
||||
types are merged. As far as we know this behavior is not specified
|
||||
anywhere and could change with a new compiler version, hence this patch.
|
||||
|
||||
Move the definitions of these variables into an assembler file and add
|
||||
hidden writable aliases for internal use. This has the added bonus of
|
||||
removing the asm workaround to set the values on rseq registration.
|
||||
|
||||
Tested on Debian 12 with GCC 12.2.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index e0a86a305c4dc2ed..ec0d67b1549823ad 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -69,6 +69,7 @@ dl-routines = \
|
||||
dl-printf \
|
||||
dl-profile \
|
||||
dl-reloc \
|
||||
+ dl-rseq-symbols \
|
||||
dl-runtime \
|
||||
dl-scope \
|
||||
dl-setup_hash \
|
||||
diff --git a/elf/dl-rseq-symbols.S b/elf/dl-rseq-symbols.S
|
||||
new file mode 100644
|
||||
index 0000000000000000..b4bba06a99b0a486
|
||||
--- /dev/null
|
||||
+++ b/elf/dl-rseq-symbols.S
|
||||
@@ -0,0 +1,64 @@
|
||||
+/* Define symbols used by rseq.
|
||||
+ Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+
|
||||
+#if __WORDSIZE == 64
|
||||
+#define RSEQ_OFFSET_SIZE 8
|
||||
+#else
|
||||
+#define RSEQ_OFFSET_SIZE 4
|
||||
+#endif
|
||||
+
|
||||
+/* Some targets define a macro to denote the zero register. */
|
||||
+#undef zero
|
||||
+
|
||||
+/* Define 2 symbols: '__rseq_size' is public const and '_rseq_size' (an
|
||||
+ alias of '__rseq_size') is hidden and writable for internal use by the
|
||||
+ dynamic linker which will initialize the value both symbols point to
|
||||
+ before copy relocations take place. */
|
||||
+
|
||||
+ .globl __rseq_size
|
||||
+ .type __rseq_size, %object
|
||||
+ .size __rseq_size, 4
|
||||
+ .hidden _rseq_size
|
||||
+ .globl _rseq_size
|
||||
+ .type _rseq_size, %object
|
||||
+ .size _rseq_size, 4
|
||||
+ .section .data.rel.ro
|
||||
+ .balign 4
|
||||
+__rseq_size:
|
||||
+_rseq_size:
|
||||
+ .zero 4
|
||||
+
|
||||
+/* Define 2 symbols: '__rseq_offset' is public const and '_rseq_offset' (an
|
||||
+ alias of '__rseq_offset') is hidden and writable for internal use by the
|
||||
+ dynamic linker which will initialize the value both symbols point to
|
||||
+ before copy relocations take place. */
|
||||
+
|
||||
+ .globl __rseq_offset
|
||||
+ .type __rseq_offset, %object
|
||||
+ .size __rseq_offset, RSEQ_OFFSET_SIZE
|
||||
+ .hidden _rseq_offset
|
||||
+ .globl _rseq_offset
|
||||
+ .type _rseq_offset, %object
|
||||
+ .size _rseq_offset, RSEQ_OFFSET_SIZE
|
||||
+ .section .data.rel.ro
|
||||
+ .balign RSEQ_OFFSET_SIZE
|
||||
+__rseq_offset:
|
||||
+_rseq_offset:
|
||||
+ .zero RSEQ_OFFSET_SIZE
|
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
index d5f2587f1348441c..039080d7110f5064 100644
|
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c
|
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
@@ -45,8 +45,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
|
||||
#endif
|
||||
|
||||
const unsigned int __rseq_flags;
|
||||
-const unsigned int __rseq_size attribute_relro;
|
||||
-const ptrdiff_t __rseq_offset attribute_relro;
|
||||
+
|
||||
+/* The variables are in .data.relro but are not yet write-protected. */
|
||||
+extern unsigned int _rseq_size attribute_hidden;
|
||||
+extern ptrdiff_t _rseq_offset attribute_hidden;
|
||||
|
||||
void
|
||||
__tls_pre_init_tp (void)
|
||||
@@ -107,10 +109,7 @@ __tls_init_tp (void)
|
||||
#endif
|
||||
if (rseq_register_current_thread (pd, do_rseq))
|
||||
{
|
||||
- /* We need a writable view of the variables. They are in
|
||||
- .data.relro and are not yet write-protected. */
|
||||
- extern unsigned int size __asm__ ("__rseq_size");
|
||||
- size = sizeof (pd->rseq_area);
|
||||
+ _rseq_size = sizeof (pd->rseq_area);
|
||||
}
|
||||
|
||||
#ifdef RSEQ_SIG
|
||||
@@ -119,8 +118,7 @@ __tls_init_tp (void)
|
||||
all targets support __thread_pointer, so set __rseq_offset only
|
||||
if thre rseq registration may have happened because RSEQ_SIG is
|
||||
defined. */
|
||||
- extern ptrdiff_t offset __asm__ ("__rseq_offset");
|
||||
- offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
|
||||
+ _rseq_offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
|
||||
#endif
|
||||
}
|
||||
|
136
glibc-RHEL-65280-3.patch
Normal file
136
glibc-RHEL-65280-3.patch
Normal file
@ -0,0 +1,136 @@
|
||||
commit 2e456ccf0c34a056e3ccafac4a0c7effef14d918
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jul 8 21:14:00 2024 +0200
|
||||
|
||||
Linux: Make __rseq_size useful for feature detection (bug 31965)
|
||||
|
||||
The __rseq_size value is now the active area of struct rseq
|
||||
(so 20 initially), not the full struct size including padding
|
||||
at the end (32 initially).
|
||||
|
||||
Update misc/tst-rseq to print some additional diagnostics.
|
||||
|
||||
Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
|
||||
diff --git a/manual/threads.texi b/manual/threads.texi
|
||||
index 3fd307e69a8029fa..42e824fcdbec60f6 100644
|
||||
--- a/manual/threads.texi
|
||||
+++ b/manual/threads.texi
|
||||
@@ -1007,8 +1007,12 @@ This variable is either zero (if restartable sequence registration
|
||||
failed or has been disabled) or the size of the restartable sequence
|
||||
registration. This can be different from the size of @code{struct rseq}
|
||||
if the kernel has extended the size of the registration. If
|
||||
-registration is successful, @code{__rseq_size} is at least 32 (the
|
||||
-initial size of @code{struct rseq}).
|
||||
+registration is successful, @code{__rseq_size} is at least 20 (the
|
||||
+initially active size of @code{struct rseq}).
|
||||
+
|
||||
+Previous versions of @theglibc{} set this to 32 even if the kernel only
|
||||
+supported the initial area of 20 bytes because the value included unused
|
||||
+padding at the end of the restartable sequence area.
|
||||
@end deftypevar
|
||||
|
||||
@deftypevar {unsigned int} __rseq_flags
|
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
index 039080d7110f5064..2f56281a02246a09 100644
|
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c
|
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
@@ -46,10 +46,6 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
|
||||
|
||||
const unsigned int __rseq_flags;
|
||||
|
||||
-/* The variables are in .data.relro but are not yet write-protected. */
|
||||
-extern unsigned int _rseq_size attribute_hidden;
|
||||
-extern ptrdiff_t _rseq_offset attribute_hidden;
|
||||
-
|
||||
void
|
||||
__tls_pre_init_tp (void)
|
||||
{
|
||||
@@ -108,9 +104,7 @@ __tls_init_tp (void)
|
||||
do_rseq = TUNABLE_GET (rseq, int, NULL);
|
||||
#endif
|
||||
if (rseq_register_current_thread (pd, do_rseq))
|
||||
- {
|
||||
- _rseq_size = sizeof (pd->rseq_area);
|
||||
- }
|
||||
+ _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
|
||||
|
||||
#ifdef RSEQ_SIG
|
||||
/* This should be a compile-time constant, but the current
|
||||
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
index 9e8f99fd51a063b1..ccb16640133fa9e3 100644
|
||||
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
@@ -25,15 +25,34 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/rseq.h>
|
||||
|
||||
+/* 32 is the initially required value for the area size. The
|
||||
+ actually used rseq size may be less (20 bytes initially). */
|
||||
+#define RSEQ_AREA_SIZE_INITIAL 32
|
||||
+#define RSEQ_AREA_SIZE_INITIAL_USED 20
|
||||
+
|
||||
+/* The variables are in .data.relro but are not yet write-protected. */
|
||||
+extern unsigned int _rseq_size attribute_hidden;
|
||||
+extern ptrdiff_t _rseq_offset attribute_hidden;
|
||||
+
|
||||
#ifdef RSEQ_SIG
|
||||
static inline bool
|
||||
rseq_register_current_thread (struct pthread *self, bool do_rseq)
|
||||
{
|
||||
if (do_rseq)
|
||||
{
|
||||
+ unsigned int size;
|
||||
+#if IS_IN (rtld)
|
||||
+ /* Use the hidden symbol in ld.so. */
|
||||
+ size = _rseq_size;
|
||||
+#else
|
||||
+ size = __rseq_size;
|
||||
+#endif
|
||||
+ if (size < RSEQ_AREA_SIZE_INITIAL)
|
||||
+ /* The initial implementation used only 20 bytes out of 32,
|
||||
+ but still expected size 32. */
|
||||
+ size = RSEQ_AREA_SIZE_INITIAL;
|
||||
int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
|
||||
- sizeof (self->rseq_area),
|
||||
- 0, RSEQ_SIG);
|
||||
+ size, 0, RSEQ_SIG);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (ret))
|
||||
return true;
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
index 572c11166f8b6533..1d404db610c08fdf 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
@@ -29,6 +29,7 @@
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <syscall.h>
|
||||
+# include <sys/auxv.h>
|
||||
# include <thread_pointer.h>
|
||||
# include <tls.h>
|
||||
# include "tst-rseq.h"
|
||||
@@ -42,7 +43,8 @@ do_rseq_main_test (void)
|
||||
TEST_COMPARE (__rseq_flags, 0);
|
||||
TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
|
||||
== (char *) &pd->rseq_area);
|
||||
- TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
|
||||
+ /* The current implementation only supports the initial size. */
|
||||
+ TEST_COMPARE (__rseq_size, 20);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -52,6 +54,12 @@ do_rseq_test (void)
|
||||
{
|
||||
FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
|
||||
}
|
||||
+ printf ("info: __rseq_size: %u\n", __rseq_size);
|
||||
+ printf ("info: __rseq_offset: %td\n", __rseq_offset);
|
||||
+ printf ("info: __rseq_flags: %u\n", __rseq_flags);
|
||||
+ printf ("info: getauxval (AT_RSEQ_FEATURE_SIZE): %ld\n",
|
||||
+ getauxval (AT_RSEQ_FEATURE_SIZE));
|
||||
+ printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN));
|
||||
do_rseq_main_test ();
|
||||
}
|
||||
#else /* RSEQ_SIG */
|
54
glibc-RHEL-65280-4.patch
Normal file
54
glibc-RHEL-65280-4.patch
Normal file
@ -0,0 +1,54 @@
|
||||
commit 97f60abd25628425971f07e9b0e7f8eec0741235
|
||||
Author: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Thu Nov 7 22:23:49 2024 +0100
|
||||
|
||||
nptl: initialize rseq area prior to registration
|
||||
|
||||
Per the rseq syscall documentation, 3 fields are required to be
|
||||
initialized by userspace prior to registration, they are 'cpu_id',
|
||||
'rseq_cs' and 'flags'. Since we have no guarantee that 'struct pthread'
|
||||
is cleared on all architectures, explicitly set those 3 fields prior to
|
||||
registration.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/nptl/descr.h b/nptl/descr.h
|
||||
index 6484e3703f9a0a97..c08c5149c7239e7c 100644
|
||||
--- a/nptl/descr.h
|
||||
+++ b/nptl/descr.h
|
||||
@@ -424,6 +424,8 @@ struct pthread
|
||||
{
|
||||
uint32_t cpu_id_start;
|
||||
uint32_t cpu_id;
|
||||
+ uint64_t rseq_cs;
|
||||
+ uint32_t flags;
|
||||
};
|
||||
char pad[32]; /* Original rseq area size. */
|
||||
} rseq_area __attribute__ ((aligned (32)));
|
||||
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
index ccb16640133fa9e3..7e70ae7ebdee4917 100644
|
||||
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
@@ -51,11 +51,21 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq)
|
||||
/* The initial implementation used only 20 bytes out of 32,
|
||||
but still expected size 32. */
|
||||
size = RSEQ_AREA_SIZE_INITIAL;
|
||||
+
|
||||
+ /* Initialize the rseq fields that are read by the kernel on
|
||||
+ registration, there is no guarantee that struct pthread is
|
||||
+ cleared on all architectures. */
|
||||
+ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_UNINITIALIZED);
|
||||
+ THREAD_SETMEM (self, rseq_area.rseq_cs, 0);
|
||||
+ THREAD_SETMEM (self, rseq_area.flags, 0);
|
||||
+
|
||||
int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
|
||||
size, 0, RSEQ_SIG);
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (ret))
|
||||
return true;
|
||||
}
|
||||
+ /* When rseq is disabled by tunables or the registration fails, inform
|
||||
+ userspace by setting 'cpu_id' to RSEQ_CPU_ID_REGISTRATION_FAILED. */
|
||||
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
|
||||
return false;
|
||||
}
|
28
glibc-RHEL-65280-5.patch
Normal file
28
glibc-RHEL-65280-5.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit d9f40387d3305d97e30a8cf8724218c42a63680a
|
||||
Author: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Wed Nov 20 14:15:42 2024 -0500
|
||||
|
||||
nptl: initialize cpu_id_start prior to rseq registration
|
||||
|
||||
When adding explicit initialization of rseq fields prior to
|
||||
registration, I glossed over the fact that 'cpu_id_start' is also
|
||||
documented as initialized by user-space.
|
||||
|
||||
While current kernels don't validate the content of this field on
|
||||
registration, future ones could.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
index 7e70ae7ebdee4917..c108a12a6227eeac 100644
|
||||
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
@@ -56,6 +56,7 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq)
|
||||
registration, there is no guarantee that struct pthread is
|
||||
cleared on all architectures. */
|
||||
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_UNINITIALIZED);
|
||||
+ THREAD_SETMEM (self, rseq_area.cpu_id_start, 0);
|
||||
THREAD_SETMEM (self, rseq_area.rseq_cs, 0);
|
||||
THREAD_SETMEM (self, rseq_area.flags, 0);
|
||||
|
158
glibc-RHEL-65280-6.patch
Normal file
158
glibc-RHEL-65280-6.patch
Normal file
@ -0,0 +1,158 @@
|
||||
commit c813c1490d5d8640a94fced10fc7674a48737b96
|
||||
Author: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Wed Jul 10 15:37:28 2024 -0400
|
||||
|
||||
nptl: Add rseq auxvals
|
||||
|
||||
Get the rseq feature size and alignment requirement from the auxiliary
|
||||
vector for use inside the dynamic loader. Use '__rseq_size' directly to
|
||||
store the feature size. If the main thread registration fails or is
|
||||
disabled by tunable, reset the value to 0.
|
||||
|
||||
This will be used in the TLS block allocator to compute the size and
|
||||
alignment of the rseq area block for the extended ABI support.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
sysdeps/nptl/dl-tls_init_tp.c: Adjust for skipped commit:
|
||||
33237fe83d553dff (Remove --enable-tunables configure option)
|
||||
|
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
index 2f56281a02246a09..20552b11843148fb 100644
|
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c
|
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
@@ -46,6 +46,8 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
|
||||
|
||||
const unsigned int __rseq_flags;
|
||||
|
||||
+size_t _rseq_align attribute_hidden;
|
||||
+
|
||||
void
|
||||
__tls_pre_init_tp (void)
|
||||
{
|
||||
@@ -99,12 +101,17 @@ __tls_init_tp (void)
|
||||
}
|
||||
|
||||
{
|
||||
+ /* If the registration fails or is disabled by tunable, the public
|
||||
+ '__rseq_size' will be set to '0' regardless of the feature size of the
|
||||
+ allocated rseq area. An rseq area of at least 32 bytes is always
|
||||
+ allocated since application code is allowed to check the status of the
|
||||
+ rseq registration by reading the content of the 'cpu_id' field. */
|
||||
bool do_rseq = true;
|
||||
#if HAVE_TUNABLES
|
||||
do_rseq = TUNABLE_GET (rseq, int, NULL);
|
||||
#endif
|
||||
- if (rseq_register_current_thread (pd, do_rseq))
|
||||
- _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
|
||||
+ if (!rseq_register_current_thread (pd, do_rseq))
|
||||
+ _rseq_size = 0;
|
||||
|
||||
#ifdef RSEQ_SIG
|
||||
/* This should be a compile-time constant, but the current
|
||||
diff --git a/sysdeps/unix/sysv/linux/dl-parse_auxv.h b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
|
||||
index bf9374371eb217fc..44c135c56570134e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/dl-parse_auxv.h
|
||||
+++ b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <fpu_control.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <link.h>
|
||||
+#include <rseq-internal.h>
|
||||
|
||||
typedef ElfW(Addr) dl_parse_auxv_t[AT_MINSIGSTKSZ + 1];
|
||||
|
||||
@@ -57,5 +58,17 @@ void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
|
||||
GLRO(dl_sysinfo) = auxv_values[AT_SYSINFO];
|
||||
#endif
|
||||
|
||||
+ /* Get the rseq feature size, with a minimum of RSEQ_AREA_SIZE_INITIAL_USED
|
||||
+ (20) for kernels that don't have AT_RSEQ_FEATURE_SIZE. Limit the feature
|
||||
+ size to RSEQ_AREA_SIZE_MAX_USED (28) which fits the rseq area in 'struct
|
||||
+ pthread' and represents the maximum feature size of currently released
|
||||
+ kernels. Since no kernels currently cross the 32 bytes of the original
|
||||
+ ABI, the semantics of a feature size of 32 or more are still undetermined.
|
||||
+ */
|
||||
+ _rseq_size = MIN (MAX (auxv_values[AT_RSEQ_FEATURE_SIZE],
|
||||
+ RSEQ_AREA_SIZE_INITIAL_USED),
|
||||
+ RSEQ_AREA_SIZE_MAX_USED);
|
||||
+ _rseq_align = MAX (auxv_values[AT_RSEQ_ALIGN], RSEQ_MIN_ALIGN);
|
||||
+
|
||||
DL_PLATFORM_AUXV
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
index c108a12a6227eeac..f4027b09519a652b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
|
||||
@@ -25,13 +25,31 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/rseq.h>
|
||||
|
||||
-/* 32 is the initially required value for the area size. The
|
||||
- actually used rseq size may be less (20 bytes initially). */
|
||||
+/* Minimum size of the rseq area allocation required by the syscall. The
|
||||
+ actually used rseq feature size may be less (20 bytes initially). */
|
||||
#define RSEQ_AREA_SIZE_INITIAL 32
|
||||
+
|
||||
+/* Minimum used feature size of the rseq area. */
|
||||
#define RSEQ_AREA_SIZE_INITIAL_USED 20
|
||||
|
||||
-/* The variables are in .data.relro but are not yet write-protected. */
|
||||
+/* Maximum currently used feature size of the rseq area. */
|
||||
+#define RSEQ_AREA_SIZE_MAX_USED 28
|
||||
+
|
||||
+/* Minimum alignment of the rseq area. */
|
||||
+#define RSEQ_MIN_ALIGN 32
|
||||
+
|
||||
+/* Alignment requirement of the rseq area.
|
||||
+ Populated from the auxiliary vector with a minimum of '32'.
|
||||
+ In .data.relro but not yet write-protected. */
|
||||
+extern size_t _rseq_align attribute_hidden;
|
||||
+
|
||||
+/* Size of the active features in the rseq area.
|
||||
+ Populated from the auxiliary vector with a minimum of '20'.
|
||||
+ In .data.relro but not yet write-protected. */
|
||||
extern unsigned int _rseq_size attribute_hidden;
|
||||
+
|
||||
+/* Offset from the thread pointer to the rseq area.
|
||||
+ In .data.relro but not yet write-protected. */
|
||||
extern ptrdiff_t _rseq_offset attribute_hidden;
|
||||
|
||||
#ifdef RSEQ_SIG
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
index 1d404db610c08fdf..5946db73d9b079c3 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
|
||||
@@ -38,13 +38,15 @@ static void
|
||||
do_rseq_main_test (void)
|
||||
{
|
||||
struct pthread *pd = THREAD_SELF;
|
||||
+ size_t rseq_feature_size = MIN (MAX (getauxval (AT_RSEQ_FEATURE_SIZE),
|
||||
+ RSEQ_AREA_SIZE_INITIAL_USED),
|
||||
+ RSEQ_AREA_SIZE_MAX_USED);
|
||||
|
||||
TEST_VERIFY_EXIT (rseq_thread_registered ());
|
||||
TEST_COMPARE (__rseq_flags, 0);
|
||||
TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
|
||||
== (char *) &pd->rseq_area);
|
||||
- /* The current implementation only supports the initial size. */
|
||||
- TEST_COMPARE (__rseq_size, 20);
|
||||
+ TEST_COMPARE (__rseq_size, rseq_feature_size);
|
||||
}
|
||||
|
||||
static void
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h
|
||||
index a476c316fc2671a0..86cf50fbeff32384 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq.h
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <syscall.h>
|
||||
#include <sys/rseq.h>
|
||||
#include <tls.h>
|
||||
+#include <rseq-internal.h>
|
||||
|
||||
static inline bool
|
||||
rseq_thread_registered (void)
|
11
glibc.spec
11
glibc.spec
@ -157,7 +157,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 172%{?dist}
|
||||
Release: 173%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -1123,6 +1123,12 @@ Patch815: glibc-RHEL-67593.patch
|
||||
Patch816: glibc-RHEL-46729.patch
|
||||
Patch817: glibc-RHEL-61569-1.patch
|
||||
Patch818: glibc-RHEL-61569-2.patch
|
||||
Patch819: glibc-RHEL-65280-1.patch
|
||||
Patch820: glibc-RHEL-65280-2.patch
|
||||
Patch821: glibc-RHEL-65280-3.patch
|
||||
Patch822: glibc-RHEL-65280-4.patch
|
||||
Patch823: glibc-RHEL-65280-5.patch
|
||||
Patch824: glibc-RHEL-65280-6.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -3116,6 +3122,9 @@ update_gconv_modules_cache ()
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Mar 06 2025 Arjun Shankar <arjun@redhat.com> - 2.34-173
|
||||
- Make __rseq_size useful for feature detection (RHEL-65280)
|
||||
|
||||
* Mon Mar 03 2025 Frederic Berat <fberat@redhat.com> - 2.34-172
|
||||
- Backport: support: Add support_next_to_fault_before support function
|
||||
(RHEL-61569)
|
||||
|
Loading…
Reference in New Issue
Block a user