From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754017AbbJPJrS (ORCPT ); Fri, 16 Oct 2015 05:47:18 -0400 Received: from mx2.parallels.com ([199.115.105.18]:41617 "EHLO mx2.parallels.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752034AbbJPJrP (ORCPT ); Fri, 16 Oct 2015 05:47:15 -0400 From: Andrey Ryabinin To: CC: Andrey Ryabinin , Ingo Molnar , Thomas Gleixner , "H. Peter Anvin" , , Andrew Morton , Andy Lutomirski , Andrey Konovalov , Kostya Serebryany , Alexander Potapenko , kasan-dev , Borislav Petkov , Denys Vlasenko , Andi Kleen , Dmitry Vyukov , Sasha Levin , Wolfram Gloger , "Paul E. McKenney" , Peter Zijlstra Subject: [PATCH v4 1/2] compiler, atomics: Provide READ_ONCE_NOKSAN() Date: Fri, 16 Oct 2015 12:44:53 +0300 Message-ID: <1444988694-26043-2-git-send-email-aryabinin@virtuozzo.com> X-Mailer: git-send-email 2.4.9 In-Reply-To: <1444988694-26043-1-git-send-email-aryabinin@virtuozzo.com> References: <1444739750-29241-1-git-send-email-aryabinin@virtuozzo.com> <1444988694-26043-1-git-send-email-aryabinin@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-ClientProxiedBy: US-EXCH.sw.swsoft.com (10.255.249.47) To US-EXCH.sw.swsoft.com (10.255.249.47) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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_NOKSAN() macro. KASAN will not check the memory accessed by READ_ONCE_NOKSAN(). The KernelThreadSanitizer (KTSAN) is going to ignore it as well. This patch creates __read_once_size_noksan() a clone of __read_once_size(). The only difference between them is 'no_sanitized_address' attribute appended to '*_nokasan' 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_NOKSAN() is just a clone of READ_ONCE(). Signed-off-by: Andrey Ryabinin --- include/linux/compiler-gcc.h | 13 +++++++++ include/linux/compiler.h | 66 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index dfaa7b3..8efb40e 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -237,12 +237,25 @@ #define KASAN_ABI_VERSION 3 #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 */ #if !defined(__noclone) #define __noclone /* not needed */ #endif +#if !defined(__no_sanitize_address) +#define __no_sanitize_address +#endif + /* * A trick to suppress uninitialized variable warning without generating any * code diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c836eb2..dfa172f7 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -198,19 +198,45 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #include -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) { - 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(); - } + __READ_ONCE_SIZE; +} + +#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_noksan(const volatile void *p, void *res, int size) +{ + __READ_ONCE_SIZE; +} +#else +static __always_inline +void __read_once_size_noksan(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) { @@ -248,8 +274,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s * required ordering. */ -#define READ_ONCE(x) \ - ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) +#define __READ_ONCE(x, noksan) \ +({ \ + union { typeof(x) __val; char __c[1]; } __u; \ + if (noksan) \ + __read_once_size_noksan(&(x), __u.__c, sizeof(x)); \ + else \ + __read_once_size(&(x), __u.__c, sizeof(x)); \ + __u.__val; \ +}) +#define READ_ONCE(x) __READ_ONCE(x, 0) + +/* + * Use READ_ONCE_NOKSAN() instead of READ_ONCE() if you need + * to hide memory access from KASAN. + */ +#define READ_ONCE_NOKSAN(x) __READ_ONCE(x, 1) #define WRITE_ONCE(x, val) \ ({ \ -- 2.4.9