Skip to content

Commit 8040345

Browse files
Jinjie Ruanshuahkh
authored andcommitted
kunit: test: Fix the possible memory leak in executor_test
When CONFIG_KUNIT_ALL_TESTS=y, making CONFIG_DEBUG_KMEMLEAK=y and CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y, the below memory leak is detected. If kunit_filter_suites() succeeds, not only copy but also filtered_suite and filtered_suite->test_cases should be freed. So as Rae suggested, to avoid the suite set never be freed when KUNIT_ASSERT_EQ() fails and exits after kunit_filter_suites() succeeds, update kfree_at_end() func to free_suite_set_at_end() to use kunit_free_suite_set() to free them as kunit_module_exit() and kunit_run_all_tests() do it. As the second arg got of free_suite_set_at_end() is a local variable, copy it for free to avoid wild-memory-access. After applying this patch, the following memory leak is never detected. unreferenced object 0xffff8881001de400 (size 1024): comm "kunit_try_catch", pid 1396, jiffies 4294720452 (age 932.801s) hex dump (first 32 bytes): 73 75 69 74 65 32 00 00 00 00 00 00 00 00 00 00 suite2.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817db753>] __kmalloc_node_track_caller+0x53/0x150 [<ffffffff817bd242>] kmemdup+0x22/0x50 [<ffffffff829e961d>] kunit_filter_suites+0x44d/0xcc0 [<ffffffff829eb69f>] filter_suites_test+0x12f/0x360 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff8881052cd388 (size 192): comm "kunit_try_catch", pid 1396, jiffies 4294720452 (age 932.801s) hex dump (first 32 bytes): a0 85 9e 82 ff ff ff ff 80 cd 7c 84 ff ff ff ff ..........|..... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817dbad2>] __kmalloc+0x52/0x150 [<ffffffff829e9651>] kunit_filter_suites+0x481/0xcc0 [<ffffffff829eb69f>] filter_suites_test+0x12f/0x360 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff888100da8400 (size 1024): comm "kunit_try_catch", pid 1398, jiffies 4294720454 (age 781.945s) hex dump (first 32 bytes): 73 75 69 74 65 32 00 00 00 00 00 00 00 00 00 00 suite2.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817db753>] __kmalloc_node_track_caller+0x53/0x150 [<ffffffff817bd242>] kmemdup+0x22/0x50 [<ffffffff829e961d>] kunit_filter_suites+0x44d/0xcc0 [<ffffffff829eb13f>] filter_suites_test_glob_test+0x12f/0x560 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff888105117878 (size 96): comm "kunit_try_catch", pid 1398, jiffies 4294720454 (age 781.945s) hex dump (first 32 bytes): a0 85 9e 82 ff ff ff ff a0 ac 7c 84 ff ff ff ff ..........|..... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817dbad2>] __kmalloc+0x52/0x150 [<ffffffff829e9651>] kunit_filter_suites+0x481/0xcc0 [<ffffffff829eb13f>] filter_suites_test_glob_test+0x12f/0x560 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff888102c31c00 (size 1024): comm "kunit_try_catch", pid 1404, jiffies 4294720460 (age 781.948s) hex dump (first 32 bytes): 6e 6f 72 6d 61 6c 5f 73 75 69 74 65 00 00 00 00 normal_suite.... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817db753>] __kmalloc_node_track_caller+0x53/0x150 [<ffffffff817bd242>] kmemdup+0x22/0x50 [<ffffffff829ecf17>] kunit_filter_attr_tests+0xf7/0x860 [<ffffffff829e99ff>] kunit_filter_suites+0x82f/0xcc0 [<ffffffff829ea975>] filter_attr_test+0x195/0x5f0 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff8881052cd250 (size 192): comm "kunit_try_catch", pid 1404, jiffies 4294720460 (age 781.948s) hex dump (first 32 bytes): a0 85 9e 82 ff ff ff ff 00 a9 7c 84 ff ff ff ff ..........|..... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817dbad2>] __kmalloc+0x52/0x150 [<ffffffff829ecfc1>] kunit_filter_attr_tests+0x1a1/0x860 [<ffffffff829e99ff>] kunit_filter_suites+0x82f/0xcc0 [<ffffffff829ea975>] filter_attr_test+0x195/0x5f0 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff888104f4e400 (size 1024): comm "kunit_try_catch", pid 1408, jiffies 4294720464 (age 781.944s) hex dump (first 32 bytes): 73 75 69 74 65 00 00 00 00 00 00 00 00 00 00 00 suite........... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff817db753>] __kmalloc_node_track_caller+0x53/0x150 [<ffffffff817bd242>] kmemdup+0x22/0x50 [<ffffffff829ecf17>] kunit_filter_attr_tests+0xf7/0x860 [<ffffffff829e99ff>] kunit_filter_suites+0x82f/0xcc0 [<ffffffff829e9fc3>] filter_attr_skip_test+0x133/0x6e0 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 unreferenced object 0xffff8881052cc620 (size 192): comm "kunit_try_catch", pid 1408, jiffies 4294720464 (age 781.944s) hex dump (first 32 bytes): a0 85 9e 82 ff ff ff ff c0 a8 7c 84 ff ff ff ff ..........|..... 00 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 ................ backtrace: [<ffffffff817dbad2>] __kmalloc+0x52/0x150 [<ffffffff829ecfc1>] kunit_filter_attr_tests+0x1a1/0x860 [<ffffffff829e99ff>] kunit_filter_suites+0x82f/0xcc0 [<ffffffff829e9fc3>] filter_attr_skip_test+0x133/0x6e0 [<ffffffff829e802a>] kunit_generic_run_threadfn_adapter+0x4a/0x90 [<ffffffff81236fc6>] kthread+0x2b6/0x380 [<ffffffff81096afd>] ret_from_fork+0x2d/0x70 [<ffffffff81003511>] ret_from_fork_asm+0x11/0x20 Fixes: e5857d3 ("kunit: flatten kunit_suite*** to kunit_suite** in .kunit_test_suites") Fixes: 76066f9 ("kunit: add tests for filtering attributes") Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> Suggested-by: Rae Moar <rmoar@google.com> Reviewed-by: David Gow <davidgow@google.com> Suggested-by: David Gow <davidgow@google.com> Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202309142251.uJ8saAZv-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202309270433.wGmFRGjd-lkp@intel.com/ Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
1 parent 24de14c commit 8040345

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

