This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.

For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
selftests/harness: order TEST_F and XFAIL_ADD constructors

This commit fixes a constructor ordering race where XFAIL_ADD() could run
before TEST_F() and read a NULL _##fixture_##test##_object pointer. The
fix uses constructor priorities to ensure TEST_F runs first.

> TEST_F() allocates and registers its struct __test_metadata via mmap()
> inside its constructor, and only then assigns the
> _##fixture_##test##_object pointer.
>
> XFAIL_ADD() runs in a constructor too and reads
> _##fixture_##test##_object to initialize xfail->test. If XFAIL_ADD runs
> first, xfail->test can be NULL and the expected failure will be reported
> as FAIL.
>
> Use constructor priorities to ensure TEST_F registration runs before
> XFAIL_ADD, without adding extra state or runtime lookups.
>
> Fixes: 2709473c9386 ("selftests: kselftest_harness: support using xfail")

Should the Fixes: tag point to commit 24cf65a62266 instead?

The existing tag points to 2709473c9386 ("selftests: kselftest_harness:
support using xfail"), but that commit used static initialization
(.test = &object) which had no race condition.

The race was actually introduced by commit 24cf65a62266
("selftests/harness: Share _metadata between forked processes"), which
changed TEST_F to use constructor-based allocation and also changed
XFAIL_ADD to read the pointer value in its constructor. This created the
race where XFAIL_ADD could run before TEST_F and read NULL.

> Signed-off-by: Sun Jian <[email protected]>

> diff --git a/tools/testing/selftests/kselftest_harness.h 
> b/tools/testing/selftests/kselftest_harness.h
> index 16a119a4656c..4afaef01c22e 100644
> --- a/tools/testing/selftests/kselftest_harness.h
> +++ b/tools/testing/selftests/kselftest_harness.h
> @@ -76,6 +76,9 @@ static inline void __kselftest_memset_safe(void *s, int c, 
> size_t n)
>               memset(s, c, n);
>  }
>
> +#define KSELFTEST_PRIO_TEST_F  20000
> +#define KSELFTEST_PRIO_XFAIL   20001
> +
>  #define TEST_TIMEOUT_DEFAULT 30
>
>  /* Utilities exposed to the test definitions */
> @@ -465,7 +468,7 @@ static inline void __kselftest_memset_safe(void *s, int 
> c, size_t n)
>                       fixture_name##_teardown(_metadata, self, variant); \
>       } \
>       static struct __test_metadata *_##fixture_name##_##test_name##_object; \
> -     static void __attribute__((constructor)) \
> +     static void __attribute__((constructor(KSELFTEST_PRIO_TEST_F))) \
>                       _register_##fixture_name##_##test_name(void) \
>       { \
>               struct __test_metadata *object = mmap(NULL, sizeof(*object), \
> @@ -880,7 +883,7 @@ struct __test_xfail {
>               .fixture = &_##fixture_name##_fixture_object, \
>               .variant = &_##fixture_name##_##variant_name##_object, \
>       }; \
> -     static void __attribute__((constructor)) \
> +     static void __attribute__((constructor(KSELFTEST_PRIO_XFAIL))) \
>               
> _register_##fixture_name##_##variant_name##_##test_name##_xfail(void) \
>       { \
>               _##fixture_name##_##variant_name##_##test_name##_xfail.test = \


Reply via email to