From patchwork Tue Apr 26 20:44:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 53250 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E42973858C83 for ; Tue, 26 Apr 2022 20:45:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E42973858C83 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1651005912; bh=PPYKpA9z2+/5cx1gplZztP2bmIqEsmtOgrfNa+48nXk=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=QoHRXnXFWYrALFJ/D7Ck8N2BhxLTzIwDR/3vb7/uPJenvewE5CRfyQO3radv6G1Gr PE8EqYoEQPXX8Na3owR5FyL68q0ZL2wIedy6o3xBI6usgmTGtREMNDfGVc577CbRrh l9ykuLYe6BTcL9pf87BEVuqiogEBrFRnOnaVyK3E= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 4D7D23858C83 for ; Tue, 26 Apr 2022 20:44:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4D7D23858C83 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-86-3TJ3DLIbNg6kcNGu5549sA-1; Tue, 26 Apr 2022 16:44:41 -0400 X-MC-Unique: 3TJ3DLIbNg6kcNGu5549sA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id EDC8D299E762; Tue, 26 Apr 2022 20:44:40 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AD9CA2024CC8; Tue, 26 Apr 2022 20:44:40 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 23QKibW41326086 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 26 Apr 2022 22:44:38 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 23QKiaxe1326085; Tue, 26 Apr 2022 22:44:36 +0200 Date: Tue, 26 Apr 2022 22:44:36 +0200 To: Richard Biener , Jeff Law Subject: [PATCH] asan: Fix up asan_redzone_buffer::emit_redzone_byte [PR105396] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi! On the following testcase, we have in main's frame 3 variables, some red zone padding, 4 byte d, followed by 12 bytes of red zone padding, then 8 byte b followed by 24 bytes of red zone padding, then 40 bytes c followed by some red zone padding. The intended content of shadow memory for that is (note, each byte describes 8 bytes of memory): f1 f1 f1 f1 04 f2 00 f2 f2 f2 00 00 00 00 00 f3 f3 f3 f3 f3 left red d mr b middle r c right red zone f1 is left red zone magic f2 is middle red zone magic f3 is right red zone magic 00 when all 8 bytes are accessible 01-07 when only 1 to 7 bytes are accessible followed by inaccessible bytes The -fdump-rtl-expand-details dump makes it clear that it misbehaves: Flushing rzbuffer at offset -160 with: f1 f1 f1 f1 Flushing rzbuffer at offset -128 with: 04 f2 00 00 Flushing rzbuffer at offset -128 with: 00 00 00 f2 Flushing rzbuffer at offset -96 with: f2 f2 00 00 Flushing rzbuffer at offset -64 with: 00 00 00 f3 Flushing rzbuffer at offset -32 with: f3 f3 f3 f3 In the end we end up with f1 f1 f1 f1 00 00 00 f2 f2 f2 00 00 00 00 00 f3 f3 f3 f3 f3 shadow bytes because at offset -128 there are 2 overlapping stores as asan_redzone_buffer::emit_redzone_byte has flushed the temporary 4 byte buffer in the middle. The function is called with an offset and value. If the passed offset is consecutive with the prev_offset + buffer size (off == offset), then we handle it correctly, similarly if the new offset is far enough from the old one (we then flush whatever was in the buffer and if needed add up to 3 bytes of 00 before actually pushing value. But what isn't handled correctly is when the offset isn't consecutive to what has been added last time, but it is in the same 4 byte word of shadow memory (32 bytes of actual memory), like the above case where we have consecutive 04 f2 and then skip one shadow memory byte (aka 8 bytes of real memory) and then want to emit f2. Emitting that as a store of little-endian 0x0000f204 followed by a store of 0xf2000000 to the same address doesn't work, we want to emit 0xf200f204. The following patch does that by pushing 1 or 2 00 bytes. Additionally, as a small cleanup, instead of using m_shadow_bytes.safe_push (value); flush_if_full (); in all of if, else if and else bodies it sinks those 2 stmts to the end of function as all do the same thing. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-04-26 Jakub Jelinek PR sanitizer/105396 * asan.cc (asan_redzone_buffer::emit_redzone_byte): Handle the case where offset is bigger than off but smaller than m_prev_offset + 32 bits by pushing one or more 0 bytes. Sink the m_shadow_bytes.safe_push (value); flush_if_full (); statements from all cases to the end of the function. * gcc.dg/asan/pr105396.c: New test. Jakub --- gcc/asan.cc.jj 2022-02-19 09:03:50.000000000 +0100 +++ gcc/asan.cc 2022-04-26 16:57:49.737316329 +0200 @@ -1497,10 +1497,14 @@ asan_redzone_buffer::emit_redzone_byte ( HOST_WIDE_INT off = m_prev_offset + ASAN_SHADOW_GRANULARITY * m_shadow_bytes.length (); if (off == offset) + /* Consecutive shadow memory byte. */; + else if (offset < m_prev_offset + (HOST_WIDE_INT) (ASAN_SHADOW_GRANULARITY + * RZ_BUFFER_SIZE) + && !m_shadow_bytes.is_empty ()) { - /* Consecutive shadow memory byte. */ - m_shadow_bytes.safe_push (value); - flush_if_full (); + /* Shadow memory byte with a small gap. */ + for (; off < offset; off += ASAN_SHADOW_GRANULARITY) + m_shadow_bytes.safe_push (0); } else { @@ -1521,9 +1525,9 @@ asan_redzone_buffer::emit_redzone_byte ( m_shadow_mem = adjust_address (m_shadow_mem, VOIDmode, diff >> ASAN_SHADOW_SHIFT); m_prev_offset = offset; - m_shadow_bytes.safe_push (value); - flush_if_full (); } + m_shadow_bytes.safe_push (value); + flush_if_full (); } /* Emit RTX emission of the content of the buffer. */ --- gcc/testsuite/gcc.dg/asan/pr105396.c.jj 2022-04-26 16:56:34.522348879 +0200 +++ gcc/testsuite/gcc.dg/asan/pr105396.c 2022-04-26 17:00:54.757776387 +0200 @@ -0,0 +1,19 @@ +/* PR sanitizer/105396 */ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ +/* { dg-shouldfail "asan" } */ + +int +main () +{ + int a; + int *b[1]; + int c[10]; + int d[1][1]; + for (a = 0; a < 1; a++) + d[1][a] = 0; + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } */ +/* { dg-output "WRITE of size.*" } */