tests: Handle system-wide tunables in rseq tests

Message ID 20260630185133.434497-1-mjeanson@efficios.com (mailing list archive)
State New
Headers
Series tests: Handle system-wide tunables in rseq tests |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 fail Test failed

Commit Message

Michael Jeanson June 30, 2026, 6:51 p.m. UTC
  With the new system-wide tunables, a local policy could override the
rseq tunable set by the build system when running the tests. Add a check
in the tests for the expected state of the tunable and fail if it has
been overriden.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
---
 sysdeps/unix/sysv/linux/tst-rseq-disable.c | 12 ++++++++++++
 sysdeps/unix/sysv/linux/tst-rseq-nptl.c    |  2 ++
 sysdeps/unix/sysv/linux/tst-rseq.c         |  2 ++
 sysdeps/unix/sysv/linux/tst-rseq.h         |  7 +++++++
 4 files changed, 23 insertions(+)
  

Comments

Yury Khrustalev July 2, 2026, 3:11 p.m. UTC | #1
On Tue, Jun 30, 2026 at 02:51:30PM -0400, Michael Jeanson wrote:
> With the new system-wide tunables, a local policy could override the
> rseq tunable set by the build system when running the tests. Add a check
> in the tests for the expected state of the tunable and fail if it has
> been overriden.

Could this be solved by running these tests in the container and having
an empty /etc/tunables.conf for them?
  
Michael Jeanson July 2, 2026, 3:35 p.m. UTC | #2
On 2026-07-02 11:11, Yury Khrustalev wrote:
> On Tue, Jun 30, 2026 at 02:51:30PM -0400, Michael Jeanson wrote:
>> With the new system-wide tunables, a local policy could override the
>> rseq tunable set by the build system when running the tests. Add a check
>> in the tests for the expected state of the tunable and fail if it has
>> been overriden.
> 
> Could this be solved by running these tests in the container and having
> an empty /etc/tunables.conf for them?

I'm not sure what 'the container' is in this context but if it's a 
generic way to isolate from the local system-wide tunables then yes it 
would.

Cheers,

Michael
  
DJ Delorie July 2, 2026, 3:48 p.m. UTC | #3
Michael Jeanson <mjeanson@efficios.com> writes:
> I'm not sure what 'the container' is in this context but if it's a 
> generic way to isolate from the local system-wide tunables then yes it 
> would.

Yes, the test-container is a chroot we build at test time that has an
installed glibc and a few utilities (like sh and cp) and a basic
filesystem (like /etc).  It also has the build and source trees mounted
inside it.  "Running a test in a container" means running it with
support/test-container.c, which manages setting up the container
(refreshing the install and pre-installing any test-specific files
needed for the test), running the test in it, and cleaning up the
container afterwards.

The primary purpose of this system is to allow us to test things that
need to be tested "live" without interfering with (or being affected by)
the host OS.

See https://developers.redhat.com/blog/2018/11/16/microcontainers-for-unit-testing
for some introduction.
  
Michael Jeanson July 2, 2026, 8:16 p.m. UTC | #4
On 2026-07-02 11:48, DJ Delorie wrote:
> Yes, the test-container is a chroot we build at test time that has an
> installed glibc and a few utilities (like sh and cp) and a basic
> filesystem (like /etc).  It also has the build and source trees mounted
> inside it.  "Running a test in a container" means running it with
> support/test-container.c, which manages setting up the container
> (refreshing the install and pre-installing any test-specific files
> needed for the test), running the test in it, and cleaning up the
> container afterwards.
> 
> The primary purpose of this system is to allow us to test things that
> need to be tested "live" without interfering with (or being affected by)
> the host OS.
> 
> See https://developers.redhat.com/blog/2018/11/16/microcontainers-for-unit-testing
> for some introduction.

I had a quick look and I'm not quite sure how to combine the 
'tests-internal' and 'tests-container' targets to allow running 
tst-rseq/tst-rseq-disable.

I don't know if the added complexity of the container is really required 
given the low probability of the testsuite being run with a system-wide 
policy on 'glibc.pthread.rseq'. Reporting the error to the user might be 
enough.

Thoughts?

Michael
  
DJ Delorie July 2, 2026, 8:23 p.m. UTC | #5
Michael Jeanson <mjeanson@efficios.com> writes:
> I had a quick look and I'm not quite sure how to combine the 
> 'tests-internal' and 'tests-container' targets to allow running 
> tst-rseq/tst-rseq-disable.

I seem to recall in the past, I've just added the one test to both lists
and it seemed to work.  It might depend on which two lists you're adding
it to.

> I don't know if the added complexity of the container is really required 
> given the low probability of the testsuite being run with a system-wide 
> policy on 'glibc.pthread.rseq'. Reporting the error to the user might be 
> enough.

I think a check in the test for the desired state, and UNSUPPORTED if
it's set wrong, is fine.  Especially if we're using an environment
variable to set a tunable, and the sysadmin has disallowed changing it
through a global config.  They had a reason, one hopes.
  
Yury Khrustalev July 3, 2026, 9:14 a.m. UTC | #6
Hi Michael,

On Thu, Jul 02, 2026 at 04:23:34PM -0400, DJ Delorie wrote:
> Michael Jeanson <mjeanson@efficios.com> writes:
> > I had a quick look and I'm not quite sure how to combine the 
> > 'tests-internal' and 'tests-container' targets to allow running 
> > tst-rseq/tst-rseq-disable.
> 
> I seem to recall in the past, I've just added the one test to both lists
> and it seemed to work.  It might depend on which two lists you're adding
> it to.

The elf/tst-tunconf1 test is added to both tests-internal and tests-container
in elf/Makefile. This test also has 'elf/tst-tunconf1.root' folder for
the container and it uses custom tunables. I think you could do the same
with the rseq tests.

Thanks,
Yury
  
Michael Jeanson July 3, 2026, 3:13 p.m. UTC | #7
On 2026-07-03 05:14, Yury Khrustalev wrote:
>>
>> I seem to recall in the past, I've just added the one test to both lists
>> and it seemed to work.  It might depend on which two lists you're adding
>> it to.
> 
> The elf/tst-tunconf1 test is added to both tests-internal and tests-container
> in elf/Makefile. This test also has 'elf/tst-tunconf1.root' folder for
> the container and it uses custom tunables. I think you could do the same
> with the rseq tests.

I thought I was doing something wrong but I get the same behavior with 
other container tests, when I try to run a single test like so:

   $ ../configure --prefix=/usr
   $ make -j$(nproc)
   $ make test t=elf/tst-tunconf1

The testroot.pristine is not created in the build dir and the test fails 
with:

FAIL: elf/tst-tunconf1
original exit status 1
error: test-container.c:835: Cannot create testroot lock.


If I run the full 'elf' testsuite:

   $ make subdirs=elf check -j$(nproc)

Then the testroot.pristine is created, all the tests succeed and I can 
then run the single test successfully. I tried finding the missing 
dependency in the Makefiles but couldn't quite figure it out.

Anyway, other than that it works, so do you prefer a second version of 
the patch using tests-container for the rseq tests or is this simple one 
that only adds the reporting good enough?

Thanks,

Michael
  
DJ Delorie July 3, 2026, 3:36 p.m. UTC | #8
Michael Jeanson <mjeanson@efficios.com> writes:
> The testroot.pristine is not created in the build dir

$ make $PWD/testroot.pristine/install.stamp

The initial testroot isn't created unless you do a full test run - that
was an optimization we decided on back when, to save time.  Warning: it
isn't re-built if you run "make check" again either, you need to delete
and remake the install.stamp to update it during development.

Every test after that just rsync's the pristine root to the working root
as needed.
  
Yury Khrustalev July 3, 2026, 3:38 p.m. UTC | #9
On Fri, Jul 03, 2026 at 11:13:45AM -0400, Michael Jeanson wrote:
> On 2026-07-03 05:14, Yury Khrustalev wrote:
> > > 
> > > I seem to recall in the past, I've just added the one test to both lists
> > > and it seemed to work.  It might depend on which two lists you're adding
> > > it to.
> > 
> > The elf/tst-tunconf1 test is added to both tests-internal and tests-container
> > in elf/Makefile. This test also has 'elf/tst-tunconf1.root' folder for
> > the container and it uses custom tunables. I think you could do the same
> > with the rseq tests.
> 
> I thought I was doing something wrong but I get the same behavior with other
> container tests, when I try to run a single test like so:
> 
>   $ ../configure --prefix=/usr
>   $ make -j$(nproc)
>   $ make test t=elf/tst-tunconf1
> 
> The testroot.pristine is not created in the build dir and the test fails
> with:
> 
> FAIL: elf/tst-tunconf1
> original exit status 1
> error: test-container.c:835: Cannot create testroot lock.

I also encountered this problem. You can generate testroot using this
command (run inside the build folder):

  make $(pwd)/testroot.pristine/install.stamp

> If I run the full 'elf' testsuite:
> 
>   $ make subdirs=elf check -j$(nproc)
> 
> Then the testroot.pristine is created, all the tests succeed and I can then
> run the single test successfully. I tried finding the missing dependency in
> the Makefiles but couldn't quite figure it out.

I agree it would be nice to fix makefile dependencies, but I don't know
an easy way to do that.

> Anyway, other than that it works, so do you prefer a second version of the
> patch using tests-container for the rseq tests or is this simple one that
> only adds the reporting good enough?

I think it's best to use test-container for the rseq tests so that we
can fully control the test environment for them.

Thanks,
Yury
  
Michael Jeanson July 3, 2026, 6:20 p.m. UTC | #10
On 2026-07-03 11:36, DJ Delorie wrote:
> Michael Jeanson <mjeanson@efficios.com> writes:
>> The testroot.pristine is not created in the build dir
> 
> $ make $PWD/testroot.pristine/install.stamp
> 
> The initial testroot isn't created unless you do a full test run - that
> was an optimization we decided on back when, to save time.  Warning: it
> isn't re-built if you run "make check" again either, you need to delete
> and remake the install.stamp to update it during development.
> 
> Every test after that just rsync's the pristine root to the working root
> as needed.

That works, thanks.

Also one more question, are system-wide tunables supposed to work with 
statically linked executables? In my test environment I'm able to make 
tst-rseq fail with a suitable /etc/tunables.conf but it seem to have no 
impact on tst-rseq-static.
  
Adhemerval Zanella Netto July 3, 2026, 7:24 p.m. UTC | #11
On 03/07/26 12:36, DJ Delorie wrote:
> Michael Jeanson <mjeanson@efficios.com> writes:
>> The testroot.pristine is not created in the build dir
> 
> $ make $PWD/testroot.pristine/install.stamp

As a side note, should we add this as an implicit rule for 'make test ...'?

> 
> The initial testroot isn't created unless you do a full test run - that
> was an optimization we decided on back when, to save time.  Warning: it
> isn't re-built if you run "make check" again either, you need to delete
> and remake the install.stamp to update it during development.
> 
> Every test after that just rsync's the pristine root to the working root
> as needed.
>
  
DJ Delorie July 6, 2026, 9:21 p.m. UTC | #12
Michael Jeanson <mjeanson@efficios.com> writes:
> Also one more question, are system-wide tunables supposed to work with 
> statically linked executables? In my test environment I'm able to make 
> tst-rseq fail with a suitable /etc/tunables.conf but it seem to have no 
> impact on tst-rseq-static.

The current code is conditional on both SHARED and USE_LDCONFIG, as the
data comes from /etc/ld.so.cache.

I don't remember exactly what the blocker here was, as we do support
calling dlopen() from a static binary, and I assume that must load
/etc/ld.so.cache.
  
DJ Delorie July 6, 2026, 9:24 p.m. UTC | #13
Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
> On 03/07/26 12:36, DJ Delorie wrote:
>> Michael Jeanson <mjeanson@efficios.com> writes:
>>> The testroot.pristine is not created in the build dir
>> 
>> $ make $PWD/testroot.pristine/install.stamp
>
> As a side note, should we add this as an implicit rule for 'make test ...'?

Please no ;-)

When I'm writing tests, I use "make test" a *lot* and rebuilding and
reinstalling the whole testroot each time would be a huge waste.

Maybe some parameter to "make test" like "make test newroot=1 t=" ?
  
Michael Jeanson July 6, 2026, 9:56 p.m. UTC | #14
On 2026-07-06 17:24, DJ Delorie wrote:
> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
>> On 03/07/26 12:36, DJ Delorie wrote:
>>> Michael Jeanson <mjeanson@efficios.com> writes:
>>>> The testroot.pristine is not created in the build dir
>>>
>>> $ make $PWD/testroot.pristine/install.stamp
>>
>> As a side note, should we add this as an implicit rule for 'make test ...'?
> 
> Please no ;-)
> 
> When I'm writing tests, I use "make test" a *lot* and rebuilding and
> reinstalling the whole testroot each time would be a huge waste.
> 
> Maybe some parameter to "make test" like "make test newroot=1 t=" ?

But once the stamp file exists it shouldn't recreate the testroot on 
each 'make test t=' invocation?
  
DJ Delorie July 6, 2026, 10:01 p.m. UTC | #15
Michael Jeanson <mjeanson@efficios.com> writes:
> But once the stamp file exists it shouldn't recreate the testroot on 
> each 'make test t=' invocation?

Ah, make once, yes.  That would help, although I don't know if there's
anything else that needs to be done "once" for a testsuite to work.

I would not want to rebuild the testroot each time you run one test.
  
Yury Khrustalev July 7, 2026, 8:37 a.m. UTC | #16
On Mon, Jul 06, 2026 at 06:01:33PM -0400, DJ Delorie wrote:
> Michael Jeanson <mjeanson@efficios.com> writes:
> > But once the stamp file exists it shouldn't recreate the testroot on 
> > each 'make test t=' invocation?
> 
> Ah, make once, yes.  That would help, although I don't know if there's
> anything else that needs to be done "once" for a testsuite to work.

