kcsan: Instrument memcpy/memset/memmove with newer Clang
commit 7c201739beef1a586d806463f1465429cdce34c5 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
@ -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…
x
Reference in New Issue
Block a user