commit bd51cdb807c2cf5ada0101ca7db89076b54ed18e Author: Yury Gribov Date: Tue Jul 22 11:02:03 2014 +0400 2014-07-23 Yury Gribov * doc/cpp.texi (__SANITIZE_ADDRESS__): Updated description. * doc/invoke.texi (-fsanitize=kernel-address): Describe new option. * flag-types.h (SANITIZE_USER_ADDRESS, SANITIZE_KERNEL_ADDRESS): New enums. * gcc.c (sanitize_spec_function): Support new option. (SANITIZER_SPEC): Remove now redundant check. * opts.c (common_handle_option): Support new option. (finish_options): Check for incompatibilities. * toplev.c (process_options): Split userspace-specific checks. diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index aaed739..0a6e50c 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -2354,8 +2354,8 @@ This macro is defined, with value 3, when @option{-fstack-protector-strong} is in use. @item __SANITIZE_ADDRESS__ -This macro is defined, with value 1, when @option{-fsanitize=address} is -in use. +This macro is defined, with value 1, when @option{-fsanitize=address} +or @option{-fsanitize=kernel-address} are in use. @item __TIMESTAMP__ This macro expands to a string constant that describes the date and time diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b5e8d98..391daf8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -5405,6 +5405,11 @@ more details. The run-time behavior can be influenced using the @url{https://code.google.com/p/address-sanitizer/wiki/Flags#Run-time_flags} for a list of supported options. +@item -fsanitize=kernel-address +@opindex fsanitize=kernel-address +Enable AddressSanitizer for Linux kernel. +See @uref{http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel} for more details. + @item -fsanitize=thread @opindex fsanitize=thread Enable ThreadSanitizer, a fast data race detector. diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 2849455..bf813b6 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -214,23 +214,25 @@ enum vect_cost_model { enum sanitize_code { /* AddressSanitizer. */ SANITIZE_ADDRESS = 1 << 0, + SANITIZE_USER_ADDRESS = 1 << 1, + SANITIZE_KERNEL_ADDRESS = 1 << 2, /* ThreadSanitizer. */ - SANITIZE_THREAD = 1 << 1, + SANITIZE_THREAD = 1 << 3, /* LeakSanitizer. */ - SANITIZE_LEAK = 1 << 2, + SANITIZE_LEAK = 1 << 4, /* UndefinedBehaviorSanitizer. */ - SANITIZE_SHIFT = 1 << 3, - SANITIZE_DIVIDE = 1 << 4, - SANITIZE_UNREACHABLE = 1 << 5, - SANITIZE_VLA = 1 << 6, - SANITIZE_NULL = 1 << 7, - SANITIZE_RETURN = 1 << 8, - SANITIZE_SI_OVERFLOW = 1 << 9, - SANITIZE_BOOL = 1 << 10, - SANITIZE_ENUM = 1 << 11, - SANITIZE_FLOAT_DIVIDE = 1 << 12, - SANITIZE_FLOAT_CAST = 1 << 13, - SANITIZE_BOUNDS = 1 << 14, + SANITIZE_SHIFT = 1 << 5, + SANITIZE_DIVIDE = 1 << 6, + SANITIZE_UNREACHABLE = 1 << 7, + SANITIZE_VLA = 1 << 8, + SANITIZE_NULL = 1 << 9, + SANITIZE_RETURN = 1 << 10, + SANITIZE_SI_OVERFLOW = 1 << 11, + SANITIZE_BOOL = 1 << 12, + SANITIZE_ENUM = 1 << 13, + SANITIZE_FLOAT_DIVIDE = 1 << 14, + SANITIZE_FLOAT_CAST = 1 << 15, + SANITIZE_BOUNDS = 1 << 16, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM diff --git a/gcc/gcc.c b/gcc/gcc.c index 6cd08ea..c0fde8c 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -779,8 +779,7 @@ proper position among the other output files. */ #ifndef SANITIZER_SPEC #define SANITIZER_SPEC "\ %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\ - %{static:%ecannot specify -static with -fsanitize=address}\ - %{%:sanitize(thread):%e-fsanitize=address is incompatible with -fsanitize=thread}}\ + %{static:%ecannot specify -static with -fsanitize=address}}\ %{%:sanitize(thread):" LIBTSAN_SPEC "\ %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}\ %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\ @@ -8224,7 +8223,9 @@ sanitize_spec_function (int argc, const char **argv) return NULL; if (strcmp (argv[0], "address") == 0) - return (flag_sanitize & SANITIZE_ADDRESS) ? "" : NULL; + return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL; + if (strcmp (argv[0], "kernel-address") == 0) + return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL; if (strcmp (argv[0], "thread") == 0) return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; if (strcmp (argv[0], "undefined") == 0) diff --git a/gcc/opts.c b/gcc/opts.c index 5fed6f0..4b0af82 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -869,6 +869,20 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, /* The -gsplit-dwarf option requires -ggnu-pubnames. */ if (opts->x_dwarf_split_debug_info) opts->x_debug_generate_pub_sections = 2; + + /* Userspace and kernel ASan conflict with each other and with TSan. */ + + if ((flag_sanitize & SANITIZE_USER_ADDRESS) + && (flag_sanitize & SANITIZE_KERNEL_ADDRESS)) + error_at (loc, + "-fsanitize=address is incompatible with " + "-fsanitize=kernel-address"); + + if ((flag_sanitize & SANITIZE_ADDRESS) + && (flag_sanitize & SANITIZE_THREAD)) + error_at (loc, + "-fsanitize=address and -fsanitize=kernel-address " + "are incompatible with -fsanitize=thread"); } #define LEFT_COLUMN 27 @@ -1454,7 +1468,10 @@ common_handle_option (struct gcc_options *opts, size_t len; } spec[] = { - { "address", SANITIZE_ADDRESS, sizeof "address" - 1 }, + { "address", SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, + sizeof "address" - 1 }, + { "kernel-address", SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS, + sizeof "kernel-address" - 1 }, { "thread", SANITIZE_THREAD, sizeof "thread" - 1 }, { "leak", SANITIZE_LEAK, sizeof "leak" - 1 }, { "shift", SANITIZE_SHIFT, sizeof "shift" - 1 }, @@ -1520,6 +1537,25 @@ common_handle_option (struct gcc_options *opts, the null pointer checks. */ if (flag_sanitize & SANITIZE_NULL) opts->x_flag_delete_null_pointer_checks = 0; + + /* Kernel ASan implies normal ASan but does not yet support + all features. */ + if (flag_sanitize & SANITIZE_KERNEL_ADDRESS) + { + maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_STACK, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0, + opts->x_param_values, + opts_set->x_param_values); + } + break; } diff --git a/gcc/toplev.c b/gcc/toplev.c index 1c9befd..d82244f 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1555,9 +1555,18 @@ process_options (void) warn_stack_protect = 0; /* Address Sanitizer needs porting to each target architecture. */ + if ((flag_sanitize & SANITIZE_ADDRESS) - && (targetm.asan_shadow_offset == NULL - || !FRAME_GROWS_DOWNWARD)) + && !FRAME_GROWS_DOWNWARD) + { + warning (0, + "-fsanitize=address and -fsanitize=kernel-address " + "are not supported for this target"); + flag_sanitize &= ~SANITIZE_ADDRESS; + } + + if ((flag_sanitize & SANITIZE_USER_ADDRESS) + && targetm.asan_shadow_offset == NULL) { warning (0, "-fsanitize=address not supported for this target"); flag_sanitize &= ~SANITIZE_ADDRESS;