Skip to content

Commit ece69af

Browse files
thejharndb
authored andcommitted
rwonce: handle KCSAN like KASAN in read_word_at_a_time()
read_word_at_a_time() is allowed to read out of bounds by straddling the end of an allocation (and the caller is expected to then mask off out-of-bounds data). This works as long as the caller guarantees that the access won't hit a pagefault (either by ensuring that addr is aligned or by explicitly checking where the next page boundary is). Such out-of-bounds data could include things like KASAN redzones, adjacent allocations that are concurrently written to, or simply an adjacent struct field that is concurrently updated. KCSAN should ignore racy reads of OOB data that is not actually used, just like KASAN, so (similar to the code above) change read_word_at_a_time() to use __no_sanitize_or_inline instead of __no_kasan_or_inline, and explicitly inform KCSAN that we're reading the first byte. We do have an instrument_read() helper that calls into both KASAN and KCSAN, but I'm instead open-coding that here to avoid having to pull the entire instrumented.h header into rwonce.h. Also, since this read can be racy by design, we should technically do READ_ONCE(), so add that. Fixes: dfd402a ("kcsan: Add Kernel Concurrency Sanitizer infrastructure") Signed-off-by: Jann Horn <jannh@google.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Marco Elver <elver@google.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1 parent dcce854 commit ece69af

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

include/asm-generic/rwonce.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,14 @@ unsigned long __read_once_word_nocheck(const void *addr)
7979
(typeof(x))__read_once_word_nocheck(&(x)); \
8080
})
8181

82-
static __no_kasan_or_inline
82+
static __no_sanitize_or_inline
8383
unsigned long read_word_at_a_time(const void *addr)
8484
{
85+
/* open-coded instrument_read(addr, 1) */
8586
kasan_check_read(addr, 1);
86-
return *(unsigned long *)addr;
87+
kcsan_check_read(addr, 1);
88+
89+
return READ_ONCE(*(unsigned long *)addr);
8790
}
8891

8992
#endif /* __ASSEMBLY__ */

0 commit comments

Comments
 (0)