From patchwork Fri Sep 27 03:43:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Wu X-Patchwork-Id: 11163705 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E3D6217D4 for ; Fri, 27 Sep 2019 03:43:55 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C183020863 for ; Fri, 27 Sep 2019 03:43:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="igO/Lcry" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C183020863 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=/N3VXxXoZT7gEWfYjBYnGJjVhFMRPb/ThLMytq7T62U=; b=igO/LcryGl0fGB aCyREZXyUgm5o+H+CVHUepkqhIH/wly3y1/5Kr0UNO3DzUc09OzCkF7RagAdyJVQh3H2tfBKUH5Zc zVzXMo4rLyqnJl/G1YtxP4HXPpGUlKtIX2H0ToR5rWtOx0t4gDuvVjWmgzAsTI1u3bDY0wzfnj6by shITBiUjmAUG/Il0VkjsRuvZ5x8MYxmxuzsOAsh5W+Da6xDEjAwrqrB/aj8yuF2K1cSlSu2QapV2s x5SUr4bgvtNVnWKMAk/ZsN69mhBhErLJgom+FLIAAtQFLnzE/LViXfvdT39t6/FtPLWaBbQScf0a1 rutW6HJv4X7r6t6KaflQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.2 #3 (Red Hat Linux)) id 1iDhAg-0004uZ-0w; Fri, 27 Sep 2019 03:43:54 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.92.2 #3 (Red Hat Linux)) id 1iDhAc-0004u6-JT; Fri, 27 Sep 2019 03:43:52 +0000 X-UUID: a227aa22d2b94251a29de5cadf5bf977-20190926 X-UUID: a227aa22d2b94251a29de5cadf5bf977-20190926 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1113642830; Thu, 26 Sep 2019 19:43:41 -0800 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Thu, 26 Sep 2019 20:43:41 -0700 Received: from mtkcas07.mediatek.inc (172.21.101.84) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Fri, 27 Sep 2019 11:43:39 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Fri, 27 Sep 2019 11:43:39 +0800 From: Walter Wu To: Andrey Ryabinin , Alexander Potapenko , Dmitry Vyukov , Matthias Brugger Subject: [PATCH] kasan: fix the missing underflow in memmove and memcpy with CONFIG_KASAN_GENERIC=y Date: Fri, 27 Sep 2019 11:43:38 +0800 Message-ID: <20190927034338.15813-1-walter-zh.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190926_204350_644939_A6250459 X-CRM114-Status: GOOD ( 11.31 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [216.200.240.184 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Walter Wu , wsd_upstream@mediatek.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, linux-mm@kvack.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org memmove() and memcpy() have missing underflow issues. When -7 <= size < 0, then KASAN will miss to catch the underflow issue. It looks like shadow start address and shadow end address is the same, so it does not actually check anything. The following test is indeed not caught by KASAN: char *p = kmalloc(64, GFP_KERNEL); memset((char *)p, 0, 64); memmove((char *)p, (char *)p + 4, -2); kfree((char*)p); It should be checked here: void *memmove(void *dest, const void *src, size_t len) { check_memory_region((unsigned long)src, len, false, _RET_IP_); check_memory_region((unsigned long)dest, len, true, _RET_IP_); return __memmove(dest, src, len); } We fix the shadow end address which is calculated, then generic KASAN get the right shadow end address and detect this underflow issue. [1] https://bugzilla.kernel.org/show_bug.cgi?id=199341 Signed-off-by: Walter Wu Reported-by: Dmitry Vyukov --- lib/test_kasan.c | 36 ++++++++++++++++++++++++++++++++++++ mm/kasan/generic.c | 8 ++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/test_kasan.c b/lib/test_kasan.c index b63b367a94e8..8bd014852556 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -280,6 +280,40 @@ static noinline void __init kmalloc_oob_in_memset(void) kfree(ptr); } +static noinline void __init kmalloc_oob_in_memmove_underflow(void) +{ + char *ptr; + size_t size = 64; + + pr_info("underflow out-of-bounds in memmove\n"); + ptr = kmalloc(size, GFP_KERNEL); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset((char *)ptr, 0, 64); + memmove((char *)ptr, (char *)ptr + 4, -2); + kfree(ptr); +} + +static noinline void __init kmalloc_oob_in_memmove_overflow(void) +{ + char *ptr; + size_t size = 64; + + pr_info("overflow out-of-bounds in memmove\n"); + ptr = kmalloc(size, GFP_KERNEL); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset((char *)ptr, 0, 64); + memmove((char *)ptr + size, (char *)ptr, 2); + kfree(ptr); +} + static noinline void __init kmalloc_uaf(void) { char *ptr; @@ -734,6 +768,8 @@ static int __init kmalloc_tests_init(void) kmalloc_oob_memset_4(); kmalloc_oob_memset_8(); kmalloc_oob_memset_16(); + kmalloc_oob_in_memmove_underflow(); + kmalloc_oob_in_memmove_overflow(); kmalloc_uaf(); kmalloc_uaf_memset(); kmalloc_uaf2(); diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index 616f9dd82d12..34ca23d59e67 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -131,9 +131,13 @@ static __always_inline bool memory_is_poisoned_n(unsigned long addr, size_t size) { unsigned long ret; + void *shadow_start = kasan_mem_to_shadow((void *)addr); + void *shadow_end = kasan_mem_to_shadow((void *)addr + size - 1) + 1; - ret = memory_is_nonzero(kasan_mem_to_shadow((void *)addr), - kasan_mem_to_shadow((void *)addr + size - 1) + 1); + if ((long)size < 0) + shadow_end = kasan_mem_to_shadow((void *)addr + size); + + ret = memory_is_nonzero(shadow_start, shadow_end); if (unlikely(ret)) { unsigned long last_byte = addr + size - 1;