lib/kunit/executor_test.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <kunit/test.h>
1010
#include <kunit/attributes.h>
1111

12-
static void kfree_at_end(struct kunit *test, const void *to_free);
12+
static void free_suite_set_at_end(struct kunit *test, const void *to_free);
1313
static struct kunit_suite *alloc_fake_suite(struct kunit *test,
1414
const char *suite_name,
1515
struct kunit_case *test_cases);
@@ -56,7 +56,7 @@ static void filter_suites_test(struct kunit *test)
5656
got = kunit_filter_suites(&suite_set, "suite2", NULL, NULL, &err);
5757
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
5858
KUNIT_ASSERT_EQ(test, err, 0);
59-
kfree_at_end(test, got.start);
59+
free_suite_set_at_end(test, &got);
6060

6161
/* Validate we just have suite2 */
6262
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
@@ -82,7 +82,7 @@ static void filter_suites_test_glob_test(struct kunit *test)
8282
got = kunit_filter_suites(&suite_set, "suite2.test2", NULL, NULL, &err);
8383
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
8484
KUNIT_ASSERT_EQ(test, err, 0);
85-
kfree_at_end(test, got.start);
85+
free_suite_set_at_end(test, &got);
8686

8787
/* Validate we just have suite2 */
8888
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
@@ -109,7 +109,7 @@ static void filter_suites_to_empty_test(struct kunit *test)
109109

110110
got = kunit_filter_suites(&suite_set, "not_found", NULL, NULL, &err);
111111
KUNIT_ASSERT_EQ(test, err, 0);
112-
kfree_at_end(test, got.start); /* just in case */
112+
free_suite_set_at_end(test, &got); /* just in case */
113113

114114
KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end,
115115
"should be empty to indicate no match");
@@ -172,7 +172,7 @@ static void filter_attr_test(struct kunit *test)
172172
got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
173173
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
174174
KUNIT_ASSERT_EQ(test, err, 0);
175-
kfree_at_end(test, got.start);
175+
free_suite_set_at_end(test, &got);
176176

177177
/* Validate we just have normal_suite */
178178
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]);
@@ -200,7 +200,7 @@ static void filter_attr_empty_test(struct kunit *test)
200200

201201
got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
202202
KUNIT_ASSERT_EQ(test, err, 0);
203-
kfree_at_end(test, got.start); /* just in case */
203+
free_suite_set_at_end(test, &got); /* just in case */
204204

205205
KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end,
206206
"should be empty to indicate no match");
@@ -222,7 +222,7 @@ static void filter_attr_skip_test(struct kunit *test)
222222
got = kunit_filter_suites(&suite_set, NULL, filter, "skip", &err);
223223
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
224224
KUNIT_ASSERT_EQ(test, err, 0);
225-
kfree_at_end(test, got.start);
225+
free_suite_set_at_end(test, &got);
226226

227227
/* Validate we have both the slow and normal test */
228228
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases);
@@ -256,18 +256,26 @@ kunit_test_suites(&executor_test_suite);
256256

257257
/* Test helpers */
258258

259-
/* Use the resource API to register a call to kfree(to_free).
259+
static void free_suite_set(void *suite_set)
260+
{
261+
kunit_free_suite_set(*(struct kunit_suite_set *)suite_set);
262+
kfree(suite_set);
263+
}
264+
265+
/* Use the resource API to register a call to free_suite_set.
260266
* Since we never actually use the resource, it's safe to use on const data.
261267
*/
262-
static void kfree_at_end(struct kunit *test, const void *to_free)
268+
static void free_suite_set_at_end(struct kunit *test, const void *to_free)
263269
{
264-
/* kfree() handles NULL already, but avoid allocating a no-op cleanup. */
265-
if (IS_ERR_OR_NULL(to_free))
270+
struct kunit_suite_set *free;
271+
272+
if (!((struct kunit_suite_set *)to_free)->start)
266273
return;
267274

268-
kunit_add_action(test,
269-
(kunit_action_t *)kfree,
270-
(void *)to_free);
275+
free = kzalloc(sizeof(struct kunit_suite_set), GFP_KERNEL);
276+
*free = *(struct kunit_suite_set *)to_free;
277+
278+
kunit_add_action(test, free_suite_set, (void *)free);
271279
}
272280

273281
static struct kunit_suite *alloc_fake_suite(struct kunit *test,

0 commit comments

Comments
 (0)