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

Unified · Split

2 files
  1. kernel/kcsan/kcsan-test.c +51 −14
  2. lib/Kconfig.kcsan +5 −0
kernel/kcsan/kcsan-test.c+51−14
@@ -27,6 +27,12 @@ · 26 unmodified lines
27#include <linux/types.h>27#include <linux/types.h>
28#include <trace/events/printk.h>28#include <trace/events/printk.h>
29 29
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
30/* Points to current test-case memory access "kernels". */36/* Points to current test-case memory access "kernels". */
31static void (*access_kernels[2])(void);37static void (*access_kernels[2])(void);
32 38
@@ -186,20 +192,21 @@ static bool report_matches(const struct expect_report *r) · 153 unmodified lines
186 192
187 /* Access 1 & 2 */193 /* Access 1 & 2 */
188 for (i = 0; i < 2; ++i) {194 for (i = 0; i < 2; ++i) {
195 const int ty = r->access[i].type;
189 const char *const access_type =196 const char *const access_type =
190 (r->access[i].type & KCSAN_ACCESS_ASSERT) ?197 (ty & KCSAN_ACCESS_ASSERT) ?
191 ((r->access[i].type & KCSAN_ACCESS_WRITE) ?198 ((ty & KCSAN_ACCESS_WRITE) ?
192 "assert no accesses" :199 "assert no accesses" :
193 "assert no writes") :200 "assert no writes") :
194 ((r->access[i].type & KCSAN_ACCESS_WRITE) ?201 ((ty & KCSAN_ACCESS_WRITE) ?
195 "write" :202 ((ty & KCSAN_ACCESS_COMPOUND) ?
196 "read");203 "read-write" :
204 "write") :
205 "read");
197 const char *const access_type_aux =206 const char *const access_type_aux =
198 (r->access[i].type & KCSAN_ACCESS_ATOMIC) ?207 (ty & KCSAN_ACCESS_ATOMIC) ?
199 " (marked)" :208 " (marked)" :
200 ((r->access[i].type & KCSAN_ACCESS_SCOPED) ?209 ((ty & KCSAN_ACCESS_SCOPED) ? " (scoped)" : "");
201 " (scoped)" :
202 "");
203 210
204 if (i == 1) {211 if (i == 1) {
205 /* Access 2 */212 /* Access 2 */
@@ -277,6 +284,12 @@ static noinline void test_kernel_write_atomic(void) · 71 unmodified lines
277 WRITE_ONCE(test_var, READ_ONCE_NOCHECK(test_sink) + 1);284 WRITE_ONCE(test_var, READ_ONCE_NOCHECK(test_sink) + 1);
278}285}
279 286
287static 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
280__no_kcsan293__no_kcsan
281static noinline void test_kernel_write_uninstrumented(void) { test_var++; }294static noinline void test_kernel_write_uninstrumented(void) { test_var++; }
282 295
@@ -439,8 +452,8 @@ static void test_concurrent_races(struct kunit *test) · 156 unmodified lines
439 const struct expect_report expect = {452 const struct expect_report expect = {
440 .access = {453 .access = {
441 /* NULL will match any address. */454 /* NULL will match any address. */
442 { test_kernel_rmw_array, NULL, 0, KCSAN_ACCESS_WRITE },455 { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) },
443 { test_kernel_rmw_array, NULL, 0, 0 },456 { test_kernel_rmw_array, NULL, 0, __KCSAN_ACCESS_RW(0) },
444 },457 },
445 };458 };
446 static const struct expect_report never = {459 static const struct expect_report never = {
@@ -629,6 +642,29 @@ static void test_read_plain_atomic_write(struct kunit *test) · 182 unmodified lines
629 KUNIT_EXPECT_TRUE(test, match_expect);642 KUNIT_EXPECT_TRUE(test, match_expect);
630}643}
631 644
645/* Test that atomic RMWs generate correct report. */
646__no_kcsan
647static 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
632/* Zero-sized accesses should never cause data race reports. */668/* Zero-sized accesses should never cause data race reports. */
633__no_kcsan669__no_kcsan
634static void test_zero_size_access(struct kunit *test)670static void test_zero_size_access(struct kunit *test)
@@ -942,6 +978,7 @@ static struct kunit_case kcsan_test_cases[] = { · 307 unmodified lines
942 KCSAN_KUNIT_CASE(test_write_write_struct_part),978 KCSAN_KUNIT_CASE(test_write_write_struct_part),
943 KCSAN_KUNIT_CASE(test_read_atomic_write_atomic),979 KCSAN_KUNIT_CASE(test_read_atomic_write_atomic),
944 KCSAN_KUNIT_CASE(test_read_plain_atomic_write),980 KCSAN_KUNIT_CASE(test_read_plain_atomic_write),
981 KCSAN_KUNIT_CASE(test_read_plain_atomic_rmw),
945 KCSAN_KUNIT_CASE(test_zero_size_access),982 KCSAN_KUNIT_CASE(test_zero_size_access),
946 KCSAN_KUNIT_CASE(test_data_race),983 KCSAN_KUNIT_CASE(test_data_race),
947 KCSAN_KUNIT_CASE(test_assert_exclusive_writer),984 KCSAN_KUNIT_CASE(test_assert_exclusive_writer),
lib/Kconfig.kcsan+5−0
@@ -40,6 +40,11 @@ menuconfig KCSAN · 39 unmodified lines
40 40
41if KCSAN41if KCSAN
42 42
43# Compiler capabilities that should not fail the test if they are unavailable.
44config CC_HAS_TSAN_COMPOUND_READ_BEFORE_WRITE
45 def_bool (CC_IS_CLANG && $(cc-option,-fsanitize=thread -mllvm -tsan-compound-read-before-write=1)) || \
46 (CC_IS_GCC && $(cc-option,-fsanitize=thread --param tsan-compound-read-before-write=1))
47
43config KCSAN_VERBOSE48config KCSAN_VERBOSE
44 bool "Show verbose reports with more information about system state"49 bool "Show verbose reports with more information about system state"
45 depends on PROVE_LOCKING50 depends on PROVE_LOCKING

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