Running

  make $(pwd)/testroot.pristine/install.stamp

Is enough for any 'make test t=...' in my experience. Moreover, I
suppose it's only required for the tests that are in 'tests-container'.

So, I agree with Adhemerval that this dependency might be useful.

Thanks,
Yury
  
Michael Jeanson July 7, 2026, 2:45 p.m. UTC | #17
On 2026-07-06 17:21, DJ Delorie wrote:
> Michael Jeanson <mjeanson@efficios.com> writes:
>> Also one more question, are system-wide tunables supposed to work with
>> statically linked executables? In my test environment I'm able to make
>> tst-rseq fail with a suitable /etc/tunables.conf but it seem to have no
>> impact on tst-rseq-static.
> 
> The current code is conditional on both SHARED and USE_LDCONFIG, as the
> data comes from /etc/ld.so.cache.
> 
> I don't remember exactly what the blocker here was, as we do support
> calling dlopen() from a static binary, and I assume that must load
> /etc/ld.so.cache.

That should probably be part of the user documentation, it seenms like 
an easy pitfall since the GLIBC_TUNABLE variable is not affected by the 
linking type of a binary.
  
Adhemerval Zanella Netto July 7, 2026, 3:15 p.m. UTC | #18
On 07/07/26 05:37, Yury Khrustalev wrote:
> On Mon, Jul 06, 2026 at 06:01:33PM -0400, DJ Delorie wrote:
>> Michael Jeanson <mjeanson@efficios.com> writes:
>>> But once the stamp file exists it shouldn't recreate the testroot on 
>>> each 'make test t=' invocation?
>>
>> Ah, make once, yes.  That would help, although I don't know if there's
>> anything else that needs to be done "once" for a testsuite to work.
> 
> Running
> 
>   make $(pwd)/testroot.pristine/install.stamp
> 
> Is enough for any 'make test t=...' in my experience. Moreover, I
> suppose it's only required for the tests that are in 'tests-container'.
> 
> So, I agree with Adhemerval that this dependency might be useful.
The 'make test t=...' will not work for test-containers without the container
installed anyway.  And the idea is to regenerate the contain iff some hard 
dependency requires rebuild, like libc.so (adding all installed files also 
does not make much sense). 

So 'make test t=...' where only the test is updated should not trigger a
new container installation.
  

Patch

diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
index 7d66340eae..5ad32abbe3 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
@@ -105,6 +105,15 @@  check_rseq_disabled (void)
     }
 }
 
+static void
+check_rseq_tunable_disabled (void)
+{
+  /* Check that the environment properly sets the rseq tunable to disabled and
+     that it's not overriden by a system-wide policy.  */
+  if (rseq_tunable ())
+    FAIL_UNSUPPORTED ("glibc.pthread.rseq tunable forced to enabled, skipping test");
+}
+
 static void *
 thread_func (void *ignored)
 {
@@ -128,6 +137,9 @@  do_test (void)
           getauxval (AT_RSEQ_FEATURE_SIZE));
   printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN));
 
+  puts ("info: checking rseq tunable state");
+  check_rseq_tunable_disabled ();
+
   puts ("info: checking main thread");
   check_rseq_disabled ();
 
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
index 02a5258afe..6031a99b7b 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
@@ -226,6 +226,8 @@  do_rseq_test (void)
   int t[] = { 1, 2, 6, 5, 4, 3, 50 };
   int i, result = 0;
 
+  if (!rseq_tunable ())
+    FAIL_UNSUPPORTED ("glibc.pthread.rseq tunable forced to disabled, skipping test");
   if (!rseq_available ())
     FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
   setup_signals ();
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
index ba93d390f4..a5c7c8aae6 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
@@ -110,6 +110,8 @@  proc_func (void *ignored)
 static int
 do_test (void)
 {
+  if (!rseq_tunable ())
+    FAIL_UNSUPPORTED ("glibc.pthread.rseq tunable forced to disabled, skipping test");
   if (!rseq_available ())
     {
       FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h
index 1efa4f30f1..fd5220e40e 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.h
+++ b/sysdeps/unix/sysv/linux/tst-rseq.h
@@ -24,6 +24,7 @@ 
 #include <sys/rseq.h>
 #include <tls.h>
 #include <rseq-internal.h>
+#include <elf/dl-tunables.h>
 
 static inline bool
 rseq_thread_registered (void)
@@ -56,3 +57,9 @@  rseq_available (void)
       FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno));
     }
 }
+
+static inline bool
+rseq_tunable (void)
+{
+  return TUNABLE_GET_FULL (glibc, pthread, rseq, int, NULL);
+}