diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index d8d4d6557b80..05147112b355 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -36,10 +36,17 @@ config UBSAN_KCOV_BROKEN See https://bugs.llvm.org/show_bug.cgi?id=45831 for the status in newer releases. +config CC_HAS_UBSAN_BOUNDS + def_bool $(cc-option,-fsanitize=bounds) + +config CC_HAS_UBSAN_ARRAY_BOUNDS + def_bool $(cc-option,-fsanitize=array-bounds) + config UBSAN_BOUNDS bool "Perform array index bounds checking" default UBSAN depends on !UBSAN_KCOV_BROKEN + depends on CC_HAS_UBSAN_ARRAY_BOUNDS || CC_HAS_UBSAN_BOUNDS help This option enables detection of directly indexed out of bounds array accesses, where the array size is known at compile time. @@ -47,15 +54,30 @@ config UBSAN_BOUNDS 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 + 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. + +config UBSAN_ARRAY_BOUNDS + def_bool CC_HAS_UBSAN_ARRAY_BOUNDS + depends on UBSAN_BOUNDS + config UBSAN_LOCAL_BOUNDS bool "Perform array local bounds checking" depends on UBSAN_TRAP - depends on CC_IS_CLANG depends on !UBSAN_KCOV_BROKEN + depends on $(cc-option,-fsanitize=local-bounds) help This option enables -fsanitize=local-bounds which traps when an - exception/error is detected. Therefore, it should be enabled only - if trapping is expected. + 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 @@ -69,6 +91,38 @@ config UBSAN_MISC own Kconfig options. Disable this if you only want to have individually selected checks. +config UBSAN_SHIFT + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=shift) + +config UBSAN_DIV_ZERO + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=integer-divide-by-zero) + +config UBSAN_UNREACHABLE + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=unreachable) + +config UBSAN_SIGNED_OVERFLOW + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=signed-integer-overflow) + +config UBSAN_UNSIGNED_OVERFLOW + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=unsigned-integer-overflow) + +config UBSAN_OBJECT_SIZE + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=object-size) + +config UBSAN_BOOL + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=bool) + +config UBSAN_ENUM + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=enum) + config UBSAN_SANITIZE_ALL bool "Enable instrumentation for the entire kernel" depends on ARCH_HAS_UBSAN_SANITIZE_ALL @@ -85,6 +139,7 @@ config UBSAN_ALIGNMENT bool "Enable checks for pointers alignment" default !HAVE_EFFICIENT_UNALIGNED_ACCESS depends on !UBSAN_TRAP + depends on $(cc-option,-fsanitize=alignment) help This option enables the check of unaligned memory accesses. Enabling this option on architectures that support unaligned diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index c18fecc53605..0e53a93e8f15 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -1,33 +1,18 @@ # SPDX-License-Identifier: GPL-2.0 -export CFLAGS_UBSAN := +# 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_ARRAY_BOUNDS) += -fsanitize=array-bounds +ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds +ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift +ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero +ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable +ubsan-cflags-$(CONFIG_UBSAN_SIGNED_OVERFLOW) += -fsanitize=signed-integer-overflow +ubsan-cflags-$(CONFIG_UBSAN_UNSIGNED_OVERFLOW) += -fsanitize=unsigned-integer-overflow +ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size +ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool +ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum +ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error -ifdef CONFIG_UBSAN_ALIGNMENT - CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) -endif - -ifdef CONFIG_UBSAN_BOUNDS - ifdef CONFIG_CC_IS_CLANG - CFLAGS_UBSAN += -fsanitize=array-bounds - else - CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) - endif -endif - -ifdef CONFIG_UBSAN_LOCAL_BOUNDS - CFLAGS_UBSAN += -fsanitize=local-bounds -endif - -ifdef CONFIG_UBSAN_MISC - CFLAGS_UBSAN += $(call cc-option, -fsanitize=shift) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=bool) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=enum) -endif - -ifdef CONFIG_UBSAN_TRAP - CFLAGS_UBSAN += $(call cc-option, -fsanitize-undefined-trap-on-error) -endif +export CFLAGS_UBSAN := $(ubsan-cflags-y)