Commit 2d47c695 authored by Kees Cook's avatar Kees Cook

ubsan: Tighten UBSAN_BOUNDS on GCC

The use of -fsanitize=bounds on GCC will ignore some trailing arrays,
leaving a gap in coverage. Switch to using -fsanitize=bounds-strict to
match Clang's stricter behavior.

Cc: Marco Elver <elver@google.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Nicolas Schier <nicolas@fjasle.eu>
Cc: Tom Rix <trix@redhat.com>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Miroslav Benes <mbenes@suse.cz>
Cc: linux-kbuild@vger.kernel.org
Cc: llvm@lists.linux.dev
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20230405022356.gonna.338-kees@kernel.org
parent f1fcbaa1
...@@ -27,16 +27,29 @@ config UBSAN_TRAP ...@@ -27,16 +27,29 @@ config UBSAN_TRAP
the system. For some system builders this is an acceptable the system. For some system builders this is an acceptable
trade-off. trade-off.
config CC_HAS_UBSAN_BOUNDS config CC_HAS_UBSAN_BOUNDS_STRICT
def_bool $(cc-option,-fsanitize=bounds) def_bool $(cc-option,-fsanitize=bounds-strict)
help
The -fsanitize=bounds-strict option is only available on GCC,
but uses the more strict handling of arrays that includes knowledge
of flexible arrays, which is comparable to Clang's regular
-fsanitize=bounds.
config CC_HAS_UBSAN_ARRAY_BOUNDS config CC_HAS_UBSAN_ARRAY_BOUNDS
def_bool $(cc-option,-fsanitize=array-bounds) def_bool $(cc-option,-fsanitize=array-bounds)
help
Under Clang, the -fsanitize=bounds option is actually composed
of two more specific options, -fsanitize=array-bounds and
-fsanitize=local-bounds. However, -fsanitize=local-bounds can
only be used when trap mode is enabled. (See also the help for
CONFIG_LOCAL_BOUNDS.) Explicitly check for -fsanitize=array-bounds
so that we can build up the options needed for UBSAN_BOUNDS
with or without UBSAN_TRAP.
config UBSAN_BOUNDS config UBSAN_BOUNDS
bool "Perform array index bounds checking" bool "Perform array index bounds checking"
default UBSAN default UBSAN
depends on CC_HAS_UBSAN_ARRAY_BOUNDS || CC_HAS_UBSAN_BOUNDS depends on CC_HAS_UBSAN_ARRAY_BOUNDS || CC_HAS_UBSAN_BOUNDS_STRICT
help help
This option enables detection of directly indexed out of bounds This option enables detection of directly indexed out of bounds
array accesses, where the array size is known at compile time. array accesses, where the array size is known at compile time.
...@@ -44,33 +57,26 @@ config UBSAN_BOUNDS ...@@ -44,33 +57,26 @@ config UBSAN_BOUNDS
to the {str,mem}*cpy() family of functions (that is addressed to the {str,mem}*cpy() family of functions (that is addressed
by CONFIG_FORTIFY_SOURCE). by CONFIG_FORTIFY_SOURCE).
config UBSAN_ONLY_BOUNDS config UBSAN_BOUNDS_STRICT
def_bool CC_HAS_UBSAN_BOUNDS && !CC_HAS_UBSAN_ARRAY_BOUNDS def_bool UBSAN_BOUNDS && CC_HAS_UBSAN_BOUNDS_STRICT
depends on UBSAN_BOUNDS
help help
This is a weird case: Clang's -fsanitize=bounds includes GCC's bounds sanitizer. This option is used to select the
-fsanitize=local-bounds, but it's trapping-only, so for correct options in Makefile.ubsan.
Clang, we must use -fsanitize=array-bounds when we want
traditional array bounds checking enabled. For GCC, we
want -fsanitize=bounds.
config UBSAN_ARRAY_BOUNDS config UBSAN_ARRAY_BOUNDS
def_bool CC_HAS_UBSAN_ARRAY_BOUNDS def_bool UBSAN_BOUNDS && CC_HAS_UBSAN_ARRAY_BOUNDS
depends on UBSAN_BOUNDS help
Clang's array bounds sanitizer. This option is used to select
the correct options in Makefile.ubsan.
config UBSAN_LOCAL_BOUNDS config UBSAN_LOCAL_BOUNDS
bool "Perform array local bounds checking" def_bool UBSAN_ARRAY_BOUNDS && UBSAN_TRAP
depends on UBSAN_TRAP help
depends on $(cc-option,-fsanitize=local-bounds) This option enables Clang's -fsanitize=local-bounds which traps
help when an access through a pointer that is derived from an object
This option enables -fsanitize=local-bounds which traps when an of a statically-known size, where an added offset (which may not
exception/error is detected. Therefore, it may only be enabled be known statically) is out-of-bounds. Since this option is
with CONFIG_UBSAN_TRAP. trap-only, it depends on CONFIG_UBSAN_TRAP.
Enabling this option detects errors due to accesses through a
pointer that is derived from an object of a statically-known size,
where an added offset (which may not be known statically) is
out-of-bounds.
config UBSAN_SHIFT config UBSAN_SHIFT
bool "Perform checking for bit-shift overflows" bool "Perform checking for bit-shift overflows"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Enable available and selected UBSAN features. # Enable available and selected UBSAN features.
ubsan-cflags-$(CONFIG_UBSAN_ALIGNMENT) += -fsanitize=alignment ubsan-cflags-$(CONFIG_UBSAN_ALIGNMENT) += -fsanitize=alignment
ubsan-cflags-$(CONFIG_UBSAN_ONLY_BOUNDS) += -fsanitize=bounds ubsan-cflags-$(CONFIG_UBSAN_BOUNDS_STRICT) += -fsanitize=bounds-strict
ubsan-cflags-$(CONFIG_UBSAN_ARRAY_BOUNDS) += -fsanitize=array-bounds ubsan-cflags-$(CONFIG_UBSAN_ARRAY_BOUNDS) += -fsanitize=array-bounds
ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds
ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment