From patchwork Thu Dec 19 12:02:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: max X-Patchwork-Id: 303406 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3AD8A2C0084 for ; Thu, 19 Dec 2013 23:03:04 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=eJD10ehckQAb7d/y6 bbmWLbMAVes5sT0Zs5yAWld6rIYnyk+SZKbK/T3to8mmu7Gvn7ZNix8RJ/0Ycuhj PXso6dXyZiLsxLafW5Jy5AqGf+4Kmk6yarTXsK9fj8Z46adKXXNOhyv/ehiUCCes wCEZjiTum1c7re9YOSiLRouuhI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=PLaZZ5F6MxkEphdyCEW6K1S XqMU=; b=NokcQb7F2ve5tcjGUMyfwCAT5M16mdxO0JMY2UEmITtJehkFPwNOgsj NM5b6ZipzE+2XFD3q7I0zc6KnpvIQbyMf/3CwOpXW+jjbUNRcyo49EMvYpYsxtQF Du8DvyqUGXpLY6OA3AEBOH5C4qOkPOQPRsg3H29d3WwBg2FgZ1YI= Received: (qmail 22297 invoked by alias); 19 Dec 2013 12:02:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 22254 invoked by uid 89); 19 Dec 2013 12:02:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mailout4.w1.samsung.com Received: from mailout4.w1.samsung.com (HELO mailout4.w1.samsung.com) (210.118.77.14) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (DES-CBC3-SHA encrypted) ESMTPS; Thu, 19 Dec 2013 12:02:52 +0000 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MY100GNTYSPG060@mailout4.w1.samsung.com> for gcc-patches@gcc.gnu.org; Thu, 19 Dec 2013 12:02:49 +0000 (GMT) Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 6C.3C.18565.860E2B25; Thu, 19 Dec 2013 12:02:48 +0000 (GMT) Received: from [106.109.8.249] by eusync2.samsung.com (Oracle Communications Messaging Server 7u4-23.01(7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0MY100E19YSNGM50@eusync2.samsung.com>; Thu, 19 Dec 2013 12:02:48 +0000 (GMT) Message-id: <52B2E067.2050308@partner.samsung.com> Date: Thu, 19 Dec 2013 16:02:47 +0400 From: Maxim Ostapenko User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0 MIME-version: 1.0 To: Jakub Jelinek Cc: Yury Gribov , Konstantin Serebryany , GCC Patches , Viacheslav Garbuzov Subject: Re: RFC Asan instrumentation control References: <52A1B4F2.8040105@samsung.com> <20131206120929.GJ892@tucnak.redhat.com> <52A1C564.3030505@samsung.com> <52A1CCE0.40307@samsung.com> <52A1D1E3.1040200@samsung.com> <52B18887.9080605@partner.samsung.com> <20131218115930.GX892@tucnak.redhat.com> <52B2DFA0.8090800@partner.samsung.com> In-reply-to: <52B2DFA0.8090800@partner.samsung.com> Content-type: multipart/mixed; boundary=------------090602000602040909040702 X-IsSubscribed: yes Sorry, ChangeLog and patch, of course. -Maxim. 2013-12-19 Max Ostapenko * cfgexpand.c (expand_stack_vars): Optionally disable asan stack protection. (expand_used_vars): Likewise. (partition_stack_vars): Likewise. * asan.c (asan_emit_stack_protection): Optionally disable after return stack usage. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_builtin_call): Likewise. (instrument_strlen_call): Likewise. (asan_protect_global): Optionally disable global variables protection. * doc/invoke.texi: Added doc for new options. * params.def: Added new options. * params.h: Likewise. 2013-12-19 Max Ostapenko * c-c++-common/asan/global-overflow-2.c: New test. * c-c++-common/asan/memcmp-3.c: Likewise. * c-c++-common/asan/no-instrument-reads.c: Likewise. * c-c++-common/asan/no-instrument-writes.c: Likewise. * c-c++-common/asan/stack-use-after-return.c: Likewise * c-c++-common/asan/no-stack-use-after-return.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index 1394e13..005db18 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h" #include "predict.h" +#include "params.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -1003,7 +1004,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ - if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase) + if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase && ASAN_USE_AFTER_RETURN) { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment @@ -1239,6 +1240,9 @@ asan_needs_local_alias (tree decl) bool asan_protect_global (tree decl) { + if (!ASAN_GLOBALS) + return false; + rtx rtl, symbol; if (TREE_CODE (decl) == STRING_CST) @@ -1568,6 +1572,11 @@ static void instrument_derefs (gimple_stmt_iterator *iter, tree t, location_t location, bool is_store) { + if (is_store && !ASAN_INSTRUMENT_WRITES) + return; + if (!is_store && !ASAN_INSTRUMENT_READS) + return; + tree type, base; HOST_WIDE_INT size_in_bytes; @@ -1897,6 +1906,9 @@ instrument_strlen_call (gimple_stmt_iterator *iter) static bool instrument_builtin_call (gimple_stmt_iterator *iter) { + if (!ASAN_MEMINTRIN) + return false; + bool iter_advanced_p = false; gimple call = gsi_stmt (*iter); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 7a93975..55708eb 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -798,7 +798,7 @@ partition_stack_vars (void) sizes, as the shorter vars wouldn't be adequately protected. Don't do that for "large" (unsupported) alignment objects, those aren't protected anyway. */ - if ((flag_sanitize & SANITIZE_ADDRESS) && isize != jsize + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && isize != jsize && ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) break; @@ -981,7 +981,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { base = virtual_stack_vars_rtx; - if ((flag_sanitize & SANITIZE_ADDRESS) && pred) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred) { HOST_WIDE_INT prev_offset = frame_offset; tree repr_decl = NULL_TREE; @@ -1160,7 +1160,7 @@ defer_stack_allocation (tree var, bool toplevel) /* If stack protection is enabled, *all* stack variables must be deferred, so that we can re-order the strings to the top of the frame. Similarly for Address Sanitizer. */ - if (flag_stack_protect || (flag_sanitize & SANITIZE_ADDRESS)) + if (flag_stack_protect || ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK)) return true; /* We handle "large" alignment via dynamic allocation. We want to handle @@ -1820,7 +1820,7 @@ expand_used_vars (void) expand_stack_vars (stack_protect_decl_phase_2, &data); } - if (flag_sanitize & SANITIZE_ADDRESS) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK) /* Phase 3, any partitions that need asan protection in addition to phase 1 and 2. */ expand_stack_vars (asan_decl_phase_3, &data); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1a6d815..f25958b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10037,6 +10037,36 @@ The default choice depends on the target. Set the maximum number of existing candidates that will be considered when seeking a basis for a new straight-line strength reduction candidate. +@item asan-globals +Enable buffer overflow detection for global objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable global objects protection use @option{--param asan-globals=0} option. + +@item asan-stack +Enable buffer overflow detection for stack objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable stack protection use @option{--param asan-stack=0} option. + +@item asan-instrument-reads +Enable buffer overflow detection for memory reads instructions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable memory reads instructions protection use @option{--param asan-instrument-reads=0} option. + +@item asan-instrument-writes +Enable buffer overflow detection for memory writes instructions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable memory writes instructions protection use @option{--param asan-instrument-writes=0} option. + +@item asan-memintrin +Enable detection for builtin functions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable builtin functions protection use @option{--param asan-memintrin=0} option. + +@item asan-use-after-return +Enable detection of use-after-return. This kind of protection is enabled by default if you are using +@option{-fsanitize=address} option. +To disable builtin functions protection use @option{--param asan-use-after-return=0} option. + @end table @end table diff --git a/gcc/params.def b/gcc/params.def index c0f9622..60ce2df 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1049,7 +1049,37 @@ DEFPARAM (PARAM_MAX_SLSR_CANDIDATE_SCAN, "strength reduction", 50, 1, 999999) +DEFPARAM(PARAM_ASAN_STACK, + "asan-stack", + "Enable asan stack protection", + 1, 0, 1) + +DEFPARAM(PARAM_ASAN_GLOBALS, + "asan-globals", + "Enable asan globals protection", + 1, 0, 1) + +DEFPARAM(PARAM_ASAN_INSTRUMENT_WRITES, + "asan-instrument-writes", + "Enable asan store operations protection", + 1, 0, 1) + +DEFPARAM(PARAM_ASAN_INSTRUMENT_READS, + "asan-instrument-reads", + "Enable asan load operations protection", + 1, 0, 1) + +DEFPARAM(PARAM_ASAN_MEMINTRIN, + "asan-memintrin", + "Enable asan builtin functions protection", + 1, 0, 1) + +DEFPARAM(PARAM_ASAN_USE_AFTER_RETURN, + "asan-use-after-return", + "Enable asan builtin functions protection", + 1, 0, 1) /* + Local variables: mode:c End: diff --git a/gcc/params.h b/gcc/params.h index f137e9e..49c1a2d 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -218,5 +218,17 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_ALLOW_PACKED_LOAD_DATA_RACES) #define ALLOW_PACKED_STORE_DATA_RACES \ PARAM_VALUE (PARAM_ALLOW_PACKED_STORE_DATA_RACES) +#define ASAN_STACK \ + PARAM_VALUE (PARAM_ASAN_STACK) +#define ASAN_GLOBALS \ + PARAM_VALUE (PARAM_ASAN_GLOBALS) +#define ASAN_INSTRUMENT_READS \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENT_READS) +#define ASAN_INSTRUMENT_WRITES \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENT_WRITES) +#define ASAN_MEMINTRIN \ + PARAM_VALUE (PARAM_ASAN_MEMINTRIN) +#define ASAN_USE_AFTER_RETURN \ + PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN) #endif /* ! GCC_PARAMS_H */ diff --git a/gcc/testsuite/c-c++-common/asan/global-overflow-2.c b/gcc/testsuite/c-c++-common/asan/global-overflow-2.c new file mode 100644 index 0000000..5fe7ba3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/global-overflow-2.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-globals=0" } */ +#include +extern +#ifdef __cplusplus +"C" +#endif +void *memset (void *, int, __SIZE_TYPE__); + +volatile int ten = 10; + +int main() { + static char XXX[10]; + static char YYY[10]; + static char ZZZ[10]; + memset(XXX, 0, 10); + memset(YYY, 0, 10); + memset(ZZZ, 0, 10); + int res = YYY[ten]; /* BOOOM */ + res += XXX[ten/10] + ZZZ[ten/10]; + return 0; +} diff --git a/gcc/testsuite/c-c++-common/asan/memcmp-3.c b/gcc/testsuite/c-c++-common/asan/memcmp-3.c new file mode 100644 index 0000000..5b28155 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/memcmp-3.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-stack=0" } */ +#include + +volatile int one = 1; + +int +main () +{ + volatile char a1[] = {one, 2, 3, 4}; + volatile char a2[] = {1, 2*one, 3, 4}; + int res = memcmp ((void*)a1,(void*) a2, 5 + one); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c new file mode 100644 index 0000000..6098545 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-instrument-reads=0" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memset (void *, int, __SIZE_TYPE__); + +volatile int ten = 10; + +int main() { + volatile char x[10]; + memset((void*) x, 0, 10); + volatile int a = x[ten]; /* BOOOM */ + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c new file mode 100644 index 0000000..2569f39 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-instrument-writes=0" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memset (void *, int, __SIZE_TYPE__); + +volatile int ten = 10; + +int main() { + volatile char x[10]; + volatile int y; + memset((void *)x, 0, 10); + x[ten] = 1; /* BOOOM */ + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/asan/no-stack-use-after-return.c b/gcc/testsuite/c-c++-common/asan/no-stack-use-after-return.c new file mode 100644 index 0000000..4f9461e --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-stack-use-after-return.c @@ -0,0 +1,49 @@ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ +/* { dg-options "--param asan-use-after-return=0" } */ +/* { dg-do run } */ + +#include +#include + +#ifndef kSize +# define kSize 1 +#endif + +#ifndef UseThread +# define UseThread 0 +#endif + +__attribute__((noinline)) +char *Ident(char *x) { + fprintf(stderr, "1: %p\n", x); + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local[kSize]; + return Ident(local); +} + +__attribute__((noinline)) +void Func2(char *x) { + fprintf(stderr, "2: %p\n", x); + *x = 1; +} + +void *Thread(void *unused) { + Func2(Func1()); + return NULL; +} + +int main(int argc, char **argv) { +#if UseThread + pthread_t t; + pthread_create(&t, 0, Thread, 0); + pthread_join(t, 0); +#else + Func2(Func1()); +#endif + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/asan/stack-use-after-return.c b/gcc/testsuite/c-c++-common/asan/stack-use-after-return.c new file mode 100644 index 0000000..9194d83 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/stack-use-after-return.c @@ -0,0 +1,53 @@ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +#ifndef kSize +# define kSize 1 +#endif + +#ifndef UseThread +# define UseThread 0 +#endif + +__attribute__((noinline)) +char *Ident(char *x) { + fprintf(stderr, "1: %p\n", x); + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local[kSize]; + return Ident(local); +} + +__attribute__((noinline)) +void Func2(char *x) { + fprintf(stderr, "2: %p\n", x); + *x = 1; +} + +void *Thread(void *unused) { + Func2(Func1()); + return NULL; +} + +int main(int argc, char **argv) { +#if UseThread + pthread_t t; + pthread_create(&t, 0, Thread, 0); + pthread_join(t, 0); +#else + Func2(Func1()); +#endif + return 0; +} + +/* { dg-output "WRITE of size 1 .* thread T0(\n|\r\n|\r).*" } */ +/* { dg-output " #0 .* Func2.*stack-use-after-return.c:31.*" }*/ +/* { dg-output "is located in stack of thread T0 at offset.*" }*/ +/* { dg-output "\'local\' <== Memory access at offset 32 is inside this variable.*" }*/