kcsan: permissive: Ignore data-racy 1-bit value changes
authorMarco Elver <elver@google.com>
Mon, 7 Jun 2021 12:56:53 +0000 (14:56 +0200)
committerPaul E. McKenney <paulmck@kernel.org>
Tue, 20 Jul 2021 20:49:44 +0000 (13:49 -0700)
commitd8fd74d35a8d3c602232e3238e916bda9d03d520
treecb6e2461b1af5196bb1dfccc03adc288c120934e
parent9c827cd1fcdf54bb50f874f91af0d5de2aceb035
kcsan: permissive: Ignore data-racy 1-bit value changes

Add rules to ignore data-racy reads with only 1-bit value changes.
Details about the rules are captured in comments in
kernel/kcsan/permissive.h. More background follows.

While investigating a number of data races, we've encountered data-racy
accesses on flags variables to be very common. The typical pattern is a
reader masking all but one bit, and/or the writer setting/clearing only
1 bit (current->flags being a frequently encountered case; more examples
in mm/sl[au]b.c, which disable KCSAN for this reason).

Since these types of data-racy accesses are common (with the assumption
they are intentional and hard to miscompile) having the option (with
CONFIG_KCSAN_PERMISSIVE=y) to filter them will avoid forcing everyone to
mark them, and deliberately left to preference at this time.

One important motivation for having this option built-in is to move
closer to being able to enable KCSAN on CI systems or for testers
wishing to test the whole kernel, while more easily filtering
less interesting data races with higher probability.

For the implementation, we considered several alternatives, but had one
major requirement: that the rules be kept together with the Linux-kernel
tree. Adding them to the compiler would preclude us from making changes
quickly; if the rules require tweaks, having them part of the compiler
requires waiting another ~1 year for the next release -- that's not
realistic. We are left with the following options:

1. Maintain compiler plugins as part of the kernel-tree that
   removes instrumentation for some accesses (e.g. plain-& with
   1-bit mask). The analysis would be reader-side focused, as
   no assumption can be made about racing writers.

Because it seems unrealistic to maintain 2 plugins, one for LLVM and
GCC, we would likely pick LLVM. Furthermore, no kernel infrastructure
exists to maintain LLVM plugins, and the build-system implications and
maintenance overheads do not look great (historically, plugins written
against old LLVM APIs are not guaranteed to work with newer LLVM APIs).

2. Find a set of rules that can be expressed in terms of
   observed value changes, and make it part of the KCSAN runtime.
   The analysis is writer-side focused, given we rely on observed
   value changes.

The approach taken here is (2). While a complete approach requires both
(1) and (2), experiments show that the majority of data races involving
trivial bit operations on flags variables can be removed with (2) alone.

It goes without saying that the filtering of data races using (1) or (2)
does _not_ guarantee they are safe! Therefore, limiting ourselves to (2)
for now is the conservative choice for setups that wish to enable
CONFIG_KCSAN_PERMISSIVE=y.

Signed-off-by: Marco Elver <elver@google.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/kcsan/kcsan_test.c
kernel/kcsan/permissive.h