From patchwork Wed Feb 13 15:19:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 220165 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 93FCF2C0293 for ; Thu, 14 Feb 2013 02:19:33 +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=1361373574; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: References:MIME-Version:Content-Type:Content-Disposition: In-Reply-To:User-Agent:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=oEw2qeK5xuun2bYAM4tXwGeh0Dc=; b=xX22MRAr+0XEM8o kDch/K0pufNrwBdZG25NnqzE+l/EevE30hOqfT/YOeGWGfI5uRizz5eTjT5EnS9Y HMbNrqdRvzxTU7FbNf8jVG1PMIYSvjz25yBGLS8FO5fTFwW3+eKOfrY4UYQRJplm SIGhtddZRO2GpotW7BZ3OiHl6J2A= 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:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=hD0I1EppALRyxxuxKAOnBMa1Stbi8q/hoRXZvN+jblJNTN4zIQLmEHug/5Qw83 3AObbZpnI9B3z1FGULZ3h4zEVSE2qbH7plRMVsLIu4nwLvaGyWQmYqSnX9B1fHQ5 LjYUABR8wtrJqzFANbMHMymrhnljdLYA/9RIQubWUzEvc=; Received: (qmail 25850 invoked by alias); 13 Feb 2013 15:19:28 -0000 Received: (qmail 25838 invoked by uid 22791); 13 Feb 2013 15:19:27 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_SPAMHAUS_DROP, 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; Wed, 13 Feb 2013 15:19:18 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r1DFJH3R025903 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 13 Feb 2013 10:19:17 -0500 Received: from zalov.redhat.com (vpn1-6-84.ams2.redhat.com [10.36.6.84]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r1DFJFrq007931 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 13 Feb 2013 10:19:17 -0500 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id r1DFJEUX031901; Wed, 13 Feb 2013 16:19:15 +0100 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r1DFJELk031900; Wed, 13 Feb 2013 16:19:14 +0100 Date: Wed, 13 Feb 2013 16:19:14 +0100 From: Jakub Jelinek To: Konstantin Serebryany Cc: GCC Patches , Dodji Seketeli , Dmitry Vyukov , Evgeniy Stepanov Subject: Re: libsanitizer merge from upstream r175042 Message-ID: <20130213151914.GU4385@tucnak.redhat.com> Reply-To: Jakub Jelinek References: <20130213095107.GM4385@tucnak.redhat.com> <20130213103200.GP4385@tucnak.redhat.com> <20130213115934.GQ4385@tucnak.redhat.com> <20130213124828.GR4385@tucnak.redhat.com> <20130213130724.GS4385@tucnak.redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: 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 On Wed, Feb 13, 2013 at 05:39:15PM +0400, Konstantin Serebryany wrote: > > No. You can disable it for the whole system (prelink -ua), but that is not > > a sane requirement to running sanitized programs. > > Why not? > :) Because that is a fully system operation, requires root access, etc. The fact that some user wants to test one of his programs with Asan shouldn't need to affect other users. > This we can deal with. > We already setenv+reexec on Mac to solve similar issue with Mac's > dynamic run-time. The reexec is problematic, what if the program already in constructors run before __asan_init (perhaps ctors of other libraries etc.) does something that really shouldn't be done twice? > > Sure, but it will be then slower, I thought you are looking for ASAN speed > > improvements. > > Yes, and we already achieved it on ubuntu :) AFAIK prelink is available even on ubuntu, perhaps not the default. > > I'll try to implement it eventually and > > try to convince you ;) > > That's surely not hard to implement, but very hard to support. Why? Here is the patch, works just fine for me here during asan.exp testing. You can very easily either install and enable prelink on one of your x86_64-linux testing boxes, or just install it and add test that will say prelink -r 0x3600000000 some test shared library and then just use it in sanitized program (that will also verify that you can mmap libraries in that range), or even just write a test that will in a non-instrumented ctor with lower priority than asan's priority mmap a few pages at 0x3000000000 and close to 0x3fffff0000 and store some data into those buffers later on in sanitized code. Jakub --- asan_mapping.h.jj 2013-02-13 11:53:43.000000000 +0100 +++ asan_mapping.h 2013-02-13 16:00:22.821413836 +0100 @@ -61,13 +61,31 @@ extern SANITIZER_INTERFACE_ATTRIBUTE upt #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) #define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) +#if ASAN_LINUX && defined(__x86_64__) +# define kMidMemBeg (kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0) +# define kMidMemEnd (kLowMemEnd < 0x3000000000ULL ? 0x3fffffffffULL : 0) +# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) +# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) +#else +# define kMidMemBeg 0 +# define kMidMemEnd 0 +# define kMidShadowBeg 0 +# define kMidShadowEnd 0 +#endif + // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. #define kZeroBaseShadowStart (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) -#define kShadowGapEnd (kHighShadowBeg - 1) +#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) + +#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) +#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) + +#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) +#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) namespace __asan { @@ -86,8 +104,12 @@ static inline bool AddrIsInHighMem(uptr return a >= kHighMemBeg && a <= kHighMemEnd; } +static inline bool AddrIsInMidMem(uptr a) { + return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; +} + static inline bool AddrIsInMem(uptr a) { - return AddrIsInLowMem(a) || AddrIsInHighMem(a); + return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); } static inline uptr MemToShadow(uptr p) { @@ -99,11 +121,22 @@ static inline bool AddrIsInHighShadow(up return a >= kHighShadowBeg && a <= kHighMemEnd; } +static inline bool AddrIsInMidShadow(uptr a) { + return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; +} + static inline bool AddrIsInShadow(uptr a) { - return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); + return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } static inline bool AddrIsInShadowGap(uptr a) { + if (kMidMemBeg) + { + if (a <= kShadowGapEnd) + return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; + return (a >= kShadowGap2Beg && a <= kShadowGap2End) + || (a >= kShadowGap3Beg && a <= kShadowGap3End); + } // In zero-based shadow mode we treat addresses near zero as addresses // in shadow gap as well. if (SHADOW_OFFSET == 0) --- asan_rtl.cc.jj 2013-02-13 11:53:44.000000000 +0100 +++ asan_rtl.cc 2013-02-13 16:00:10.815483846 +0100 @@ -35,8 +35,14 @@ static void AsanDie() { Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); SleepForSeconds(flags()->sleep_before_dying); } - if (flags()->unmap_shadow_on_exit) - UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + if (flags()->unmap_shadow_on_exit) { + if (!kMidMemBeg) + UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + else { + UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); + UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); + } + } if (death_callback) death_callback(); if (flags()->abort_on_error) @@ -357,17 +363,33 @@ void __asan_init() { (void*)kHighMemBeg, (void*)kHighMemEnd); Printf("|| `[%p, %p]` || HighShadow ||\n", (void*)kHighShadowBeg, (void*)kHighShadowEnd); + if (kMidMemBeg) { + Printf("|| `[%p, %p]` || ShadowGap ||\n", + (void*)kShadowGap3Beg, (void*)kShadowGap3End); + Printf("|| `[%p, %p]` || MidMem ||\n", + (void*)kMidMemBeg, (void*)kMidMemEnd); + Printf("|| `[%p, %p]` || ShadowGap ||\n", + (void*)kShadowGap2Beg, (void*)kShadowGap2End); + Printf("|| `[%p, %p]` || MidShadow ||\n", + (void*)kMidShadowBeg, (void*)kMidShadowEnd); + } Printf("|| `[%p, %p]` || ShadowGap ||\n", (void*)kShadowGapBeg, (void*)kShadowGapEnd); Printf("|| `[%p, %p]` || LowShadow ||\n", (void*)kLowShadowBeg, (void*)kLowShadowEnd); Printf("|| `[%p, %p]` || LowMem ||\n", (void*)kLowMemBeg, (void*)kLowMemEnd); - Printf("MemToShadow(shadow): %p %p %p %p\n", + Printf("MemToShadow(shadow): %p %p %p %p", (void*)MEM_TO_SHADOW(kLowShadowBeg), (void*)MEM_TO_SHADOW(kLowShadowEnd), (void*)MEM_TO_SHADOW(kHighShadowBeg), (void*)MEM_TO_SHADOW(kHighShadowEnd)); + if (kMidMemBeg) { + Printf(" %p %p", + (void*)MEM_TO_SHADOW(kMidShadowBeg), + (void*)MEM_TO_SHADOW(kMidShadowEnd)); + } + Printf("\n"); Printf("red_zone=%zu\n", (uptr)flags()->redzone); Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); @@ -375,6 +397,9 @@ void __asan_init() { Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + if (kMidMemBeg) + CHECK(kMidShadowBeg > kLowShadowEnd && kMidMemBeg > kMidShadowEnd + && kHighShadowBeg > kMidMemEnd); } if (flags()->disable_core) { @@ -384,7 +409,26 @@ void __asan_init() { uptr shadow_start = kLowShadowBeg; if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity(); uptr shadow_end = kHighShadowEnd; - if (MemoryRangeIsAvailable(shadow_start, shadow_end)) { + if (kMidMemBeg + && MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) + && MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) { + if (kLowShadowBeg != kLowShadowEnd) { + // mmap the low shadow plus at least one page. + ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(), + kLowShadowEnd); + } + // mmap the mid shadow. + ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd); + // mmap the high shadow. + ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); + // protect the gaps + void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + CHECK(prot == (void*)kShadowGapBeg); + prot = Mprotect(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); + CHECK(prot == (void*)kShadowGap2Beg); + prot = Mprotect(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); + CHECK(prot == (void*)kShadowGap3Beg); + } else if (!kMidMemBeg && MemoryRangeIsAvailable(shadow_start, shadow_end)) { if (kLowShadowBeg != kLowShadowEnd) { // mmap the low shadow plus at least one page. ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(),