ubsan: move cc-option tests into Kconfig
authorKees Cook <keescook@chromium.org>
Wed, 16 Dec 2020 04:46:24 +0000 (20:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2020 06:46:18 +0000 (22:46 -0800)
Instead of doing if/endif blocks with cc-option calls in the UBSAN
Makefile, move all the tests into Kconfig and use the Makefile to collect
the results.

Link: https://lkml.kernel.org/r/20201203004437.389959-3-keescook@chromium.org
Link: https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/
Signed-off-by: Kees Cook <keescook@chromium.org>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
Tested-by: Nathan Chancellor <natechancellor@gmail.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: George Popescu <georgepope@android.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Marco Elver <elver@google.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Michal Marek <michal.lkml@markovi.net>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Peter Oberparleiter <oberpar@linux.ibm.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
lib/Kconfig.ubsan
scripts/Makefile.ubsan

index d8d4d65..0514711 100644 (file)
@@ -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
index c18fecc..0e53a93 100644 (file)
@@ -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)