Re: [patch 07/10] selftests/rseq: Validate legacy behavior

From: Dmitry Vyukov

Date: Wed Apr 29 2026 - 05:36:56 EST


On Wed, 29 Apr 2026 at 01:34, Thomas Gleixner <tglx@xxxxxxxxxx> wrote:
>
> The RSEQ legacy mode behavior requires that the ID fields in the rseq
> region are unconditionally updated on every context switch and before
> signal delivery even if not required by the ABI specification.
>
> To ensure that this behavior is preserved for legacy users in the future,
> add a test which validates that with a sleep() and a signal sent to self.
>
> Provide a run script which prevents GLIBC from registering a RSEQ region,
> so that the test can register it's own legacy sized region.
>
> Fixes: 566d8015f7ee ("rseq: Avoid CPU/MM CID updates when no event pending")
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx

Reviewed-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx>

> ---
> tools/testing/selftests/rseq/Makefile | 4 -
> tools/testing/selftests/rseq/legacy_check.c | 65 +++++++++++++++++++++++
> tools/testing/selftests/rseq/run_legacy_check.sh | 4 +
> 3 files changed, 71 insertions(+), 2 deletions(-)
>
> --- a/tools/testing/selftests/rseq/Makefile
> +++ b/tools/testing/selftests/rseq/Makefile
> @@ -17,11 +17,11 @@ OVERRIDE_TARGETS = 1
> TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_mm_cid_test param_test \
> param_test_benchmark param_test_compare_twice param_test_mm_cid \
> param_test_mm_cid_benchmark param_test_mm_cid_compare_twice \
> - syscall_errors_test slice_test
> + syscall_errors_test slice_test legacy_check
>
> TEST_GEN_PROGS_EXTENDED = librseq.so
>
> -TEST_PROGS = run_param_test.sh run_syscall_errors_test.sh
> +TEST_PROGS = run_param_test.sh run_syscall_errors_test.sh run_legacy_check.sh
>
> TEST_FILES := settings
>
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/legacy_check.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +
> +#include <errno.h>
> +#include <signal.h>
> +#include <stdint.h>
> +#include <unistd.h>
> +
> +#include "rseq.h"
> +
> +#include "../kselftest_harness.h"
> +
> +FIXTURE(legacy)
> +{
> +};
> +
> +static int cpu_id_in_sigfn = -1;
> +
> +static void sigfn(int sig)
> +{
> + struct rseq_abi *rs = rseq_get_abi();
> +
> + cpu_id_in_sigfn = rs->cpu_id_start;
> +}
> +
> +FIXTURE_SETUP(legacy)
> +{
> + int res = __rseq_register_current_thread(true, true);
> +
> + switch (res) {
> + case -ENOSYS:
> + SKIP(return, "RSEQ not enabled\n");
> + case -EBUSY:
> + SKIP(return, "GLIBC owns RSEQ. Disable GLIBC RSEQ registration\n");
> + default:
> + ASSERT_EQ(res, 0);
> + }
> +
> + ASSERT_NE(signal(SIGUSR1, sigfn), SIG_ERR);
> +}
> +
> +FIXTURE_TEARDOWN(legacy)
> +{
> +}
> +
> +TEST_F(legacy, legacy_test)
> +{
> + struct rseq_abi *rs = rseq_get_abi();
> +
> + ASSERT_NE(rs, NULL);
> +
> + /* Overwrite rs::cpu_id_start */
> + rs->cpu_id_start = -1;
> + sleep(1);
> + ASSERT_NE(rs->cpu_id_start, -1);
> +
> + rs->cpu_id_start = -1;
> + ASSERT_EQ(raise(SIGUSR1), 0);
> + ASSERT_NE(rs->cpu_id_start, -1);
> + ASSERT_NE(cpu_id_in_sigfn, -1);
> +}
> +
> +TEST_HARNESS_MAIN
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/run_legacy_check.sh
> @@ -0,0 +1,4 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0" ./legacy_check
>