Skip to content

Commit

Permalink
compiler.h: fix barrier_data() on clang
Browse files Browse the repository at this point in the history
Commit 815f0dd ("include/linux/compiler*.h: make compiler-*.h
mutually exclusive") neglected to copy barrier_data() from
compiler-gcc.h into compiler-clang.h.

The definition in compiler-gcc.h was really to work around clang's more
aggressive optimization, so this broke barrier_data() on clang, and
consequently memzero_explicit() as well.

For example, this results in at least the memzero_explicit() call in
lib/crypto/sha256.c:sha256_transform() being optimized away by clang.

Fix this by moving the definition of barrier_data() into compiler.h.

Also move the gcc/clang definition of barrier() into compiler.h,
__memory_barrier() is icc-specific (and barrier() is already defined
using it in compiler-intel.h) and doesn't belong in compiler.h.

[[email protected]: fix ALPHA builds when SMP is not enabled]

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 815f0dd ("include/linux/compiler*.h: make compiler-*.h mutually exclusive")
Signed-off-by: Arvind Sankar <[email protected]>
Signed-off-by: Randy Dunlap <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Tested-by: Nick Desaulniers <[email protected]>
Reviewed-by: Nick Desaulniers <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Cc: <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
nivedita76 authored and torvalds committed Nov 14, 2020
1 parent 96e1fac commit 3347acc
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 27 deletions.
1 change: 1 addition & 0 deletions include/asm-generic/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#ifndef __ASSEMBLY__

#include <linux/compiler.h>
#include <asm/rwonce.h>

#ifndef nop
Expand Down
6 changes: 0 additions & 6 deletions include/linux/compiler-clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif

/* The following are for compatibility with GCC, from compiler-gcc.h,
* and may be redefined here because they should not be shared with other
* compilers, like ICC.
*/
#define barrier() __asm__ __volatile__("" : : : "memory")

#if __has_feature(shadow_call_stack)
# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
#endif
19 changes: 0 additions & 19 deletions include/linux/compiler-gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,6 @@
# error Sorry, your version of GCC is too old - please use 4.9 or newer.
#endif

/* Optimization barrier */

/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
/*
* This version is i.e. to prevent dead stores elimination on @ptr
* where gcc and llvm may behave differently when otherwise using
* normal barrier(): while gcc behavior gets along with a normal
* barrier(), llvm needs an explicit input variable to be assumed
* clobbered. The issue is as follows: while the inline asm might
* access any memory it wants, the compiler could have fit all of
* @ptr into memory registers instead, and since @ptr never escaped
* from that, it proved that the inline asm wasn't touching any of
* it. This version works well with both compilers, i.e. we're telling
* the compiler that the inline asm absolutely may see the contents
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
*/
#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")

/*
* This macro obfuscates arithmetic on a variable address so that gcc
* shouldn't recognize the original var, and make assumptions about it.
Expand Down
18 changes: 16 additions & 2 deletions include/linux/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,

/* Optimization barrier */
#ifndef barrier
# define barrier() __memory_barrier()
/* The "volatile" is due to gcc bugs */
# define barrier() __asm__ __volatile__("": : :"memory")
#endif

#ifndef barrier_data
# define barrier_data(ptr) barrier()
/*
* This version is i.e. to prevent dead stores elimination on @ptr
* where gcc and llvm may behave differently when otherwise using
* normal barrier(): while gcc behavior gets along with a normal
* barrier(), llvm needs an explicit input variable to be assumed
* clobbered. The issue is as follows: while the inline asm might
* access any memory it wants, the compiler could have fit all of
* @ptr into memory registers instead, and since @ptr never escaped
* from that, it proved that the inline asm wasn't touching any of
* it. This version works well with both compilers, i.e. we're telling
* the compiler that the inline asm absolutely may see the contents
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
*/
# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
#endif

/* workaround for GCC PR82365 if needed */
Expand Down

0 comments on commit 3347acc

Please sign in to comment.