mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 22:54:01 +00:00
kcsan: Instrument memcpy/memset/memmove with newer Clang
commit 7c201739be
upstream.
With Clang version 16+, -fsanitize=thread will turn
memcpy/memset/memmove calls in instrumented functions into
__tsan_memcpy/__tsan_memset/__tsan_memmove calls respectively.
Add these functions to the core KCSAN runtime, so that we (a) catch data
races with mem* functions, and (b) won't run into linker errors with
such newer compilers.
Cc: stable@vger.kernel.org # v5.10+
Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
[ elver@google.com: adjust check_access() call for v5.15 and earlier. ]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2cd6026e25
commit
7b3631a2e1
1 changed files with 50 additions and 0 deletions
|
@ -9,10 +9,12 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "atomic.h"
|
||||
|
@ -1045,3 +1047,51 @@ EXPORT_SYMBOL(__tsan_atomic_thread_fence);
|
|||
void __tsan_atomic_signal_fence(int memorder);
|
||||
void __tsan_atomic_signal_fence(int memorder) { }
|
||||
EXPORT_SYMBOL(__tsan_atomic_signal_fence);
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMSET
|
||||
void *__tsan_memset(void *s, int c, size_t count);
|
||||
noinline void *__tsan_memset(void *s, int c, size_t count)
|
||||
{
|
||||
/*
|
||||
* Instead of not setting up watchpoints where accessed size is greater
|
||||
* than MAX_ENCODABLE_SIZE, truncate checked size to MAX_ENCODABLE_SIZE.
|
||||
*/
|
||||
size_t check_len = min_t(size_t, count, MAX_ENCODABLE_SIZE);
|
||||
|
||||
check_access(s, check_len, KCSAN_ACCESS_WRITE);
|
||||
return memset(s, c, count);
|
||||
}
|
||||
#else
|
||||
void *__tsan_memset(void *s, int c, size_t count) __alias(memset);
|
||||
#endif
|
||||
EXPORT_SYMBOL(__tsan_memset);
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMMOVE
|
||||
void *__tsan_memmove(void *dst, const void *src, size_t len);
|
||||
noinline void *__tsan_memmove(void *dst, const void *src, size_t len)
|
||||
{
|
||||
size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE);
|
||||
|
||||
check_access(dst, check_len, KCSAN_ACCESS_WRITE);
|
||||
check_access(src, check_len, 0);
|
||||
return memmove(dst, src, len);
|
||||
}
|
||||
#else
|
||||
void *__tsan_memmove(void *dst, const void *src, size_t len) __alias(memmove);
|
||||
#endif
|
||||
EXPORT_SYMBOL(__tsan_memmove);
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMCPY
|
||||
void *__tsan_memcpy(void *dst, const void *src, size_t len);
|
||||
noinline void *__tsan_memcpy(void *dst, const void *src, size_t len)
|
||||
{
|
||||
size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE);
|
||||
|
||||
check_access(dst, check_len, KCSAN_ACCESS_WRITE);
|
||||
check_access(src, check_len, 0);
|
||||
return memcpy(dst, src, len);
|
||||
}
|
||||
#else
|
||||
void *__tsan_memcpy(void *dst, const void *src, size_t len) __alias(memcpy);
|
||||
#endif
|
||||
EXPORT_SYMBOL(__tsan_memcpy);
|
||||
|
|
Loading…
Reference in a new issue