Commit fb52c87a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-kselftest-kunit-6.6-rc2' of...

Merge tag 'linux-kselftest-kunit-6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kunit fixes from Shuah Khan:
 "Fixes to possible memory leak, null-ptr-deref, wild-memory-access, and
  error path bugs"

* tag 'linux-kselftest-kunit-6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  kunit: Fix possible memory leak in kunit_filter_suites()
  kunit: Fix possible null-ptr-deref in kunit_parse_glob_filter()
  kunit: Fix the wrong err path and add goto labels in kunit_filter_suites()
  kunit: Fix wild-memory-access bug in kunit_free_suite_set()
  kunit: test: Make filter strings in executor_test writable
parents afe03f08 9076bc47
...@@ -65,7 +65,7 @@ struct kunit_glob_filter { ...@@ -65,7 +65,7 @@ struct kunit_glob_filter {
}; };
/* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */ /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */
static void kunit_parse_glob_filter(struct kunit_glob_filter *parsed, static int kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
const char *filter_glob) const char *filter_glob)
{ {
const int len = strlen(filter_glob); const int len = strlen(filter_glob);
...@@ -73,16 +73,28 @@ static void kunit_parse_glob_filter(struct kunit_glob_filter *parsed, ...@@ -73,16 +73,28 @@ static void kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
if (!period) { if (!period) {
parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL); parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL);
if (!parsed->suite_glob)
return -ENOMEM;
parsed->test_glob = NULL; parsed->test_glob = NULL;
strcpy(parsed->suite_glob, filter_glob); strcpy(parsed->suite_glob, filter_glob);
return; return 0;
} }
parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL); parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL);
if (!parsed->suite_glob)
return -ENOMEM;
parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL); parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL);
if (!parsed->test_glob) {
kfree(parsed->suite_glob);
return -ENOMEM;
}
strncpy(parsed->suite_glob, filter_glob, period - filter_glob); strncpy(parsed->suite_glob, filter_glob, period - filter_glob);
strncpy(parsed->test_glob, period + 1, len - (period - filter_glob)); strncpy(parsed->test_glob, period + 1, len - (period - filter_glob));
return 0;
} }
/* Create a copy of suite with only tests that match test_glob. */ /* Create a copy of suite with only tests that match test_glob. */
...@@ -152,21 +164,24 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, ...@@ -152,21 +164,24 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
} }
copy_start = copy; copy_start = copy;
if (filter_glob) if (filter_glob) {
kunit_parse_glob_filter(&parsed_glob, filter_glob); *err = kunit_parse_glob_filter(&parsed_glob, filter_glob);
if (*err)
goto free_copy;
}
/* Parse attribute filters */ /* Parse attribute filters */
if (filters) { if (filters) {
filter_count = kunit_get_filter_count(filters); filter_count = kunit_get_filter_count(filters);
parsed_filters = kcalloc(filter_count, sizeof(*parsed_filters), GFP_KERNEL); parsed_filters = kcalloc(filter_count, sizeof(*parsed_filters), GFP_KERNEL);
if (!parsed_filters) { if (!parsed_filters) {
kfree(copy); *err = -ENOMEM;
return filtered; goto free_parsed_glob;
} }
for (j = 0; j < filter_count; j++) for (j = 0; j < filter_count; j++)
parsed_filters[j] = kunit_next_attr_filter(&filters, err); parsed_filters[j] = kunit_next_attr_filter(&filters, err);
if (*err) if (*err)
goto err; goto free_parsed_filters;
} }
for (i = 0; &suite_set->start[i] != suite_set->end; i++) { for (i = 0; &suite_set->start[i] != suite_set->end; i++) {
...@@ -178,7 +193,7 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, ...@@ -178,7 +193,7 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
parsed_glob.test_glob); parsed_glob.test_glob);
if (IS_ERR(filtered_suite)) { if (IS_ERR(filtered_suite)) {
*err = PTR_ERR(filtered_suite); *err = PTR_ERR(filtered_suite);
goto err; goto free_parsed_filters;
} }
} }
if (filter_count > 0 && parsed_filters != NULL) { if (filter_count > 0 && parsed_filters != NULL) {
...@@ -195,10 +210,11 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, ...@@ -195,10 +210,11 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
filtered_suite = new_filtered_suite; filtered_suite = new_filtered_suite;
if (*err) if (*err)
goto err; goto free_parsed_filters;
if (IS_ERR(filtered_suite)) { if (IS_ERR(filtered_suite)) {
*err = PTR_ERR(filtered_suite); *err = PTR_ERR(filtered_suite);
goto err; goto free_parsed_filters;
} }
if (!filtered_suite) if (!filtered_suite)
break; break;
...@@ -213,17 +229,19 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, ...@@ -213,17 +229,19 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
filtered.start = copy_start; filtered.start = copy_start;
filtered.end = copy; filtered.end = copy;
err: free_parsed_filters:
if (*err) if (filter_count)
kfree(copy); kfree(parsed_filters);
free_parsed_glob:
if (filter_glob) { if (filter_glob) {
kfree(parsed_glob.suite_glob); kfree(parsed_glob.suite_glob);
kfree(parsed_glob.test_glob); kfree(parsed_glob.test_glob);
} }
if (filter_count) free_copy:
kfree(parsed_filters); if (*err)
kfree(copy);
return filtered; return filtered;
} }
......
...@@ -119,7 +119,7 @@ static void parse_filter_attr_test(struct kunit *test) ...@@ -119,7 +119,7 @@ static void parse_filter_attr_test(struct kunit *test)
{ {
int j, filter_count; int j, filter_count;
struct kunit_attr_filter *parsed_filters; struct kunit_attr_filter *parsed_filters;
char *filters = "speed>slow, module!=example"; char filters[] = "speed>slow, module!=example", *filter = filters;
int err = 0; int err = 0;
filter_count = kunit_get_filter_count(filters); filter_count = kunit_get_filter_count(filters);
...@@ -128,7 +128,7 @@ static void parse_filter_attr_test(struct kunit *test) ...@@ -128,7 +128,7 @@ static void parse_filter_attr_test(struct kunit *test)
parsed_filters = kunit_kcalloc(test, filter_count, sizeof(*parsed_filters), parsed_filters = kunit_kcalloc(test, filter_count, sizeof(*parsed_filters),
GFP_KERNEL); GFP_KERNEL);
for (j = 0; j < filter_count; j++) { for (j = 0; j < filter_count; j++) {
parsed_filters[j] = kunit_next_attr_filter(&filters, &err); parsed_filters[j] = kunit_next_attr_filter(&filter, &err);
KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter '%s'", filters[j]); KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter '%s'", filters[j]);
} }
...@@ -154,6 +154,7 @@ static void filter_attr_test(struct kunit *test) ...@@ -154,6 +154,7 @@ static void filter_attr_test(struct kunit *test)
.start = subsuite, .end = &subsuite[2], .start = subsuite, .end = &subsuite[2],
}; };
struct kunit_suite_set got; struct kunit_suite_set got;
char filter[] = "speed>slow";
int err = 0; int err = 0;
subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases); subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases);
...@@ -168,7 +169,7 @@ static void filter_attr_test(struct kunit *test) ...@@ -168,7 +169,7 @@ static void filter_attr_test(struct kunit *test)
* attribute is unset and thus, the filtering is based on the parent attribute * attribute is unset and thus, the filtering is based on the parent attribute
* of slow. * of slow.
*/ */
got = kunit_filter_suites(&suite_set, NULL, "speed>slow", NULL, &err); got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
KUNIT_ASSERT_EQ(test, err, 0); KUNIT_ASSERT_EQ(test, err, 0);
kfree_at_end(test, got.start); kfree_at_end(test, got.start);
...@@ -191,12 +192,13 @@ static void filter_attr_empty_test(struct kunit *test) ...@@ -191,12 +192,13 @@ static void filter_attr_empty_test(struct kunit *test)
.start = subsuite, .end = &subsuite[2], .start = subsuite, .end = &subsuite[2],
}; };
struct kunit_suite_set got; struct kunit_suite_set got;
char filter[] = "module!=dummy";
int err = 0; int err = 0;
subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases); subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases);
subsuite[1] = alloc_fake_suite(test, "suite2", dummy_attr_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_attr_test_cases);
got = kunit_filter_suites(&suite_set, NULL, "module!=dummy", NULL, &err); got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
KUNIT_ASSERT_EQ(test, err, 0); KUNIT_ASSERT_EQ(test, err, 0);
kfree_at_end(test, got.start); /* just in case */ kfree_at_end(test, got.start); /* just in case */
...@@ -211,12 +213,13 @@ static void filter_attr_skip_test(struct kunit *test) ...@@ -211,12 +213,13 @@ static void filter_attr_skip_test(struct kunit *test)
.start = subsuite, .end = &subsuite[1], .start = subsuite, .end = &subsuite[1],
}; };
struct kunit_suite_set got; struct kunit_suite_set got;
char filter[] = "speed>slow";
int err = 0; int err = 0;
subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases); subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases);
/* Want: suite(slow, normal), NULL -> suite(slow with SKIP, normal), NULL */ /* Want: suite(slow, normal), NULL -> suite(slow with SKIP, normal), NULL */
got = kunit_filter_suites(&suite_set, NULL, "speed>slow", "skip", &err); got = kunit_filter_suites(&suite_set, NULL, filter, "skip", &err);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
KUNIT_ASSERT_EQ(test, err, 0); KUNIT_ASSERT_EQ(test, err, 0);
kfree_at_end(test, got.start); kfree_at_end(test, got.start);
......
...@@ -784,12 +784,13 @@ static int kunit_module_notify(struct notifier_block *nb, unsigned long val, ...@@ -784,12 +784,13 @@ static int kunit_module_notify(struct notifier_block *nb, unsigned long val,
switch (val) { switch (val) {
case MODULE_STATE_LIVE: case MODULE_STATE_LIVE:
kunit_module_init(mod);
break; break;
case MODULE_STATE_GOING: case MODULE_STATE_GOING:
kunit_module_exit(mod); kunit_module_exit(mod);
break; break;
case MODULE_STATE_COMING: case MODULE_STATE_COMING:
kunit_module_init(mod);
break;
case MODULE_STATE_UNFORMED: case MODULE_STATE_UNFORMED:
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment