diff options
author | Kees Cook <keescook@chromium.org> | 2024-02-15 14:53:33 -0800 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2024-03-19 23:50:17 -0700 |
commit | 08baa5a3cbf184794670a8645fadd7dc5584f395 (patch) | |
tree | 76bb3cc1dc58b98ac0c3fadecec8d62e960dc73f | |
parent | 0a7b0acecea273c8816f4f5b0e189989470404cf (diff) | |
download | linux-dev/v6.9-mw1/enable-unsigned-sanitizer.tar.gz |
ubsan: Reintroduce unsigned overflow sanitizerdev/v6.9-mw1/enable-unsigned-sanitizer
In order to mitigate unexpected unsigned wrap-around[1], bring back the
unsigned integer overflow sanitizer. It was removed in commit 6aaa31aeb9cf
("ubsan: remove overflow checks") because it was not being used due to
how noisy it was in the kernel currently.
Compilers are adjusting their sanitizers to trap wrap-around and to
detecting common code patterns that should not be instrumented
(e.g. "var + offset < var"). Prepare for this and explicitly rename
the option from "OVERFLOW" to "WRAP".
To annotate intentional wrap-around arithmetic, the add/sub/mul_wrap()
helpers can be used for individual statements. At the function level,
the __unsigned_wrap attribute can be used to mark an entire function as
expecting its signed arithmetic to wrap around. For a single object file
the Makefile can use "UBSAN_UNSIGNED_WRAP_target.o := n" to mark it as
wrapping, and for an entire directory, "UBSAN_UNSIGNED_WRAP := n" can be
used.
Additionally keep these disabled under CONFIG_COMPILE_TEST for now.
Link: https://github.com/KSPP/linux/issues/27 [1]
Signed-off-by: Kees Cook <keescook@chromium.org>
---
Cc: Justin Stitt <justinstitt@google.com>
Cc: Marco Elver <elver@google.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Hao Luo <haoluo@google.com>
Cc: Marco Elver <elver@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nicolas Schier <nicolas@fjasle.eu>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Hao Luo <haoluo@google.com>
Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Cc: kasan-dev@googlegroups.com
Cc: linux-hardening@vger.kernel.org
Cc: linux-kbuild@vger.kernel.org
-rw-r--r-- | include/linux/compiler_types.h | 7 | ||||
-rw-r--r-- | lib/Kconfig.ubsan | 11 | ||||
-rw-r--r-- | scripts/Makefile.lib | 3 | ||||
-rw-r--r-- | scripts/Makefile.ubsan | 3 |
4 files changed, 23 insertions, 1 deletions
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 3e64ec0f7ac80b..4f0b6520a5122a 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -288,12 +288,17 @@ struct ftrace_likely_data { #else # define __signed_wrap #endif +#ifdef CONFIG_UBSAN_UNSIGNED_WRAP +# define __unsigned_wrap __attribute__((no_sanitize("unsigned-integer-overflow"))) +#else +# define __unsigned_wrap +#endif /* Section for code which can't be instrumented at all */ #define __noinstr_section(section) \ noinline notrace __attribute((__section__(section))) \ __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \ - __no_sanitize_memory __signed_wrap + __no_sanitize_memory __signed_wrap __unsigned_wrap #define noinstr __noinstr_section(".noinstr.text") diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 48a67058f84eba..5f3f142634240e 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -129,6 +129,17 @@ config UBSAN_SIGNED_WRAP sanitizer versions will allow for wrap-around checking (rather than exclusively undefined behavior). +config UBSAN_UNSIGNED_WRAP + bool "Perform checking for unsigned arithmetic wrap-around" + depends on !COMPILE_TEST + depends on $(cc-option,-fsanitize=unsigned-integer-overflow) + help + This option enables -fsanitize=unsigned-integer-overflow which checks + for wrap-around of any arithmetic operations with unsigned integers. + This is currently extremely noisy, as unsigned types have long been + expected to wrap around on overflow, and many places in the kernel + depend on this behavior. + config UBSAN_BOOL bool "Perform checking for non-boolean values used as boolean" default UBSAN diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 1bd59b8db05f0b..cdab49b7aca374 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -180,6 +180,9 @@ _c_flags += $(if $(patsubst n%,, \ _c_flags += $(if $(patsubst n%,, \ $(UBSAN_SIGNED_WRAP_$(basetarget).o)$(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SIGNED_WRAP)$(UBSAN_SANITIZE)y), \ $(CFLAGS_UBSAN_SIGNED_WRAP)) +_c_flags += $(if $(patsubst n%,, \ + $(UBSAN_UNSIGNED_WRAP_$(basetarget).o)$(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_UNSIGNED_WRAP)$(UBSAN_SANITIZE)y), \ + $(CFLAGS_UBSAN_UNSIGNED_WRAP)) endif ifeq ($(CONFIG_KCOV),y) diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index b2d3b273b8028c..4cdadb31ac80de 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -16,3 +16,6 @@ export CFLAGS_UBSAN := $(ubsan-cflags-y) ubsan-signed-wrap-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow export CFLAGS_UBSAN_SIGNED_WRAP := $(ubsan-signed-wrap-cflags-y) + +ubsan-unsigned-wrap-cflags-$(CONFIG_UBSAN_UNSIGNED_WRAP) += -fsanitize=unsigned-integer-overflow +export CFLAGS_UBSAN_UNSIGNED_WRAP := $(ubsan-unsigned-wrap-cflags-y) |