mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
compiler, atomics, kasan: Provide READ_ONCE_NOCHECK()
Some code may perform racy by design memory reads. This could be harmless, yet such code may produce KASAN warnings. To hide such accesses from KASAN this patch introduces READ_ONCE_NOCHECK() macro. KASAN will not check the memory accessed by READ_ONCE_NOCHECK(). The KernelThreadSanitizer (KTSAN) is going to ignore it as well. This patch creates __read_once_size_nocheck() a clone of __read_once_size(). The only difference between them is 'no_sanitized_address' attribute appended to '*_nocheck' function. This attribute tells the compiler that instrumentation of memory accesses should not be applied to that function. We declare it as static '__maybe_unsed' because GCC is not capable to inline such function: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 With KASAN=n READ_ONCE_NOCHECK() is just a clone of READ_ONCE(). Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Alexander Potapenko <glider@google.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andrey Konovalov <andreyknvl@google.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Kostya Serebryany <kcc@google.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Wolfram Gloger <wmglo@dent.med.uni-muenchen.de> Cc: kasan-dev <kasan-dev@googlegroups.com> Link: http://lkml.kernel.org/r/1445243838-17763-2-git-send-email-aryabinin@virtuozzo.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
a75ca545e8
commit
d976441f44
2 changed files with 66 additions and 13 deletions
|
@ -237,12 +237,25 @@
|
||||||
#define KASAN_ABI_VERSION 3
|
#define KASAN_ABI_VERSION 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GCC_VERSION >= 40902
|
||||||
|
/*
|
||||||
|
* Tell the compiler that address safety instrumentation (KASAN)
|
||||||
|
* should not be applied to that function.
|
||||||
|
* Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
|
||||||
|
*/
|
||||||
|
#define __no_sanitize_address __attribute__((no_sanitize_address))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* gcc version >= 40000 specific checks */
|
#endif /* gcc version >= 40000 specific checks */
|
||||||
|
|
||||||
#if !defined(__noclone)
|
#if !defined(__noclone)
|
||||||
#define __noclone /* not needed */
|
#define __noclone /* not needed */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__no_sanitize_address)
|
||||||
|
#define __no_sanitize_address
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A trick to suppress uninitialized variable warning without generating any
|
* A trick to suppress uninitialized variable warning without generating any
|
||||||
* code
|
* code
|
||||||
|
|
|
@ -198,20 +198,46 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
|
||||||
|
|
||||||
#include <uapi/linux/types.h>
|
#include <uapi/linux/types.h>
|
||||||
|
|
||||||
static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
|
#define __READ_ONCE_SIZE \
|
||||||
|
({ \
|
||||||
|
switch (size) { \
|
||||||
|
case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \
|
||||||
|
case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \
|
||||||
|
case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \
|
||||||
|
case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \
|
||||||
|
default: \
|
||||||
|
barrier(); \
|
||||||
|
__builtin_memcpy((void *)res, (const void *)p, size); \
|
||||||
|
barrier(); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
static __always_inline
|
||||||
|
void __read_once_size(const volatile void *p, void *res, int size)
|
||||||
{
|
{
|
||||||
switch (size) {
|
__READ_ONCE_SIZE;
|
||||||
case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
|
|
||||||
case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
|
|
||||||
case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
|
|
||||||
case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
|
|
||||||
default:
|
|
||||||
barrier();
|
|
||||||
__builtin_memcpy((void *)res, (const void *)p, size);
|
|
||||||
barrier();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KASAN
|
||||||
|
/*
|
||||||
|
* This function is not 'inline' because __no_sanitize_address confilcts
|
||||||
|
* with inlining. Attempt to inline it may cause a build failure.
|
||||||
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
|
||||||
|
* '__maybe_unused' allows us to avoid defined-but-not-used warnings.
|
||||||
|
*/
|
||||||
|
static __no_sanitize_address __maybe_unused
|
||||||
|
void __read_once_size_nocheck(const volatile void *p, void *res, int size)
|
||||||
|
{
|
||||||
|
__READ_ONCE_SIZE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static __always_inline
|
||||||
|
void __read_once_size_nocheck(const volatile void *p, void *res, int size)
|
||||||
|
{
|
||||||
|
__READ_ONCE_SIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static __always_inline void __write_once_size(volatile void *p, void *res, int size)
|
static __always_inline void __write_once_size(volatile void *p, void *res, int size)
|
||||||
{
|
{
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
@ -248,8 +274,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
|
||||||
* required ordering.
|
* required ordering.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define READ_ONCE(x) \
|
#define __READ_ONCE(x, check) \
|
||||||
({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
|
({ \
|
||||||
|
union { typeof(x) __val; char __c[1]; } __u; \
|
||||||
|
if (check) \
|
||||||
|
__read_once_size(&(x), __u.__c, sizeof(x)); \
|
||||||
|
else \
|
||||||
|
__read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
|
||||||
|
__u.__val; \
|
||||||
|
})
|
||||||
|
#define READ_ONCE(x) __READ_ONCE(x, 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
|
||||||
|
* to hide memory access from KASAN.
|
||||||
|
*/
|
||||||
|
#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
|
||||||
|
|
||||||
#define WRITE_ONCE(x, val) \
|
#define WRITE_ONCE(x, val) \
|
||||||
({ \
|
({ \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue