Skip to content

Commit

Permalink
ubsan: Tighten UBSAN_BOUNDS on GCC
Browse files Browse the repository at this point in the history
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: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20230405022356.gonna.338-kees@kernel.org
  • Loading branch information
Kees Cook committed May 16, 2023
1 parent f1fcbaa commit 2d47c69
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 26 deletions.
56 changes: 31 additions & 25 deletions lib/Kconfig.ubsan
Original file line number Diff line number Diff line change
Expand Up @@ -27,50 +27,56 @@ config UBSAN_TRAP
the system. For some system builders this is an acceptable
trade-off.

config CC_HAS_UBSAN_BOUNDS
def_bool $(cc-option,-fsanitize=bounds)
config CC_HAS_UBSAN_BOUNDS_STRICT
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
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
bool "Perform array index bounds checking"
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
This option enables detection of directly indexed out of bounds
array accesses, where the array size is known at compile time.
Note that this does not protect array overflows via bad calls
to the {str,mem}*cpy() family of functions (that is addressed
by CONFIG_FORTIFY_SOURCE).

config UBSAN_ONLY_BOUNDS
def_bool CC_HAS_UBSAN_BOUNDS && !CC_HAS_UBSAN_ARRAY_BOUNDS
depends on UBSAN_BOUNDS
config UBSAN_BOUNDS_STRICT
def_bool UBSAN_BOUNDS && CC_HAS_UBSAN_BOUNDS_STRICT
help
This is a weird case: Clang's -fsanitize=bounds includes
-fsanitize=local-bounds, but it's trapping-only, so for
Clang, we must use -fsanitize=array-bounds when we want
traditional array bounds checking enabled. For GCC, we
want -fsanitize=bounds.
GCC's bounds sanitizer. This option is used to select the
correct options in Makefile.ubsan.

config UBSAN_ARRAY_BOUNDS
def_bool CC_HAS_UBSAN_ARRAY_BOUNDS
depends on UBSAN_BOUNDS
def_bool UBSAN_BOUNDS && CC_HAS_UBSAN_ARRAY_BOUNDS
help
Clang's array bounds sanitizer. This option is used to select
the correct options in Makefile.ubsan.

config UBSAN_LOCAL_BOUNDS
bool "Perform array local bounds checking"
depends on UBSAN_TRAP
depends on $(cc-option,-fsanitize=local-bounds)
help
This option enables -fsanitize=local-bounds which traps when an
exception/error is detected. Therefore, it may only be enabled
with 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.
def_bool UBSAN_ARRAY_BOUNDS && UBSAN_TRAP
help
This option enables Clang's -fsanitize=local-bounds which traps
when an access 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. Since this option is
trap-only, it depends on CONFIG_UBSAN_TRAP.

config UBSAN_SHIFT
bool "Perform checking for bit-shift overflows"
Expand Down
2 changes: 1 addition & 1 deletion scripts/Makefile.ubsan
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Enable available and selected UBSAN features.
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_LOCAL_BOUNDS) += -fsanitize=local-bounds
ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
Expand Down

0 comments on commit 2d47c69

Please sign in to comment.