mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
78f7a3fd6d
The randstruct support released in Clang 15 is unsafe to use due to a
bug that can cause miscompilations: "-frandomize-layout-seed
inconsistently randomizes all-function-pointers structs"
(https://github.com/llvm/llvm-project/issues/60349). It has been fixed
on the Clang 16 release branch, so add a Clang version check.
Fixes: 035f7f87b7
("randstruct: Enable Clang support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
Acked-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Bill Wendling <morbo@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20230208065133.220589-1-ebiggers@kernel.org
359 lines
14 KiB
Plaintext
359 lines
14 KiB
Plaintext
# SPDX-License-Identifier: GPL-2.0-only
|
|
menu "Kernel hardening options"
|
|
|
|
config GCC_PLUGIN_STRUCTLEAK
|
|
bool
|
|
help
|
|
While the kernel is built with warnings enabled for any missed
|
|
stack variable initializations, this warning is silenced for
|
|
anything passed by reference to another function, under the
|
|
occasionally misguided assumption that the function will do
|
|
the initialization. As this regularly leads to exploitable
|
|
flaws, this plugin is available to identify and zero-initialize
|
|
such variables, depending on the chosen level of coverage.
|
|
|
|
This plugin was originally ported from grsecurity/PaX. More
|
|
information at:
|
|
* https://grsecurity.net/
|
|
* https://pax.grsecurity.net/
|
|
|
|
menu "Memory initialization"
|
|
|
|
config CC_HAS_AUTO_VAR_INIT_PATTERN
|
|
def_bool $(cc-option,-ftrivial-auto-var-init=pattern)
|
|
|
|
config CC_HAS_AUTO_VAR_INIT_ZERO_BARE
|
|
def_bool $(cc-option,-ftrivial-auto-var-init=zero)
|
|
|
|
config CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER
|
|
# Clang 16 and later warn about using the -enable flag, but it
|
|
# is required before then.
|
|
def_bool $(cc-option,-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang)
|
|
depends on !CC_HAS_AUTO_VAR_INIT_ZERO_BARE
|
|
|
|
config CC_HAS_AUTO_VAR_INIT_ZERO
|
|
def_bool CC_HAS_AUTO_VAR_INIT_ZERO_BARE || CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER
|
|
|
|
choice
|
|
prompt "Initialize kernel stack variables at function entry"
|
|
default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS
|
|
default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN
|
|
default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_ZERO
|
|
default INIT_STACK_NONE
|
|
help
|
|
This option enables initialization of stack variables at
|
|
function entry time. This has the possibility to have the
|
|
greatest coverage (since all functions can have their
|
|
variables initialized), but the performance impact depends
|
|
on the function calling complexity of a given workload's
|
|
syscalls.
|
|
|
|
This chooses the level of coverage over classes of potentially
|
|
uninitialized variables. The selected class of variable will be
|
|
initialized before use in a function.
|
|
|
|
config INIT_STACK_NONE
|
|
bool "no automatic stack variable initialization (weakest)"
|
|
help
|
|
Disable automatic stack variable initialization.
|
|
This leaves the kernel vulnerable to the standard
|
|
classes of uninitialized stack variable exploits
|
|
and information exposures.
|
|
|
|
config GCC_PLUGIN_STRUCTLEAK_USER
|
|
bool "zero-init structs marked for userspace (weak)"
|
|
# Plugin can be removed once the kernel only supports GCC 12+
|
|
depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO
|
|
select GCC_PLUGIN_STRUCTLEAK
|
|
help
|
|
Zero-initialize any structures on the stack containing
|
|
a __user attribute. This can prevent some classes of
|
|
uninitialized stack variable exploits and information
|
|
exposures, like CVE-2013-2141:
|
|
https://git.kernel.org/linus/b9e146d8eb3b9eca
|
|
|
|
config GCC_PLUGIN_STRUCTLEAK_BYREF
|
|
bool "zero-init structs passed by reference (strong)"
|
|
# Plugin can be removed once the kernel only supports GCC 12+
|
|
depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO
|
|
depends on !(KASAN && KASAN_STACK)
|
|
select GCC_PLUGIN_STRUCTLEAK
|
|
help
|
|
Zero-initialize any structures on the stack that may
|
|
be passed by reference and had not already been
|
|
explicitly initialized. This can prevent most classes
|
|
of uninitialized stack variable exploits and information
|
|
exposures, like CVE-2017-1000410:
|
|
https://git.kernel.org/linus/06e7e776ca4d3654
|
|
|
|
As a side-effect, this keeps a lot of variables on the
|
|
stack that can otherwise be optimized out, so combining
|
|
this with CONFIG_KASAN_STACK can lead to a stack overflow
|
|
and is disallowed.
|
|
|
|
config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
|
|
bool "zero-init everything passed by reference (very strong)"
|
|
# Plugin can be removed once the kernel only supports GCC 12+
|
|
depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO
|
|
depends on !(KASAN && KASAN_STACK)
|
|
select GCC_PLUGIN_STRUCTLEAK
|
|
help
|
|
Zero-initialize any stack variables that may be passed
|
|
by reference and had not already been explicitly
|
|
initialized. This is intended to eliminate all classes
|
|
of uninitialized stack variable exploits and information
|
|
exposures.
|
|
|
|
As a side-effect, this keeps a lot of variables on the
|
|
stack that can otherwise be optimized out, so combining
|
|
this with CONFIG_KASAN_STACK can lead to a stack overflow
|
|
and is disallowed.
|
|
|
|
config INIT_STACK_ALL_PATTERN
|
|
bool "pattern-init everything (strongest)"
|
|
depends on CC_HAS_AUTO_VAR_INIT_PATTERN
|
|
depends on !KMSAN
|
|
help
|
|
Initializes everything on the stack (including padding)
|
|
with a specific debug value. This is intended to eliminate
|
|
all classes of uninitialized stack variable exploits and
|
|
information exposures, even variables that were warned about
|
|
having been left uninitialized.
|
|
|
|
Pattern initialization is known to provoke many existing bugs
|
|
related to uninitialized locals, e.g. pointers receive
|
|
non-NULL values, buffer sizes and indices are very big. The
|
|
pattern is situation-specific; Clang on 64-bit uses 0xAA
|
|
repeating for all types and padding except float and double
|
|
which use 0xFF repeating (-NaN). Clang on 32-bit uses 0xFF
|
|
repeating for all types and padding.
|
|
|
|
config INIT_STACK_ALL_ZERO
|
|
bool "zero-init everything (strongest and safest)"
|
|
depends on CC_HAS_AUTO_VAR_INIT_ZERO
|
|
depends on !KMSAN
|
|
help
|
|
Initializes everything on the stack (including padding)
|
|
with a zero value. This is intended to eliminate all
|
|
classes of uninitialized stack variable exploits and
|
|
information exposures, even variables that were warned
|
|
about having been left uninitialized.
|
|
|
|
Zero initialization provides safe defaults for strings
|
|
(immediately NUL-terminated), pointers (NULL), indices
|
|
(index 0), and sizes (0 length), so it is therefore more
|
|
suitable as a production security mitigation than pattern
|
|
initialization.
|
|
|
|
endchoice
|
|
|
|
config GCC_PLUGIN_STRUCTLEAK_VERBOSE
|
|
bool "Report forcefully initialized variables"
|
|
depends on GCC_PLUGIN_STRUCTLEAK
|
|
depends on !COMPILE_TEST # too noisy
|
|
help
|
|
This option will cause a warning to be printed each time the
|
|
structleak plugin finds a variable it thinks needs to be
|
|
initialized. Since not all existing initializers are detected
|
|
by the plugin, this can produce false positive warnings.
|
|
|
|
config GCC_PLUGIN_STACKLEAK
|
|
bool "Poison kernel stack before returning from syscalls"
|
|
depends on GCC_PLUGINS
|
|
depends on HAVE_ARCH_STACKLEAK
|
|
help
|
|
This option makes the kernel erase the kernel stack before
|
|
returning from system calls. This has the effect of leaving
|
|
the stack initialized to the poison value, which both reduces
|
|
the lifetime of any sensitive stack contents and reduces
|
|
potential for uninitialized stack variable exploits or information
|
|
exposures (it does not cover functions reaching the same stack
|
|
depth as prior functions during the same syscall). This blocks
|
|
most uninitialized stack variable attacks, with the performance
|
|
impact being driven by the depth of the stack usage, rather than
|
|
the function calling complexity.
|
|
|
|
The performance impact on a single CPU system kernel compilation
|
|
sees a 1% slowdown, other systems and workloads may vary and you
|
|
are advised to test this feature on your expected workload before
|
|
deploying it.
|
|
|
|
This plugin was ported from grsecurity/PaX. More information at:
|
|
* https://grsecurity.net/
|
|
* https://pax.grsecurity.net/
|
|
|
|
config GCC_PLUGIN_STACKLEAK_VERBOSE
|
|
bool "Report stack depth analysis instrumentation" if EXPERT
|
|
depends on GCC_PLUGIN_STACKLEAK
|
|
depends on !COMPILE_TEST # too noisy
|
|
help
|
|
This option will cause a warning to be printed each time the
|
|
stackleak plugin finds a function it thinks needs to be
|
|
instrumented. This is useful for comparing coverage between
|
|
builds.
|
|
|
|
config STACKLEAK_TRACK_MIN_SIZE
|
|
int "Minimum stack frame size of functions tracked by STACKLEAK"
|
|
default 100
|
|
range 0 4096
|
|
depends on GCC_PLUGIN_STACKLEAK
|
|
help
|
|
The STACKLEAK gcc plugin instruments the kernel code for tracking
|
|
the lowest border of the kernel stack (and for some other purposes).
|
|
It inserts the stackleak_track_stack() call for the functions with
|
|
a stack frame size greater than or equal to this parameter.
|
|
If unsure, leave the default value 100.
|
|
|
|
config STACKLEAK_METRICS
|
|
bool "Show STACKLEAK metrics in the /proc file system"
|
|
depends on GCC_PLUGIN_STACKLEAK
|
|
depends on PROC_FS
|
|
help
|
|
If this is set, STACKLEAK metrics for every task are available in
|
|
the /proc file system. In particular, /proc/<pid>/stack_depth
|
|
shows the maximum kernel stack consumption for the current and
|
|
previous syscalls. Although this information is not precise, it
|
|
can be useful for estimating the STACKLEAK performance impact for
|
|
your workloads.
|
|
|
|
config STACKLEAK_RUNTIME_DISABLE
|
|
bool "Allow runtime disabling of kernel stack erasing"
|
|
depends on GCC_PLUGIN_STACKLEAK
|
|
help
|
|
This option provides 'stack_erasing' sysctl, which can be used in
|
|
runtime to control kernel stack erasing for kernels built with
|
|
CONFIG_GCC_PLUGIN_STACKLEAK.
|
|
|
|
config INIT_ON_ALLOC_DEFAULT_ON
|
|
bool "Enable heap memory zeroing on allocation by default"
|
|
depends on !KMSAN
|
|
help
|
|
This has the effect of setting "init_on_alloc=1" on the kernel
|
|
command line. This can be disabled with "init_on_alloc=0".
|
|
When "init_on_alloc" is enabled, all page allocator and slab
|
|
allocator memory will be zeroed when allocated, eliminating
|
|
many kinds of "uninitialized heap memory" flaws, especially
|
|
heap content exposures. The performance impact varies by
|
|
workload, but most cases see <1% impact. Some synthetic
|
|
workloads have measured as high as 7%.
|
|
|
|
config INIT_ON_FREE_DEFAULT_ON
|
|
bool "Enable heap memory zeroing on free by default"
|
|
depends on !KMSAN
|
|
help
|
|
This has the effect of setting "init_on_free=1" on the kernel
|
|
command line. This can be disabled with "init_on_free=0".
|
|
Similar to "init_on_alloc", when "init_on_free" is enabled,
|
|
all page allocator and slab allocator memory will be zeroed
|
|
when freed, eliminating many kinds of "uninitialized heap memory"
|
|
flaws, especially heap content exposures. The primary difference
|
|
with "init_on_free" is that data lifetime in memory is reduced,
|
|
as anything freed is wiped immediately, making live forensics or
|
|
cold boot memory attacks unable to recover freed memory contents.
|
|
The performance impact varies by workload, but is more expensive
|
|
than "init_on_alloc" due to the negative cache effects of
|
|
touching "cold" memory areas. Most cases see 3-5% impact. Some
|
|
synthetic workloads have measured as high as 8%.
|
|
|
|
config CC_HAS_ZERO_CALL_USED_REGS
|
|
def_bool $(cc-option,-fzero-call-used-regs=used-gpr)
|
|
# https://github.com/ClangBuiltLinux/linux/issues/1766
|
|
# https://github.com/llvm/llvm-project/issues/59242
|
|
depends on !CC_IS_CLANG || CLANG_VERSION > 150006
|
|
|
|
config ZERO_CALL_USED_REGS
|
|
bool "Enable register zeroing on function exit"
|
|
depends on CC_HAS_ZERO_CALL_USED_REGS
|
|
help
|
|
At the end of functions, always zero any caller-used register
|
|
contents. This helps ensure that temporary values are not
|
|
leaked beyond the function boundary. This means that register
|
|
contents are less likely to be available for side channels
|
|
and information exposures. Additionally, this helps reduce the
|
|
number of useful ROP gadgets by about 20% (and removes compiler
|
|
generated "write-what-where" gadgets) in the resulting kernel
|
|
image. This has a less than 1% performance impact on most
|
|
workloads. Image size growth depends on architecture, and should
|
|
be evaluated for suitability. For example, x86_64 grows by less
|
|
than 1%, and arm64 grows by about 5%.
|
|
|
|
endmenu
|
|
|
|
config CC_HAS_RANDSTRUCT
|
|
def_bool $(cc-option,-frandomize-layout-seed-file=/dev/null)
|
|
# Randstruct was first added in Clang 15, but it isn't safe to use until
|
|
# Clang 16 due to https://github.com/llvm/llvm-project/issues/60349
|
|
depends on !CC_IS_CLANG || CLANG_VERSION >= 160000
|
|
|
|
choice
|
|
prompt "Randomize layout of sensitive kernel structures"
|
|
default RANDSTRUCT_FULL if COMPILE_TEST && (GCC_PLUGINS || CC_HAS_RANDSTRUCT)
|
|
default RANDSTRUCT_NONE
|
|
help
|
|
If you enable this, the layouts of structures that are entirely
|
|
function pointers (and have not been manually annotated with
|
|
__no_randomize_layout), or structures that have been explicitly
|
|
marked with __randomize_layout, will be randomized at compile-time.
|
|
This can introduce the requirement of an additional information
|
|
exposure vulnerability for exploits targeting these structure
|
|
types.
|
|
|
|
Enabling this feature will introduce some performance impact,
|
|
slightly increase memory usage, and prevent the use of forensic
|
|
tools like Volatility against the system (unless the kernel
|
|
source tree isn't cleaned after kernel installation).
|
|
|
|
The seed used for compilation is in scripts/basic/randomize.seed.
|
|
It remains after a "make clean" to allow for external modules to
|
|
be compiled with the existing seed and will be removed by a
|
|
"make mrproper" or "make distclean". This file should not be made
|
|
public, or the structure layout can be determined.
|
|
|
|
config RANDSTRUCT_NONE
|
|
bool "Disable structure layout randomization"
|
|
help
|
|
Build normally: no structure layout randomization.
|
|
|
|
config RANDSTRUCT_FULL
|
|
bool "Fully randomize structure layout"
|
|
depends on CC_HAS_RANDSTRUCT || GCC_PLUGINS
|
|
select MODVERSIONS if MODULES
|
|
help
|
|
Fully randomize the member layout of sensitive
|
|
structures as much as possible, which may have both a
|
|
memory size and performance impact.
|
|
|
|
One difference between the Clang and GCC plugin
|
|
implementations is the handling of bitfields. The GCC
|
|
plugin treats them as fully separate variables,
|
|
introducing sometimes significant padding. Clang tries
|
|
to keep adjacent bitfields together, but with their bit
|
|
ordering randomized.
|
|
|
|
config RANDSTRUCT_PERFORMANCE
|
|
bool "Limit randomization of structure layout to cache-lines"
|
|
depends on GCC_PLUGINS
|
|
select MODVERSIONS if MODULES
|
|
help
|
|
Randomization of sensitive kernel structures will make a
|
|
best effort at restricting randomization to cacheline-sized
|
|
groups of members. It will further not randomize bitfields
|
|
in structures. This reduces the performance hit of RANDSTRUCT
|
|
at the cost of weakened randomization.
|
|
endchoice
|
|
|
|
config RANDSTRUCT
|
|
def_bool !RANDSTRUCT_NONE
|
|
|
|
config GCC_PLUGIN_RANDSTRUCT
|
|
def_bool GCC_PLUGINS && RANDSTRUCT
|
|
help
|
|
Use GCC plugin to randomize structure layout.
|
|
|
|
This plugin was ported from grsecurity/PaX. More
|
|
information at:
|
|
* https://grsecurity.net/
|
|
* https://pax.grsecurity.net/
|
|
|
|
endmenu
|