From patchwork Tue Jan 22 16:58:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 214603 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]) by ozlabs.org (Postfix) with SMTP id 095492C0082 for ; Wed, 23 Jan 2013 03:58:50 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1359478731; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=sk4sM1iql4qcO5F/THmz GJrag40=; b=jj7nTkdFsl0w0W9iOPIVsOfH1q9VL2a/bzOFUD1a1f9mM4AV+H91 6JTRdbSe3iU0qj/DIdZt+7mJSzm7oPL/8vDaqJnxzTorAZiMJrCksMgeq5YrTdO1 Oy/Raxy6g07ZEapXrRfUSJQxnC5N55KAdH639Ty+UrtaBSrOw6W2OrU= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To:MIME-Version:Content-Type:Content-Disposition:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Z/JVT9+vYUOSRg2n4f9T3FXqmK7FFVx7CyMTLyh4546Kgu0+C+NvOLD8WSekRp 8FSsVEwlrONq+WmARoKVkOwdSmztb2JW0U8Bpj0O1lV75wUv5LLv1fj+P6mC1hYo DHbsFaUwu08DRP7KgqwPzTEblIUBFuQm7yn3UV0Dtn9WQ=; Received: (qmail 28220 invoked by alias); 22 Jan 2013 16:58:28 -0000 Received: (qmail 28202 invoked by uid 22791); 22 Jan 2013 16:58:22 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 22 Jan 2013 16:58:17 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r0MGwGvW019454 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 22 Jan 2013 11:58:16 -0500 Received: from zalov.redhat.com (vpn1-4-254.ams2.redhat.com [10.36.4.254]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r0MGwERZ021247 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 22 Jan 2013 11:58:16 -0500 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id r0MGwEeB018555; Tue, 22 Jan 2013 17:58:14 +0100 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r0MGwDKW018554; Tue, 22 Jan 2013 17:58:13 +0100 Date: Tue, 22 Jan 2013 17:58:13 +0100 From: Jakub Jelinek To: Dodji Seketeli , Konstantin Serebryany , Dmitry Vyukov Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Put -lasan always very early on the ld command line (PR sanitizer/55374) Message-ID: <20130122165813.GY7269@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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 Hi! libasan relies on being linked before -lpthread, -lstdc++ and -lc, but so far nothing was ensuring that. Not only e.g. -lstdc++ could come before -lasan when -lstdc++ was added by g++ language specific driver handling, but also if the user specifies -lstdc++, -lpthread or -lc somewhere on the gcc/g++ command line together with -fsanitize=address, those libraries will likely be linked before -lasan. This patch attempts to fix that, by (for Linux) linking -lasan as early as possible, in particularly after -L.../ options, but before the user command line options (input files, -Wl,* options, etc.) are copied over to the command line (%o spec file hunk). For -static-libasan, the patch changes it to link -lasan only when linking executables (and PIEs), but when linking shared libraries, we don't want to duplicate the libasan stuff in each shared library. And, when libasan.a is linked into executables/PIEs, it is linked with -Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic to avoid issues with portions of libasan.a being linked at various spots on the command line, when it comes first, nothing would actually link it in, and when we'd prepend it before every -lpthread, -lstdc++ and -lc on the command line, it would be very hard to get it right (e.g. due to -Wl,-B* user options). This reveals that two tests don't pass with -lasan being linked before -lstdc++, one fixed by backporting fix from upstream, the other by adjusting the output regexp. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-01-22 Jakub Jelinek PR sanitizer/55374 * gcc.c (LIBASAN_SPEC): Define just to ADD_STATIC_LIBASAN_LIBS if LIBASAN_EARLY_SPEC is defined. (LIBASAN_EARLY_SPEC): Define to empty string if not already defined. (LINK_COMMAND_SPEC): Add LIBASAN_EARLY_SPEC for -fsanitize=address, before %o. * config/gnu-user.h (LIBASAN_EARLY_SPEC): Define. * g++.dg/asan/large-func-test-1.C: Allow both _Zna[jm] in addition to _Znw[jm] in the backtrace. Allow _Zna[jm] to be the first frame printed in backtrace. * g++.dg/asan/deep-stack-uaf-1.C: Use malloc instead of operator new to avoid errors about mismatched allocation vs. deallocation. Jakub --- gcc/gcc.c.jj 2013-01-13 13:23:38.000000000 +0100 +++ gcc/gcc.c 2013-01-22 14:21:06.335193713 +0100 @@ -548,7 +548,9 @@ proper position among the other output f #else #define ADD_STATIC_LIBASAN_LIBS #endif -#ifdef HAVE_LD_STATIC_DYNAMIC +#ifdef LIBASAN_EARLY_SPEC +#define LIBASAN_SPEC ADD_STATIC_LIBASAN_LIBS +#elif defined(HAVE_LD_STATIC_DYNAMIC) #define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \ "} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \ ADD_STATIC_LIBASAN_LIBS @@ -557,6 +559,10 @@ proper position among the other output f #endif #endif +#ifndef LIBASAN_EARLY_SPEC +#define LIBASAN_EARLY_SPEC "" +#endif + #ifndef LIBTSAN_SPEC #ifdef HAVE_LD_STATIC_DYNAMIC #define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \ @@ -705,7 +711,8 @@ proper position among the other output f "%{fuse-ld=*:-fuse-ld=%*}\ %X %{o*} %{e*} %{N} %{n} %{r}\ %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\ - %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ + %{static:} %{L*} %(mfwrap) %(link_libgcc) \ + %{fsanitize=address:" LIBASAN_EARLY_SPEC "} %o\ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\ %(mflib) " STACK_SPLIT_SPEC "\ --- gcc/config/gnu-user.h.jj 2013-01-11 09:03:09.000000000 +0100 +++ gcc/config/gnu-user.h 2013-01-22 14:22:43.333639647 +0100 @@ -98,6 +98,15 @@ see the files COPYING3 and COPYING.RUNTI #define TARGET_C99_FUNCTIONS 1 #define TARGET_HAS_SINCOS 1 +/* Link -lasan early on the command line. For -static-libasan, don't link + it for -shared link, the executable should be compiled with -static-libasan + in that case, and for executable link link with --{,no-}whole-archive around + it to force everything into the executable. */ +#undef LIBASAN_EARLY_SPEC +#define LIBASAN_EARLY_SPEC "%{static-libasan:%{!shared:" \ + LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \ + LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}" + /* Additional libraries needed by -static-libasan. */ #undef STATIC_LIBASAN_LIBS #define STATIC_LIBASAN_LIBS "-ldl -lpthread" --- gcc/testsuite/g++.dg/asan/large-func-test-1.C.jj 2012-12-14 16:24:38.000000000 +0100 +++ gcc/testsuite/g++.dg/asan/large-func-test-1.C 2013-01-22 16:49:31.158090177 +0100 @@ -41,5 +41,5 @@ int main() { // { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } // { dg-output "0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" } // { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } -// { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } -// { dg-output " #1 0x\[0-9a-f\]+ (in (operator new|_*_Znw\[mj\])|\[(\])\[^\n\r]*(\n|\r\n|\r)" } +// { dg-output " #0( 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } +// { dg-output " #1|) 0x\[0-9a-f\]+ (in (operator new|_*_Zn\[aw\]\[mj\])|\[(\])\[^\n\r]*(\n|\r\n|\r)" } --- gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C.jj 2012-12-14 16:24:38.000000000 +0100 +++ gcc/testsuite/g++.dg/asan/deep-stack-uaf-1.C 2013-01-22 16:43:03.337091101 +0100 @@ -27,7 +27,7 @@ struct DeepFree<0> { }; int main() { - char *x = new char[10]; + char *x = (char*)malloc(10); // deep_free(x); DeepFree<200>::free(x); return x[5];