From patchwork Thu Jun 11 11:00:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marat Zakirov X-Patchwork-Id: 483056 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 A311F140291 for ; Thu, 11 Jun 2015 21:00:49 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=d5Vw1FoL; dkim-atps=neutral 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=LQPvC/rNn0wtN+6lo IGg6+obkFCAxG9dtA+7gbLf3beuBCunscOEbGwJ4uDm0agiBn4bgdAw4AGEXIIpD ATr4pIkqOH7lk3a1fRtAuieCG49r6LVqSne6qbB5tmp6Do9v9y+6goDraCjZgWOL 5a3NpvahttrZN7HHfQzrsEkOHE= 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=Pc+YpDw0JG7KOSdlOkmHmpP l1NA=; b=d5Vw1FoLhq7gCNCCJ00BT9p/b2ddTeEwmDysN3Hq0v7FIwX7dedKg96 iG0hvXO25e1mVygC3hIEti2ZBVas2hon0m2xhSgs4/gWa/Bxrpn/ziSpf5EiuXTe xeA4nr0ZAQ7n/FcPxUd8pcNah+eQjHht6Qp9yQyUuoexjMfnLRSg= Received: (qmail 13001 invoked by alias); 11 Jun 2015 11:00:42 -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 12986 invoked by uid 89); 11 Jun 2015 11:00:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=AWL, BAYES_40, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mailout2.w1.samsung.com Received: from mailout2.w1.samsung.com (HELO mailout2.w1.samsung.com) (210.118.77.12) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 11 Jun 2015 11:00:39 +0000 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NPS005YL18YAK20@mailout2.w1.samsung.com> for gcc-patches@gcc.gnu.org; Thu, 11 Jun 2015 12:00:34 +0100 (BST) Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 7A.DE.04846.25A69755; Thu, 11 Jun 2015 12:00:34 +0100 (BST) Received: from [106.109.129.103] by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NPS001QC18X3B30@eusync2.samsung.com>; Thu, 11 Jun 2015 12:00:34 +0100 (BST) Message-id: <55796A51.3090802@samsung.com> Date: Thu, 11 Jun 2015 14:00:33 +0300 From: Marat Zakirov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-version: 1.0 To: Jakub Jelinek Cc: "gcc-patches@gcc.gnu.org" , Andrew Pinski , Kostya Serebryany , Dmitry Vyukov , Yury Gribov , Andrey Ryabinin Subject: [PINGv10][PATCH] ASan on unaligned accesses References: <54F6BBA0.2010302@samsung.com> <550A662E.3080308@samsung.com> <5513ACCF.7030502@samsung.com> <20150326115013.GY1746@tucnak.redhat.com> <5513FB85.4030305@samsung.com> <20150330174257.GJ1746@tucnak.redhat.com> <5523AE6A.7010308@samsung.com> <20150407122202.GD19273@tucnak.redhat.com> <5551E11D.6030105@samsung.com> <555C3144.9050102@samsung.com> <55647D37.60909@samsung.com> <556DAB8C.3050402@samsung.com> In-reply-to: <556DAB8C.3050402@samsung.com> Content-type: multipart/mixed; boundary=------------060301030304060700050001 On 06/02/2015 04:11 PM, Marat Zakirov wrote: > On 05/26/2015 05:03 PM, Marat Zakirov wrote: >> >> >> On 05/20/2015 10:01 AM, Marat Zakirov wrote: >>> >>> >>> On 05/12/2015 02:16 PM, Marat Zakirov wrote: >>>> On 04/07/2015 03:22 PM, Jakub Jelinek wrote: >>>>> How are the automatic misaligned variables different from say heap >>>>> allocated ones, or global vars etc.? >>>> No difference you are right Jakub. Shadow memory initialization for >>>> heap values and globals of course also should be changed but it is >>>> a task for libsanitizer not ASan for which I am sending patch. Fix >>>> for libsanitizer to support unaligned heaps and globals will be >>>> committed by a separate patch. >>>>> Well, a RTL solution I've tried at http://gcc.gnu.org/PR22141, but >>>>> it gave >>>>> mixed results, so either it needs more cost tuning when it is >>>>> desirable and >>>>> when it is not, or perhaps better do that still on GIMPLE instead, >>>>> together >>>>> with trying to optimize bitfield accesses and other cases of adjacent >>>>> location accesses. But if we handle that on GIMPLE, it won't >>>>> really affect >>>>> what asan RTL emitting code produces. >>>>> >>>>> Jakub >>>>> >>>> I fixed the issue with 'movq' you were mentioned in a previous mail. >>>> >>>> --Marat >>>> >>> >> > gcc/ChangeLog: 2015-02-25 Marat Zakirov * asan.c (asan_emit_stack_protection): Support for misalign accesses. (asan_expand_check_ifn): Likewise. * params.def: New option asan-catch-misaligned. * params.h: New param ASAN_CATCH_MISALIGNED. * doc/invoke.texi: New asan param description. gcc/testsuite/ChangeLog: 2015-02-25 Marat Zakirov * c-c++-common/asan/misalign-catch.c: New test. diff --git a/gcc/asan.c b/gcc/asan.c index 9e4a629..f9d052f 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1050,7 +1050,6 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, rtx_code_label *lab; rtx_insn *insns; char buf[30]; - unsigned char shadow_bytes[4]; HOST_WIDE_INT base_offset = offsets[length - 1]; HOST_WIDE_INT base_align_bias = 0, offset, prev_offset; HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset; @@ -1059,6 +1058,8 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT; tree str_cst, decl, id; int use_after_return_class = -1; + bool misalign = (flag_sanitize & SANITIZE_KERNEL_ADDRESS) + || ASAN_CATCH_MISALIGNED; if (shadow_ptr_types[0] == NULL_TREE) asan_init_shadow_ptr_types (); @@ -1193,11 +1194,37 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, if (STRICT_ALIGNMENT) set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode))); prev_offset = base_offset; + + vec shadow_mems; + vec shadow_bytes; + + shadow_mems.create (0); + shadow_bytes.create (0); + for (l = length; l; l -= 2) { if (l == 2) cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT; offset = offsets[l - 1]; + if (l != length && misalign) + { + HOST_WIDE_INT aoff + = base_offset + ((offset - base_offset) + & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1)) + - ASAN_RED_ZONE_SIZE; + if (aoff > prev_offset) + { + shadow_mem = adjust_address (shadow_mem, VOIDmode, + (aoff - prev_offset) + >> ASAN_SHADOW_SHIFT); + prev_offset = aoff; + shadow_bytes.safe_push (0); + shadow_bytes.safe_push (0); + shadow_bytes.safe_push (0); + shadow_bytes.safe_push (0); + shadow_mems.safe_push (shadow_mem); + } + } if ((offset - base_offset) & (ASAN_RED_ZONE_SIZE - 1)) { int i; @@ -1212,13 +1239,13 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, if (aoff < offset) { if (aoff < offset - (1 << ASAN_SHADOW_SHIFT) + 1) - shadow_bytes[i] = 0; + shadow_bytes.safe_push (0); else - shadow_bytes[i] = offset - aoff; + shadow_bytes.safe_push (offset - aoff); } else - shadow_bytes[i] = ASAN_STACK_MAGIC_PARTIAL; - emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes)); + shadow_bytes.safe_push (ASAN_STACK_MAGIC_PARTIAL); + shadow_mems.safe_push (shadow_mem); offset = aoff; } while (offset <= offsets[l - 2] - ASAN_RED_ZONE_SIZE) @@ -1227,12 +1254,21 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, (offset - prev_offset) >> ASAN_SHADOW_SHIFT); prev_offset = offset; - memset (shadow_bytes, cur_shadow_byte, 4); - emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes)); + shadow_bytes.safe_push (cur_shadow_byte); + shadow_bytes.safe_push (cur_shadow_byte); + shadow_bytes.safe_push (cur_shadow_byte); + shadow_bytes.safe_push (cur_shadow_byte); + shadow_mems.safe_push (shadow_mem); offset += ASAN_RED_ZONE_SIZE; } cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE; } + for (unsigned i = 0; misalign && i < shadow_bytes.length () - 1; i++) + if (shadow_bytes[i] == 0 && shadow_bytes[i + 1] > 0) + shadow_bytes[i] = 8 + (shadow_bytes[i + 1] > 7 ? 0 : shadow_bytes[i + 1]); + for (unsigned i = 0; i < shadow_mems.length (); i++) + emit_move_insn (shadow_mems[i], asan_shadow_cst (&shadow_bytes[i * 4])); + do_pending_stack_adjust (); /* Construct epilogue sequence. */ @@ -1285,33 +1321,15 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, if (STRICT_ALIGNMENT) set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode))); - prev_offset = base_offset; - last_offset = base_offset; - last_size = 0; - for (l = length; l; l -= 2) + for (unsigned i = 0; i < shadow_mems.length (); i++) { - offset = base_offset + ((offsets[l - 1] - base_offset) - & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1)); - if (last_offset + last_size != offset) + if (shadow_bytes[i*4+3] == ASAN_STACK_MAGIC_PARTIAL) { - shadow_mem = adjust_address (shadow_mem, VOIDmode, - (last_offset - prev_offset) - >> ASAN_SHADOW_SHIFT); - prev_offset = last_offset; - asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT); - last_offset = offset; - last_size = 0; + asan_clear_shadow (shadow_mems[i], 8); + i++; } - last_size += base_offset + ((offsets[l - 2] - base_offset) - & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1)) - - offset; - } - if (last_size) - { - shadow_mem = adjust_address (shadow_mem, VOIDmode, - (last_offset - prev_offset) - >> ASAN_SHADOW_SHIFT); - asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT); + else + asan_clear_shadow (shadow_mems[i], 4); } do_pending_stack_adjust (); @@ -2546,6 +2564,8 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) gimple g = gsi_stmt (*iter); location_t loc = gimple_location (g); + bool misalign = (flag_sanitize & SANITIZE_KERNEL_ADDRESS) + || ASAN_CATCH_MISALIGNED; bool recover_p = (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0; @@ -2643,7 +2663,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) tree base_addr = gimple_assign_lhs (g); tree t = NULL_TREE; - if (real_size_in_bytes >= 8) + if (real_size_in_bytes >= 8 && !misalign) { tree shadow = build_shadow_mem_access (&gsi, loc, base_addr, shadow_ptr_type); @@ -2662,7 +2682,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) /* Aligned (>= 8 bytes) can test just (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known to be 0. */ - if (align < 8) + if (align < 8 || misalign) { gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7)); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index bf8afad..ee67e45 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10965,6 +10965,12 @@ is greater or equal to this number, use callbacks instead of inline checks. E.g. to disable inline code use @option{--param asan-instrumentation-with-call-threshold=0}. +@item asan-catch-misaligned +Catch invalid unaligned memory accesses. +This option is needed to prevent potential ASan false positives due to +unaligned to type size memory accesses in some apllication like Linux kernel +@option{--param asan-catch-misaligned=0}. + @item chkp-max-ctor-size Static constructors generated by Pointer Bounds Checker may become very large and significantly increase compile time at optimization level diff --git a/gcc/params.def b/gcc/params.def index 5e2c769..d96db71 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1151,6 +1151,11 @@ DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, "in function becomes greater or equal to this number", 7000, 0, INT_MAX) +DEFPARAM (PARAM_ASAN_CATCH_MISALIGNED, + "asan-catch-misaligned", + "catch unaligned access", + 0, 1, 1) + DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS, "uninit-control-dep-attempts", "Maximum number of nested calls to search for control dependencies " diff --git a/gcc/params.h b/gcc/params.h index 28d077f..c556ca6 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -240,5 +240,7 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN) #define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \ PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD) +#define ASAN_CATCH_MISALIGNED \ + PARAM_VALUE (PARAM_ASAN_CATCH_MISALIGNED) #endif /* ! GCC_PARAMS_H */ diff --git a/gcc/testsuite/c-c++-common/asan/misalign-catch.c b/gcc/testsuite/c-c++-common/asan/misalign-catch.c new file mode 100644 index 0000000..ae5dfc4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/misalign-catch.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-catch-misaligned=1" } */ +/* { dg-shouldfail "asan" } */ + +long long *ptr; + +__attribute__((noinline)) +void foo () { + ptr = ((long long int *)(((char *)ptr) + 1)); + *ptr = 1; +} + +int main () +{ + long long int local[9]; + ptr = (long long *)&local[8]; + foo (); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */