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 @@
/**
* 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)
{
......@@ -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)
{
......@@ -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)
{
......@@ -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)
{
......@@ -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)
{
......@@ -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)
{
......@@ -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)
......@@ -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)
......@@ -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,
......@@ -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) \
({ \
......@@ -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) \
({ \
......
......@@ -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. */
}
}
......
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