Commit 022e3209 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'kcsan.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/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
parents 1a0beef9 8dec8807
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
/** /**
* instrument_read - instrument regular read access * instrument_read - instrument regular read access
* @v: address of access
* @size: size of access
* *
* Instrument a regular read access. The instrumentation should be inserted * Instrument a regular read access. The instrumentation should be inserted
* before the actual read happens. * 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) static __always_inline void instrument_read(const volatile void *v, size_t size)
{ {
...@@ -30,12 +29,11 @@ static __always_inline void instrument_read(const volatile void *v, size_t size) ...@@ -30,12 +29,11 @@ static __always_inline void instrument_read(const volatile void *v, size_t size)
/** /**
* instrument_write - instrument regular write access * instrument_write - instrument regular write access
* @v: address of access
* @size: size of access
* *
* Instrument a regular write access. The instrumentation should be inserted * Instrument a regular write access. The instrumentation should be inserted
* before the actual write happens. * 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) static __always_inline void instrument_write(const volatile void *v, size_t size)
{ {
...@@ -45,12 +43,11 @@ static __always_inline void instrument_write(const volatile void *v, size_t size ...@@ -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 * 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 * Instrument a regular write access. The instrumentation should be inserted
* before the actual write happens. * 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) static __always_inline void instrument_read_write(const volatile void *v, size_t size)
{ {
...@@ -60,12 +57,11 @@ static __always_inline void instrument_read_write(const volatile void *v, size_t ...@@ -60,12 +57,11 @@ static __always_inline void instrument_read_write(const volatile void *v, size_t
/** /**
* instrument_atomic_read - instrument atomic read access * 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 * Instrument an atomic read access. The instrumentation should be inserted
* before the actual read happens. * 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) static __always_inline void instrument_atomic_read(const volatile void *v, size_t size)
{ {
...@@ -75,12 +71,11 @@ static __always_inline void instrument_atomic_read(const volatile void *v, size_ ...@@ -75,12 +71,11 @@ static __always_inline void instrument_atomic_read(const volatile void *v, size_
/** /**
* instrument_atomic_write - instrument atomic write access * 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 * Instrument an atomic write access. The instrumentation should be inserted
* before the actual write happens. * 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) static __always_inline void instrument_atomic_write(const volatile void *v, size_t size)
{ {
...@@ -90,12 +85,11 @@ static __always_inline void instrument_atomic_write(const volatile void *v, size ...@@ -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 * 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 * Instrument an atomic read-write access. The instrumentation should be
* inserted before the actual write happens. * 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) static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
{ {
...@@ -105,13 +99,12 @@ static __always_inline void instrument_atomic_read_write(const volatile void *v, ...@@ -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 * 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 * Instrument reads from kernel memory, that are due to copy_to_user (and
* variants). The instrumentation must be inserted before the accesses. * 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 static __always_inline void
instrument_copy_to_user(void __user *to, const void *from, unsigned long n) instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
...@@ -123,13 +116,12 @@ instrument_copy_to_user(void __user *to, const void *from, unsigned long n) ...@@ -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 * 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 * Instrument writes to kernel memory, that are due to copy_from_user (and
* variants). The instrumentation should be inserted before the accesses. * 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 static __always_inline void
instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n) instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n)
...@@ -140,14 +132,13 @@ instrument_copy_from_user_before(const void *to, const void __user *from, unsign ...@@ -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 * 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 * Instrument writes to kernel memory, that are due to copy_from_user (and
* variants). The instrumentation should be inserted after the accesses. * 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 static __always_inline void
instrument_copy_from_user_after(const void *to, const void __user *from, instrument_copy_from_user_after(const void *to, const void __user *from,
...@@ -158,12 +149,11 @@ instrument_copy_from_user_after(const void *to, const void __user *from, ...@@ -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 * 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 * 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 * whether the instrumentation happens before or after the data is copied from
* the userspace. * the userspace.
*
* @to destination variable, may not be address-taken
*/ */
#define instrument_get_user(to) \ #define instrument_get_user(to) \
({ \ ({ \
...@@ -175,14 +165,13 @@ instrument_copy_from_user_after(const void *to, const void __user *from, ...@@ -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 * 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 * 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 * whether the instrumentation happens before or after the data is copied from
* the userspace. * the userspace.
*
* @from source address
* @ptr userspace pointer to copy to
* @size number of bytes to copy
*/ */
#define instrument_put_user(from, ptr, size) \ #define instrument_put_user(from, ptr, size) \
({ \ ({ \
......
...@@ -337,11 +337,20 @@ static void delay_access(int type) ...@@ -337,11 +337,20 @@ static void delay_access(int type)
*/ */
static __always_inline u64 read_instrumented_memory(const volatile void *ptr, size_t size) 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) { switch (size) {
case 1: return READ_ONCE(*(const u8 *)ptr); case 1: return *(const volatile u8 *)ptr;
case 2: return READ_ONCE(*(const u16 *)ptr); case 2: return *(const volatile u16 *)ptr;
case 4: return READ_ONCE(*(const u32 *)ptr); case 4: return *(const volatile u32 *)ptr;
case 8: return READ_ONCE(*(const u64 *)ptr); case 8: return *(const volatile u64 *)ptr;
default: return 0; /* Ignore; we do not diff the values. */ default: return 0; /* Ignore; we do not diff the values. */
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment