History

kcsan: Test support for compound instrumentation

Changes kcsan-test module to support checking reports that include compound instrumentation. Since we should not fail the test if this support is unavailable, we have to add a config variable that the test can use to decide what to check for.

Marco Elver committed 6 years ago

Commit bec4a241 parent 9d1335c2 files · +56 −14Browse files

Showing the changes to kernel (1 of 2 files). Show all

Unified · Split

kernel/kcsan/kcsan-test.c+51−14
@@ -27,6 +27,12 @@ · 26 unmodified lines
2727 #include <linux/types.h>
2828 #include <trace/events/printk.h>
2929
30+#ifdef CONFIG_CC_HAS_TSAN_COMPOUND_READ_BEFORE_WRITE
31+#define __KCSAN_ACCESS_RW(alt) (KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)
32+#else
33+#define __KCSAN_ACCESS_RW(alt) (alt)
34+#endif
35+
3036 /* Points to current test-case memory access "kernels". */
3137 static void (*access_kernels[2])(void);
3238
@@ -186,20 +192,21 @@ static bool report_matches(const struct expect_report *r) · 153 unmodified lines
186192
187193 /* Access 1 & 2 */
188194 for (i = 0; i < 2; ++i) {
195+ const int ty = r->access[i].type;
189196 const char *const access_type =
190− (r->access[i].type & KCSAN_ACCESS_ASSERT) ?
191− ((r->access[i].type & KCSAN_ACCESS_WRITE) ?
192− "assert no accesses" :
193− "assert no writes") :
194− ((r->access[i].type & KCSAN_ACCESS_WRITE) ?
195− "write" :
196− "read");
197+ (ty & KCSAN_ACCESS_ASSERT) ?
198+ ((ty & KCSAN_ACCESS_WRITE) ?
199+ "assert no accesses" :
200+ "assert no writes") :
201+ ((ty & KCSAN_ACCESS_WRITE) ?
202+ ((ty & KCSAN_ACCESS_COMPOUND) ?
203+ "read-write" :
204+ "write") :
205+ "read");
197206 const char *const access_type_aux =
198− (r->access[i].type & KCSAN_ACCESS_ATOMIC) ?
199− " (marked)" :
200− ((r->access[i].type & KCSAN_ACCESS_SCOPED) ?
201− " (scoped)" :
202− "");
207+ (ty & KCSAN_ACCESS_ATOMIC) ?
208+ " (marked)" :
209+ ((ty & KCSAN_ACCESS_SCOPED) ? " (scoped)" : "");
203210
204211 if (i == 1) {
205212 /* Access 2 */
@@ -277,6 +284,12 @@ static noinline void test_kernel_write_atomic(void) · 71 unmodified lines
277284 WRITE_ONCE(test_var, READ_ONCE_NOCHECK(test_sink) + 1);
278285 }
279286
287+static noinline void test_kernel_atomic_rmw(void)
288+{
289+ /* Use builtin, so we can set up the "bad" atomic/non-atomic scenario. */
290+ __atomic_fetch_add(&test_var, 1, __ATOMIC_RELAXED);
291+}
292+
280293 __no_kcsan
281294 static noinline void test_kernel_write_uninstrumented(void) { test_var++; }
282295
@@ -439,8 +452,8 @@ static void test_concurrent_races(struct kunit *test) · 156 unmodified lines
439452 const struct expect_report expect = {
440453 .access = {
441454 /* NULL will match any address. */
442− { test_kernel_rmw_array, NULL, 0, KCSAN_ACCESS_WRITE },
443− { test_kernel_rmw_array, NULL, 0, 0 },
455+ { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) },
456+ { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(0) },
444457 },
445458 };
446459 static const struct expect_report never = {
@@ -629,6 +642,29 @@ static void test_read_plain_atomic_write(struct kunit *test) · 182 unmodified lines
629642 KUNIT_EXPECT_TRUE(test, match_expect);
630643 }
631644
645+/* Test that atomic RMWs generate correct report. */
646+__no_kcsan
647+static void test_read_plain_atomic_rmw(struct kunit *test)
648+{
649+ const struct expect_report expect = {
650+ .access = {
651+ { test_kernel_read, &test_var, sizeof(test_var), 0 },
652+ { test_kernel_atomic_rmw, &test_var, sizeof(test_var),
653+ KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ATOMIC },
654+ },
655+ };
656+ bool match_expect = false;
657+
658+ if (IS_ENABLED(CONFIG_KCSAN_IGNORE_ATOMICS))
659+ return;
660+
661+ begin_test_checks(test_kernel_read, test_kernel_atomic_rmw);
662+ do {
663+ match_expect = report_matches(&expect);
664+ } while (!end_test_checks(match_expect));
665+ KUNIT_EXPECT_TRUE(test, match_expect);
666+}
667+
632668 /* Zero-sized accesses should never cause data race reports. */
633669 __no_kcsan
634670 static void test_zero_size_access(struct kunit *test)
@@ -942,6 +978,7 @@ static struct kunit_case kcsan_test_cases[] = { · 307 unmodified lines
942978 KCSAN_KUNIT_CASE(test_write_write_struct_part),
943979 KCSAN_KUNIT_CASE(test_read_atomic_write_atomic),
944980 KCSAN_KUNIT_CASE(test_read_plain_atomic_write),
981+ KCSAN_KUNIT_CASE(test_read_plain_atomic_rmw),
945982 KCSAN_KUNIT_CASE(test_zero_size_access),
946983 KCSAN_KUNIT_CASE(test_data_race),
947984 KCSAN_KUNIT_CASE(test_assert_exclusive_writer),

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t