Skip to content

Commit

Permalink
Merge tag 'kcsan.2023.04.04a' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/paulmck/linux-rcu

Pull KCSAN updates from Paul McKenney:
 "Kernel concurrency sanitizer (KCSAN) updates for v6.4

  This fixes kernel-doc warnings and also updates instrumentation from
  READ_ONCE() to volatile in order to avoid unaligned load-acquire
  instructions on arm64 in kernels built with LTO"

* tag 'kcsan.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
  kcsan: Avoid READ_ONCE() in read_instrumented_memory()
  instrumented.h: Fix all kernel-doc format warnings
  • Loading branch information
Linus Torvalds committed Apr 24, 2023
2 parents 1a0beef + 8dec880 commit 022e320
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 41 deletions.
63 changes: 26 additions & 37 deletions include/linux/instrumented.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@

/**
* instrument_read - instrument regular read access
* @v: address of access
* @size: size of access
*
* Instrument a regular read access. The instrumentation should be inserted
* before the actual read happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_read(const volatile void *v, size_t size)
{
Expand All @@ -30,12 +29,11 @@ static __always_inline void instrument_read(const volatile void *v, size_t size)

/**
* instrument_write - instrument regular write access
* @v: address of access
* @size: size of access
*
* Instrument a regular write access. The instrumentation should be inserted
* before the actual write happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_write(const volatile void *v, size_t size)
{
Expand All @@ -45,12 +43,11 @@ static __always_inline void instrument_write(const volatile void *v, size_t size

/**
* instrument_read_write - instrument regular read-write access
* @v: address of access
* @size: size of access
*
* Instrument a regular write access. The instrumentation should be inserted
* before the actual write happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_read_write(const volatile void *v, size_t size)
{
Expand All @@ -60,12 +57,11 @@ static __always_inline void instrument_read_write(const volatile void *v, size_t

/**
* instrument_atomic_read - instrument atomic read access
* @v: address of access
* @size: size of access
*
* Instrument an atomic read access. The instrumentation should be inserted
* before the actual read happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_atomic_read(const volatile void *v, size_t size)
{
Expand All @@ -75,12 +71,11 @@ static __always_inline void instrument_atomic_read(const volatile void *v, size_

/**
* instrument_atomic_write - instrument atomic write access
* @v: address of access
* @size: size of access
*
* Instrument an atomic write access. The instrumentation should be inserted
* before the actual write happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_atomic_write(const volatile void *v, size_t size)
{
Expand All @@ -90,12 +85,11 @@ static __always_inline void instrument_atomic_write(const volatile void *v, size

/**
* instrument_atomic_read_write - instrument atomic read-write access
* @v: address of access
* @size: size of access
*
* Instrument an atomic read-write access. The instrumentation should be
* inserted before the actual write happens.
*
* @ptr address of access
* @size size of access
*/
static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
{
Expand All @@ -105,13 +99,12 @@ static __always_inline void instrument_atomic_read_write(const volatile void *v,

/**
* instrument_copy_to_user - instrument reads of copy_to_user
* @to: destination address
* @from: source address
* @n: number of bytes to copy
*
* Instrument reads from kernel memory, that are due to copy_to_user (and
* variants). The instrumentation must be inserted before the accesses.
*
* @to destination address
* @from source address
* @n number of bytes to copy
*/
static __always_inline void
instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
Expand All @@ -123,13 +116,12 @@ instrument_copy_to_user(void __user *to, const void *from, unsigned long n)

/**
* instrument_copy_from_user_before - add instrumentation before copy_from_user
* @to: destination address
* @from: source address
* @n: number of bytes to copy
*
* Instrument writes to kernel memory, that are due to copy_from_user (and
* variants). The instrumentation should be inserted before the accesses.
*
* @to destination address
* @from source address
* @n number of bytes to copy
*/
static __always_inline void
instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n)
Expand All @@ -140,14 +132,13 @@ instrument_copy_from_user_before(const void *to, const void __user *from, unsign

/**
* instrument_copy_from_user_after - add instrumentation after copy_from_user
* @to: destination address
* @from: source address
* @n: number of bytes to copy
* @left: number of bytes not copied (as returned by copy_from_user)
*
* Instrument writes to kernel memory, that are due to copy_from_user (and
* variants). The instrumentation should be inserted after the accesses.
*
* @to destination address
* @from source address
* @n number of bytes to copy
* @left number of bytes not copied (as returned by copy_from_user)
*/
static __always_inline void
instrument_copy_from_user_after(const void *to, const void __user *from,
Expand All @@ -158,12 +149,11 @@ instrument_copy_from_user_after(const void *to, const void __user *from,

/**
* instrument_get_user() - add instrumentation to get_user()-like macros
* @to: destination variable, may not be address-taken
*
* get_user() and friends are fragile, so it may depend on the implementation
* whether the instrumentation happens before or after the data is copied from
* the userspace.
*
* @to destination variable, may not be address-taken
*/
#define instrument_get_user(to) \
({ \
Expand All @@ -175,14 +165,13 @@ instrument_copy_from_user_after(const void *to, const void __user *from,

/**
* instrument_put_user() - add instrumentation to put_user()-like macros
* @from: source address
* @ptr: userspace pointer to copy to
* @size: number of bytes to copy
*
* put_user() and friends are fragile, so it may depend on the implementation
* whether the instrumentation happens before or after the data is copied from
* the userspace.
*
* @from source address
* @ptr userspace pointer to copy to
* @size number of bytes to copy
*/
#define instrument_put_user(from, ptr, size) \
({ \
Expand Down
17 changes: 13 additions & 4 deletions kernel/kcsan/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,20 @@ static void delay_access(int type)
*/
static __always_inline u64 read_instrumented_memory(const volatile void *ptr, size_t size)
{
/*
* In the below we don't necessarily need the read of the location to
* be atomic, and we don't use READ_ONCE(), since all we need for race
* detection is to observe 2 different values.
*
* Furthermore, on certain architectures (such as arm64), READ_ONCE()
* may turn into more complex instructions than a plain load that cannot
* do unaligned accesses.
*/
switch (size) {
case 1: return READ_ONCE(*(const u8 *)ptr);
case 2: return READ_ONCE(*(const u16 *)ptr);
case 4: return READ_ONCE(*(const u32 *)ptr);
case 8: return READ_ONCE(*(const u64 *)ptr);
case 1: return *(const volatile u8 *)ptr;
case 2: return *(const volatile u16 *)ptr;
case 4: return *(const volatile u32 *)ptr;
case 8: return *(const volatile u64 *)ptr;
default: return 0; /* Ignore; we do not diff the values. */
}
}
Expand Down

0 comments on commit 022e320

Please sign in to comment.