Pull KCSAN updates from Paul E. McKenney: - improve comments - introduce CONFIG_KCSAN_STRICT (which RCU uses) - optimize use of get_ctx() by kcsan_found_watchpoint() - rework atomic.h into permissive.h - add the ability to ignore writes that change only one bit of a given data-racy variable.
Unified · Split
| @@ -127,6 +127,18 @@ Kconfig options: · 126 unmodified lines | ||
| 127 | 127 | causes KCSAN to not report data races due to conflicts where the only plain |
| 128 | 128 | accesses are aligned writes up to word size. |
| 129 | 129 | |
| 130 | +* ``CONFIG_KCSAN_PERMISSIVE``: Enable additional permissive rules to ignore | |
| 131 | + certain classes of common data races. Unlike the above, the rules are more | |
| 132 | + complex involving value-change patterns, access type, and address. This | |
| 133 | + option depends on ``CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=y``. For details | |
| 134 | + please see the ``kernel/kcsan/permissive.h``. Testers and maintainers that | |
| 135 | + only focus on reports from specific subsystems and not the whole kernel are | |
| 136 | + recommended to disable this option. | |
| 137 | + | |
| 138 | +To use the strictest possible rules, select ``CONFIG_KCSAN_STRICT=y``, which | |
| 139 | +configures KCSAN to follow the Linux-kernel memory consistency model (LKMM) as | |
| 140 | +closely as possible. | |
| 141 | + | |
| 130 | 142 | DebugFS interface |
| 131 | 143 | ~~~~~~~~~~~~~~~~~ |
| 132 | 144 | |
| @@ -1,23 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −/* | |
| 3 | − * Rules for implicitly atomic memory accesses. | |
| 4 | − * | |
| 5 | − * Copyright (C) 2019, Google LLC. | |
| 6 | − */ | |
| 7 | − | |
| 8 | −#ifndef _KERNEL_KCSAN_ATOMIC_H | |
| 9 | −#define _KERNEL_KCSAN_ATOMIC_H | |
| 10 | − | |
| 11 | −#include <linux/types.h> | |
| 12 | − | |
| 13 | −/* | |
| 14 | − * Special rules for certain memory where concurrent conflicting accesses are | |
| 15 | − * common, however, the current convention is to not mark them; returns true if | |
| 16 | − * access to @ptr should be considered atomic. Called from slow-path. | |
| 17 | − */ | |
| 18 | −static bool kcsan_is_atomic_special(const volatile void *ptr) | |
| 19 | −{ | |
| 20 | − return false; | |
| 21 | −} | |
| 22 | − | |
| 23 | −#endif /* _KERNEL_KCSAN_ATOMIC_H */ | |
| @@ -20,9 +20,9 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/sched.h> |
| 21 | 21 | #include <linux/uaccess.h> |
| 22 | 22 | |
| 23 | −#include "atomic.h" | |
| 24 | 23 | #include "encoding.h" |
| 25 | 24 | #include "kcsan.h" |
| 25 | +#include "permissive.h" | |
| 26 | 26 | |
| 27 | 27 | static bool kcsan_early_enable = IS_ENABLED(CONFIG_KCSAN_EARLY_ENABLE); |
| 28 | 28 | unsigned int kcsan_udelay_task = CONFIG_KCSAN_UDELAY_TASK; |
| @@ -301,9 +301,9 @@ static inline void reset_kcsan_skip(void) · 272 unmodified lines | ||
| 301 | 301 | this_cpu_write(kcsan_skip, skip_count); |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | −static __always_inline bool kcsan_is_enabled(void) | |
| 304 | +static __always_inline bool kcsan_is_enabled(struct kcsan_ctx *ctx) | |
| 305 | 305 | { |
| 306 | − return READ_ONCE(kcsan_enabled) && get_ctx()->disable_count == 0; | |
| 306 | + return READ_ONCE(kcsan_enabled) && !ctx->disable_count; | |
| 307 | 307 | } |
| 308 | 308 | |
| 309 | 309 | /* Introduce delay depending on context and configuration. */ |
| @@ -353,10 +353,18 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr, · 43 unmodified lines | ||
| 353 | 353 | atomic_long_t *watchpoint, |
| 354 | 354 | long encoded_watchpoint) |
| 355 | 355 | { |
| 356 | + const bool is_assert = (type & KCSAN_ACCESS_ASSERT) != 0; | |
| 357 | + struct kcsan_ctx *ctx = get_ctx(); | |
| 356 | 358 | unsigned long flags; |
| 357 | 359 | bool consumed; |
| 358 | 360 | |
| 359 | − if (!kcsan_is_enabled()) | |
| 361 | + /* | |
| 362 | + * We know a watchpoint exists. Let's try to keep the race-window | |
| 363 | + * between here and finally consuming the watchpoint below as small as | |
| 364 | + * possible -- avoid unneccessarily complex code until consumed. | |
| 365 | + */ | |
| 366 | + | |
| 367 | + if (!kcsan_is_enabled(ctx)) | |
| 360 | 368 | return; |
| 361 | 369 | |
| 362 | 370 | /* |
| @@ -364,14 +372,22 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr, · 1 unmodified line | ||
| 364 | 372 | * reporting a race where e.g. the writer set up the watchpoint, but the |
| 365 | 373 | * reader has access_mask!=0, we have to ignore the found watchpoint. |
| 366 | 374 | */ |
| 367 | − if (get_ctx()->access_mask != 0) | |
| 375 | + if (ctx->access_mask) | |
| 368 | 376 | return; |
| 369 | 377 | |
| 370 | 378 | /* |
| 371 | − * Consume the watchpoint as soon as possible, to minimize the chances | |
| 372 | − * of !consumed. Consuming the watchpoint must always be guarded by | |
| 373 | − * kcsan_is_enabled() check, as otherwise we might erroneously | |
| 374 | − * triggering reports when disabled. | |
| 379 | + * If the other thread does not want to ignore the access, and there was | |
| 380 | + * a value change as a result of this thread's operation, we will still | |
| 381 | + * generate a report of unknown origin. | |
| 382 | + * | |
| 383 | + * Use CONFIG_KCSAN_REPORT_RACE_UNKNOWN_ORIGIN=n to filter. | |
| 384 | + */ | |
| 385 | + if (!is_assert && kcsan_ignore_address(ptr)) | |
| 386 | + return; | |
| 387 | + | |
| 388 | + /* | |
| 389 | + * Consuming the watchpoint must be guarded by kcsan_is_enabled() to | |
| 390 | + * avoid erroneously triggering reports if the context is disabled. | |
| 375 | 391 | */ |
| 376 | 392 | consumed = try_consume_watchpoint(watchpoint, encoded_watchpoint); |
| 377 | 393 | |
| @@ -391,7 +407,7 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr, · 13 unmodified lines | ||
| 391 | 407 | atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_REPORT_RACES]); |
| 392 | 408 | } |
| 393 | 409 | |
| 394 | − if ((type & KCSAN_ACCESS_ASSERT) != 0) | |
| 410 | + if (is_assert) | |
| 395 | 411 | atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ASSERT_FAILURES]); |
| 396 | 412 | else |
| 397 | 413 | atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_DATA_RACES]); |
| @@ -409,6 +425,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) · 11 unmodified lines | ||
| 409 | 425 | unsigned long access_mask; |
| 410 | 426 | enum kcsan_value_change value_change = KCSAN_VALUE_CHANGE_MAYBE; |
| 411 | 427 | unsigned long ua_flags = user_access_save(); |
| 428 | + struct kcsan_ctx *ctx = get_ctx(); | |
| 412 | 429 | unsigned long irq_flags = 0; |
| 413 | 430 | |
| 414 | 431 | /* |
| @@ -417,16 +434,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) · 2 unmodified lines | ||
| 417 | 434 | */ |
| 418 | 435 | reset_kcsan_skip(); |
| 419 | 436 | |
| 420 | − if (!kcsan_is_enabled()) | |
| 437 | + if (!kcsan_is_enabled(ctx)) | |
| 421 | 438 | goto out; |
| 422 | 439 | |
| 423 | 440 | /* |
| 424 | − * Special atomic rules: unlikely to be true, so we check them here in | |
| 425 | − * the slow-path, and not in the fast-path in is_atomic(). Call after | |
| 426 | − * kcsan_is_enabled(), as we may access memory that is not yet | |
| 427 | − * initialized during early boot. | |
| 441 | + * Check to-ignore addresses after kcsan_is_enabled(), as we may access | |
| 442 | + * memory that is not yet initialized during early boot. | |
| 428 | 443 | */ |
| 429 | − if (!is_assert && kcsan_is_atomic_special(ptr)) | |
| 444 | + if (!is_assert && kcsan_ignore_address(ptr)) | |
| 430 | 445 | goto out; |
| 431 | 446 | |
| 432 | 447 | if (!check_encodable((unsigned long)ptr, size)) { |
| @@ -479,15 +494,6 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) · 46 unmodified lines | ||
| 479 | 494 | break; /* ignore; we do not diff the values */ |
| 480 | 495 | } |
| 481 | 496 | |
| 482 | − if (IS_ENABLED(CONFIG_KCSAN_DEBUG)) { | |
| 483 | − kcsan_disable_current(); | |
| 484 | − pr_err("watching %s, size: %zu, addr: %px [slot: %d, encoded: %lx]\n", | |
| 485 | − is_write ? "write" : "read", size, ptr, | |
| 486 | − watchpoint_slot((unsigned long)ptr), | |
| 487 | − encode_watchpoint((unsigned long)ptr, size, is_write)); | |
| 488 | − kcsan_enable_current(); | |
| 489 | − } | |
| 490 | − | |
| 491 | 497 | /* |
| 492 | 498 | * Delay this thread, to increase probability of observing a racy |
| 493 | 499 | * conflicting access. |
| @@ -498,7 +504,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) · 4 unmodified lines | ||
| 498 | 504 | * Re-read value, and check if it is as expected; if not, we infer a |
| 499 | 505 | * racy access. |
| 500 | 506 | */ |
| 501 | − access_mask = get_ctx()->access_mask; | |
| 507 | + access_mask = ctx->access_mask; | |
| 502 | 508 | new = 0; |
| 503 | 509 | switch (size) { |
| 504 | 510 | case 1: |
| @@ -521,8 +527,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) · 16 unmodified lines | ||
| 521 | 527 | if (access_mask) |
| 522 | 528 | diff &= access_mask; |
| 523 | 529 | |
| 524 | − /* Were we able to observe a value-change? */ | |
| 525 | − if (diff != 0) | |
| 530 | + /* | |
| 531 | + * Check if we observed a value change. | |
| 532 | + * | |
| 533 | + * Also check if the data race should be ignored (the rules depend on | |
| 534 | + * non-zero diff); if it is to be ignored, the below rules for | |
| 535 | + * KCSAN_VALUE_CHANGE_MAYBE apply. | |
| 536 | + */ | |
| 537 | + if (diff && !kcsan_ignore_data_race(size, type, old, new, diff)) | |
| 526 | 538 | value_change = KCSAN_VALUE_CHANGE_TRUE; |
| 527 | 539 | |
| 528 | 540 | /* Check if this access raced with another. */ |
| @@ -644,6 +656,15 @@ void __init kcsan_init(void) · 115 unmodified lines | ||
| 644 | 656 | pr_info("enabled early\n"); |
| 645 | 657 | WRITE_ONCE(kcsan_enabled, true); |
| 646 | 658 | } |
| 659 | + | |
| 660 | + if (IS_ENABLED(CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY) || | |
| 661 | + IS_ENABLED(CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC) || | |
| 662 | + IS_ENABLED(CONFIG_KCSAN_PERMISSIVE) || | |
| 663 | + IS_ENABLED(CONFIG_KCSAN_IGNORE_ATOMICS)) { | |
| 664 | + pr_warn("non-strict mode configured - use CONFIG_KCSAN_STRICT=y to see all data races\n"); | |
| 665 | + } else { | |
| 666 | + pr_info("strict mode configured\n"); | |
| 667 | + } | |
| 647 | 668 | } |
| 648 | 669 | |
| 649 | 670 | /* === Exported interface =================================================== */ |
| @@ -414,6 +414,14 @@ static noinline void test_kernel_atomic_builtins(void) · 413 unmodified lines | ||
| 414 | 414 | __atomic_load_n(&test_var, __ATOMIC_RELAXED); |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | +static noinline void test_kernel_xor_1bit(void) | |
| 418 | +{ | |
| 419 | + /* Do not report data races between the read-writes. */ | |
| 420 | + kcsan_nestable_atomic_begin(); | |
| 421 | + test_var ^= 0x10000; | |
| 422 | + kcsan_nestable_atomic_end(); | |
| 423 | +} | |
| 424 | + | |
| 417 | 425 | /* ===== Test cases ===== */ |
| 418 | 426 | |
| 419 | 427 | /* Simple test with normal data race. */ |
| @@ -952,6 +960,29 @@ static void test_atomic_builtins(struct kunit *test) · 532 unmodified lines | ||
| 952 | 960 | KUNIT_EXPECT_FALSE(test, match_never); |
| 953 | 961 | } |
| 954 | 962 | |
| 963 | +__no_kcsan | |
| 964 | +static void test_1bit_value_change(struct kunit *test) | |
| 965 | +{ | |
| 966 | + const struct expect_report expect = { | |
| 967 | + .access = { | |
| 968 | + { test_kernel_read, &test_var, sizeof(test_var), 0 }, | |
| 969 | + { test_kernel_xor_1bit, &test_var, sizeof(test_var), __KCSAN_ACCESS_RW(KCSAN_ACCESS_WRITE) }, | |
| 970 | + }, | |
| 971 | + }; | |
| 972 | + bool match = false; | |
| 973 | + | |
| 974 | + begin_test_checks(test_kernel_read, test_kernel_xor_1bit); | |
| 975 | + do { | |
| 976 | + match = IS_ENABLED(CONFIG_KCSAN_PERMISSIVE) | |
| 977 | + ? report_available() | |
| 978 | + : report_matches(&expect); | |
| 979 | + } while (!end_test_checks(match)); | |
| 980 | + if (IS_ENABLED(CONFIG_KCSAN_PERMISSIVE)) | |
| 981 | + KUNIT_EXPECT_FALSE(test, match); | |
| 982 | + else | |
| 983 | + KUNIT_EXPECT_TRUE(test, match); | |
| 984 | +} | |
| 985 | + | |
| 955 | 986 | /* |
| 956 | 987 | * Generate thread counts for all test cases. Values generated are in interval |
| 957 | 988 | * [2, 5] followed by exponentially increasing thread counts from 8 to 32. |
| @@ -1024,6 +1055,7 @@ static struct kunit_case kcsan_test_cases[] = { · 66 unmodified lines | ||
| 1024 | 1055 | KCSAN_KUNIT_CASE(test_jiffies_noreport), |
| 1025 | 1056 | KCSAN_KUNIT_CASE(test_seqlock_noreport), |
| 1026 | 1057 | KCSAN_KUNIT_CASE(test_atomic_builtins), |
| 1058 | + KCSAN_KUNIT_CASE(test_1bit_value_change), | |
| 1027 | 1059 | {}, |
| 1028 | 1060 | }; |
| 1029 | 1061 | |
| @@ -0,0 +1,94 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +/* | |
| 3 | + * Special rules for ignoring entire classes of data-racy memory accesses. None | |
| 4 | + * of the rules here imply that such data races are generally safe! | |
| 5 | + * | |
| 6 | + * All rules in this file can be configured via CONFIG_KCSAN_PERMISSIVE. Keep | |
| 7 | + * them separate from core code to make it easier to audit. | |
| 8 | + * | |
| 9 | + * Copyright (C) 2019, Google LLC. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef _KERNEL_KCSAN_PERMISSIVE_H | |
| 13 | +#define _KERNEL_KCSAN_PERMISSIVE_H | |
| 14 | + | |
| 15 | +#include <linux/bitops.h> | |
| 16 | +#include <linux/sched.h> | |
| 17 | +#include <linux/types.h> | |
| 18 | + | |
| 19 | +/* | |
| 20 | + * Access ignore rules based on address. | |
| 21 | + */ | |
| 22 | +static __always_inline bool kcsan_ignore_address(const volatile void *ptr) | |
| 23 | +{ | |
| 24 | + if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE)) | |
| 25 | + return false; | |
| 26 | + | |
| 27 | + /* | |
| 28 | + * Data-racy bitops on current->flags are too common, ignore completely | |
| 29 | + * for now. | |
| 30 | + */ | |
| 31 | + return ptr == ¤t->flags; | |
| 32 | +} | |
| 33 | + | |
| 34 | +/* | |
| 35 | + * Data race ignore rules based on access type and value change patterns. | |
| 36 | + */ | |
| 37 | +static bool | |
| 38 | +kcsan_ignore_data_race(size_t size, int type, u64 old, u64 new, u64 diff) | |
| 39 | +{ | |
| 40 | + if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE)) | |
| 41 | + return false; | |
| 42 | + | |
| 43 | + /* | |
| 44 | + * Rules here are only for plain read accesses, so that we still report | |
| 45 | + * data races between plain read-write accesses. | |
| 46 | + */ | |
| 47 | + if (type || size > sizeof(long)) | |
| 48 | + return false; | |
| 49 | + | |
| 50 | + /* | |
| 51 | + * A common pattern is checking/setting just 1 bit in a variable; for | |
| 52 | + * example: | |
| 53 | + * | |
| 54 | + * if (flags & SOME_FLAG) { ... } | |
| 55 | + * | |
| 56 | + * and elsewhere flags is updated concurrently: | |
| 57 | + * | |
| 58 | + * flags |= SOME_OTHER_FLAG; // just 1 bit | |
| 59 | + * | |
| 60 | + * While it is still recommended that such accesses be marked | |
| 61 | + * appropriately, in many cases these types of data races are so common | |
| 62 | + * that marking them all is often unrealistic and left to maintainer | |
| 63 | + * preference. | |
| 64 | + * | |
| 65 | + * The assumption in all cases is that with all known compiler | |
| 66 | + * optimizations (including those that tear accesses), because no more | |
| 67 | + * than 1 bit changed, the plain accesses are safe despite the presence | |
| 68 | + * of data races. | |
| 69 | + * | |
| 70 | + * The rules here will ignore the data races if we observe no more than | |
| 71 | + * 1 bit changed. | |
| 72 | + * | |
| 73 | + * Of course many operations can effecively change just 1 bit, but the | |
| 74 | + * general assuption that data races involving 1-bit changes can be | |
| 75 | + * tolerated still applies. | |
| 76 | + * | |
| 77 | + * And in case a true bug is missed, the bug likely manifests as a | |
| 78 | + * reportable data race elsewhere. | |
| 79 | + */ | |
| 80 | + if (hweight64(diff) == 1) { | |
| 81 | + /* | |
| 82 | + * Exception: Report data races where the values look like | |
| 83 | + * ordinary booleans (one of them was 0 and the 0th bit was | |
| 84 | + * changed) More often than not, they come with interesting | |
| 85 | + * memory ordering requirements, so let's report them. | |
| 86 | + */ | |
| 87 | + if (!((!old || !new) && diff == 1)) | |
| 88 | + return true; | |
| 89 | + } | |
| 90 | + | |
| 91 | + return false; | |
| 92 | +} | |
| 93 | + | |
| 94 | +#endif /* _KERNEL_KCSAN_PERMISSIVE_H */ | |
| @@ -40,10 +40,14 @@ menuconfig KCSAN · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | if KCSAN |
| 42 | 42 | |
| 43 | −# Compiler capabilities that should not fail the test if they are unavailable. | |
| 44 | 43 | config CC_HAS_TSAN_COMPOUND_READ_BEFORE_WRITE |
| 45 | 44 | def_bool (CC_IS_CLANG && $(cc-option,-fsanitize=thread -mllvm -tsan-compound-read-before-write=1)) || \ |
| 46 | 45 | (CC_IS_GCC && $(cc-option,-fsanitize=thread --param tsan-compound-read-before-write=1)) |
| 46 | + help | |
| 47 | + The compiler instruments plain compound read-write operations | |
| 48 | + differently (++, --, +=, -=, |=, &=, etc.), which allows KCSAN to | |
| 49 | + distinguish them from other plain accesses. This is currently | |
| 50 | + supported by Clang 12 or later. | |
| 47 | 51 | |
| 48 | 52 | config KCSAN_VERBOSE |
| 49 | 53 | bool "Show verbose reports with more information about system state" |
| @@ -58,9 +62,6 @@ config KCSAN_VERBOSE · 8 unmodified lines | ||
| 58 | 62 | generated from any one of them, system stability may suffer due to |
| 59 | 63 | deadlocks or recursion. If in doubt, say N. |
| 60 | 64 | |
| 61 | −config KCSAN_DEBUG | |
| 62 | − bool "Debugging of KCSAN internals" | |
| 63 | − | |
| 64 | 65 | config KCSAN_SELFTEST |
| 65 | 66 | bool "Perform short selftests on boot" |
| 66 | 67 | default y |
| @@ -149,7 +150,8 @@ config KCSAN_SKIP_WATCH_RANDOMIZE · 82 unmodified lines | ||
| 149 | 150 | KCSAN_WATCH_SKIP. |
| 150 | 151 | |
| 151 | 152 | config KCSAN_INTERRUPT_WATCHER |
| 152 | − bool "Interruptible watchers" | |
| 153 | + bool "Interruptible watchers" if !KCSAN_STRICT | |
| 154 | + default KCSAN_STRICT | |
| 153 | 155 | help |
| 154 | 156 | If enabled, a task that set up a watchpoint may be interrupted while |
| 155 | 157 | delayed. This option will allow KCSAN to detect races between |
| @@ -169,13 +171,9 @@ config KCSAN_REPORT_ONCE_IN_MS · 13 unmodified lines | ||
| 169 | 171 | reporting to avoid flooding the console with reports. Setting this |
| 170 | 172 | to 0 disables rate limiting. |
| 171 | 173 | |
| 172 | −# The main purpose of the below options is to control reported data races (e.g. | |
| 173 | −# in fuzzer configs), and are not expected to be switched frequently by other | |
| 174 | −# users. We could turn some of them into boot parameters, but given they should | |
| 175 | −# not be switched normally, let's keep them here to simplify configuration. | |
| 176 | −# | |
| 177 | −# The defaults below are chosen to be very conservative, and may miss certain | |
| 178 | −# bugs. | |
| 174 | +# The main purpose of the below options is to control reported data races, and | |
| 175 | +# are not expected to be switched frequently by non-testers or at runtime. | |
| 176 | +# The defaults are chosen to be conservative, and can miss certain bugs. | |
| 179 | 177 | |
| 180 | 178 | config KCSAN_REPORT_RACE_UNKNOWN_ORIGIN |
| 181 | 179 | bool "Report races of unknown origin" |
| @@ -186,9 +184,17 @@ config KCSAN_REPORT_RACE_UNKNOWN_ORIGIN · 4 unmodified lines | ||
| 186 | 184 | reported if it was only possible to infer a race due to a data value |
| 187 | 185 | change while an access is being delayed on a watchpoint. |
| 188 | 186 | |
| 187 | +config KCSAN_STRICT | |
| 188 | + bool "Strict data-race checking" | |
| 189 | + help | |
| 190 | + KCSAN will report data races with the strictest possible rules, which | |
| 191 | + closely aligns with the rules defined by the Linux-kernel memory | |
| 192 | + consistency model (LKMM). | |
| 193 | + | |
| 189 | 194 | config KCSAN_REPORT_VALUE_CHANGE_ONLY |
| 190 | 195 | bool "Only report races where watcher observed a data value change" |
| 191 | 196 | default y |
| 197 | + depends on !KCSAN_STRICT | |
| 192 | 198 | help |
| 193 | 199 | If enabled and a conflicting write is observed via a watchpoint, but |
| 194 | 200 | the data value of the memory location was observed to remain |
| @@ -197,6 +203,7 @@ config KCSAN_REPORT_VALUE_CHANGE_ONLY · 2 unmodified lines | ||
| 197 | 203 | config KCSAN_ASSUME_PLAIN_WRITES_ATOMIC |
| 198 | 204 | bool "Assume that plain aligned writes up to word size are atomic" |
| 199 | 205 | default y |
| 206 | + depends on !KCSAN_STRICT | |
| 200 | 207 | help |
| 201 | 208 | Assume that plain aligned writes up to word size are atomic by |
| 202 | 209 | default, and also not subject to other unsafe compiler optimizations |
| @@ -209,6 +216,7 @@ config KCSAN_ASSUME_PLAIN_WRITES_ATOMIC · 6 unmodified lines | ||
| 209 | 216 | |
| 210 | 217 | config KCSAN_IGNORE_ATOMICS |
| 211 | 218 | bool "Do not instrument marked atomic accesses" |
| 219 | + depends on !KCSAN_STRICT | |
| 212 | 220 | help |
| 213 | 221 | Never instrument marked atomic accesses. This option can be used for |
| 214 | 222 | additional filtering. Conflicting marked atomic reads and plain |
| @@ -224,4 +232,14 @@ config KCSAN_IGNORE_ATOMICS · 9 unmodified lines | ||
| 224 | 232 | due to two conflicting plain writes will be reported (aligned and |
| 225 | 233 | unaligned, if CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n). |
| 226 | 234 | |
| 235 | +config KCSAN_PERMISSIVE | |
| 236 | + bool "Enable all additional permissive rules" | |
| 237 | + depends on KCSAN_REPORT_VALUE_CHANGE_ONLY | |
| 238 | + help | |
| 239 | + Enable additional permissive rules to ignore certain classes of data | |
| 240 | + races (also see kernel/kcsan/permissive.h). None of the permissive | |
| 241 | + rules imply that such data races are generally safe, but can be used | |
| 242 | + to further reduce reported data races due to data-racy patterns | |
| 243 | + common across the kernel. | |
| 244 | + | |
| 227 | 245 | endif # KCSAN |