From: huhai <
hu...@kylinos.cn>
kunit_filter_glob_tests() returns NULL if a suite matches the suite glob
but none of its tests match the test glob. If an attribute filter is also
specified, kunit_filter_suites() passes this NULL pointer to
kunit_filter_attr_tests(), which eventually dereferences it in kmemdup().
This causes a kernel panic with, for example:
kunit.filter_glob=kunit_executor_test.not_found
kunit.filter="speed>slow"
Pid: 1, comm: swapper/0 Not tainted 7.2.0
RIP: 0033:memcpy_orig+0x1a/0x115
RSP: 00000000a0803df8 EFLAGS: 00010202
RAX: 0000000060b3f800 RBX: 0000000000000250 RCX: 0000000060b3f800
RDX: 0000000000000210 RSI: 0000000000000000 RDI: 0000000060b3f800
RBP: 0000000000000000 R08: 00000000a0803f4c R09: 000000000000006e
R10: 0000000060812a11 R11: 747365745f726f01 R12: 00000000a0803f4c
R13: 0000000000000000 R14: 0000000060812a00 R15: 0000000000000001
Kernel panic - not syncing: Segfault with no mm
CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.2.0 #3 VOLUNTARY
Stack:
60107348 608013c0 60490e60 6027d5b0
6026d06a 9f1ffe43 6026cf68 00000000
3e00000000000001 a0803ee8 a0803f4c 6026a6d1
Call Trace:
[<60107348>] ? kmemdup_noprof+0x48/0x60
[<6027d5b0>] ? glob_match+0x0/0x20
[<6026d06a>] ? kunit_filter_attr_tests+0x3a/0x2a0
[<6026cf68>] ? kunit_next_attr_filter+0xb8/0x180
[<6026a6d1>] ? kunit_filter_suites+0xf1/0x6e0
[<6027d5b0>] ? glob_match+0x0/0x20
[<6026aab7>] ? kunit_filter_suites+0x4d7/0x6e0
[<6026c5f1>] ? kunit_run_all_tests+0xc1/0x330
[<6000211b>] ? do_one_initcall+0x0/0x203
[<60002675>] ? kernel_init_freeable+0x2e2/0x365
[<603359b5>] ? kernel_init+0x33/0x19e
[<60043435>] ? new_thread_handler+0x45/0x60
Check for a NULL result after glob filtering and skip the suite instead of
passing it to the attribute filters. Add a test for this case.
Fixes: 529534e8cba3 ("kunit: Add ability to filter attributes")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: huhai <
hu...@kylinos.cn>
---
lib/kunit/executor.c | 2 ++
lib/kunit/executor_test.c | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
index b0f8a41d61d3..8bc2d35078fe 100644
--- a/lib/kunit/executor.c
+++ b/lib/kunit/executor.c
@@ -226,6 +226,8 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
*err = PTR_ERR(filtered_suite);
goto free_filtered_suite;
}
+ if (!filtered_suite)
+ continue;
}
if (filter_count > 0 && parsed_filters != NULL) {
for (k = 0; k < filter_count; k++) {
diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c
index 4cb119ad8f64..0b8ca3df953e 100644
--- a/lib/kunit/executor_test.c
+++ b/lib/kunit/executor_test.c
@@ -115,6 +115,27 @@ static void filter_suites_to_empty_test(struct kunit *test)
"should be empty to indicate no match");
}
+static void filter_suites_glob_and_attr_to_empty_test(struct kunit *test)
+{
+ struct kunit_suite *subsuite[2] = {NULL};
+ struct kunit_suite_set suite_set = {
+ .start = subsuite, .end = &subsuite[1],
+ };
+ struct kunit_suite_set got;
+ char filter[] = "speed>slow";
+ int err = 0;
+
+ subsuite[0] = alloc_fake_suite(test, "suite", dummy_test_cases);
+
+ got = kunit_filter_suites(&suite_set, "suite.not_found", filter, NULL,
+ &err);
+ KUNIT_ASSERT_EQ(test, err, 0);
+ free_suite_set_at_end(test, &got);
+
+ KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end,
+ "should be empty to indicate no match");
+}
+
static void parse_filter_attr_test(struct kunit *test)
{
int j, filter_count;
@@ -240,6 +261,7 @@ static struct kunit_case executor_test_cases[] = {
KUNIT_CASE(filter_suites_test),
KUNIT_CASE(filter_suites_test_glob_test),
KUNIT_CASE(filter_suites_to_empty_test),
+ KUNIT_CASE(filter_suites_glob_and_attr_to_empty_test),
KUNIT_CASE(parse_filter_attr_test),
KUNIT_CASE(filter_attr_test),
KUNIT_CASE(filter_attr_empty_test),
--
2.40.1