Skip to content

Commit

Permalink
Merge branch 'kcsan' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/paulmck/linux-rcu into locking/core

Pull v5.9 KCSAN bits from Paul E. McKenney.

Perhaps the most important change is that GCC 11 now has all fixes in place
to support KCSAN, so GCC support can be enabled again.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Aug 1, 2020
2 parents 28cff52 + 61d56d7 commit 63722bb
Show file tree
Hide file tree
Showing 12 changed files with 1,166 additions and 14 deletions.
3 changes: 2 additions & 1 deletion Documentation/dev-tools/kcsan.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ approach to detect races. KCSAN's primary purpose is to detect `data races`_.
Usage
-----

KCSAN requires Clang version 11 or later.
KCSAN is supported by both GCC and Clang. With GCC we require version 11 or
later, and with Clang also require version 11 or later.

To enable KCSAN configure the kernel with::

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/pat/set_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ static inline void cpa_inc_2m_checked(void)

static inline void cpa_inc_4k_install(void)
{
cpa_4k_install++;
data_race(cpa_4k_install++);
}

static inline void cpa_inc_lp_sameprot(int level)
Expand Down
2 changes: 2 additions & 0 deletions include/linux/rculist.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ static inline void __list_splice_init_rcu(struct list_head *list,
*/

sync();
ASSERT_EXCLUSIVE_ACCESS(*first);
ASSERT_EXCLUSIVE_ACCESS(*last);

/*
* Readers are finished with the source list, so perform splice.
Expand Down
8 changes: 7 additions & 1 deletion kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,13 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig)
struct vm_area_struct *new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);

if (new) {
*new = *orig;
ASSERT_EXCLUSIVE_WRITER(orig->vm_flags);
ASSERT_EXCLUSIVE_WRITER(orig->vm_file);
/*
* orig->shared.rb may be modified concurrently, but the clone
* will be reinitialized.
*/
*new = data_race(*orig);
INIT_LIST_HEAD(&new->anon_vma_chain);
new->vm_next = new->vm_prev = NULL;
}
Expand Down
9 changes: 6 additions & 3 deletions kernel/kcsan/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ CFLAGS_REMOVE_core.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_debugfs.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_report.o = $(CC_FLAGS_FTRACE)

CFLAGS_core.o := $(call cc-option,-fno-conserve-stack,) \
$(call cc-option,-fno-stack-protector,)
CFLAGS_core.o := $(call cc-option,-fno-conserve-stack) \
-fno-stack-protector -DDISABLE_BRANCH_PROFILING

obj-y := core.o debugfs.o report.o
obj-$(CONFIG_KCSAN_SELFTEST) += test.o
obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o

CFLAGS_kcsan-test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
obj-$(CONFIG_KCSAN_TEST) += kcsan-test.o
6 changes: 2 additions & 4 deletions kernel/kcsan/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
#ifndef _KERNEL_KCSAN_ATOMIC_H
#define _KERNEL_KCSAN_ATOMIC_H

#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/types.h>

/*
* Special rules for certain memory where concurrent conflicting accesses are
Expand All @@ -13,8 +12,7 @@
*/
static bool kcsan_is_atomic_special(const volatile void *ptr)
{
/* volatile globals that have been observed in data races. */
return ptr == &jiffies || ptr == &current->state;
return false;
}

#endif /* _KERNEL_KCSAN_ATOMIC_H */
9 changes: 9 additions & 0 deletions kernel/kcsan/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ EXPORT_SYMBOL(__kcsan_check_access);
*/

#define DEFINE_TSAN_READ_WRITE(size) \
void __tsan_read##size(void *ptr); \
void __tsan_read##size(void *ptr) \
{ \
check_access(ptr, size, 0); \
Expand All @@ -784,6 +785,7 @@ EXPORT_SYMBOL(__kcsan_check_access);
void __tsan_unaligned_read##size(void *ptr) \
__alias(__tsan_read##size); \
EXPORT_SYMBOL(__tsan_unaligned_read##size); \
void __tsan_write##size(void *ptr); \
void __tsan_write##size(void *ptr) \
{ \
check_access(ptr, size, KCSAN_ACCESS_WRITE); \
Expand All @@ -799,12 +801,14 @@ DEFINE_TSAN_READ_WRITE(4);
DEFINE_TSAN_READ_WRITE(8);
DEFINE_TSAN_READ_WRITE(16);

void __tsan_read_range(void *ptr, size_t size);
void __tsan_read_range(void *ptr, size_t size)
{
check_access(ptr, size, 0);
}
EXPORT_SYMBOL(__tsan_read_range);

void __tsan_write_range(void *ptr, size_t size);
void __tsan_write_range(void *ptr, size_t size)
{
check_access(ptr, size, KCSAN_ACCESS_WRITE);
Expand All @@ -821,6 +825,7 @@ EXPORT_SYMBOL(__tsan_write_range);
* the size-check of compiletime_assert_rwonce_type().
*/
#define DEFINE_TSAN_VOLATILE_READ_WRITE(size) \
void __tsan_volatile_read##size(void *ptr); \
void __tsan_volatile_read##size(void *ptr) \
{ \
const bool is_atomic = size <= sizeof(long long) && \
Expand All @@ -833,6 +838,7 @@ EXPORT_SYMBOL(__tsan_write_range);
void __tsan_unaligned_volatile_read##size(void *ptr) \
__alias(__tsan_volatile_read##size); \
EXPORT_SYMBOL(__tsan_unaligned_volatile_read##size); \
void __tsan_volatile_write##size(void *ptr); \
void __tsan_volatile_write##size(void *ptr) \
{ \
const bool is_atomic = size <= sizeof(long long) && \
Expand All @@ -858,14 +864,17 @@ DEFINE_TSAN_VOLATILE_READ_WRITE(16);
* The below are not required by KCSAN, but can still be emitted by the
* compiler.
*/
void __tsan_func_entry(void *call_pc);
void __tsan_func_entry(void *call_pc)
{
}
EXPORT_SYMBOL(__tsan_func_entry);
void __tsan_func_exit(void);
void __tsan_func_exit(void)
{
}
EXPORT_SYMBOL(__tsan_func_exit);
void __tsan_init(void);
void __tsan_init(void)
{
}
Expand Down
Loading

0 comments on commit 63722bb

Please sign in to comment.