From patchwork Mon Oct 14 10:36:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Wu X-Patchwork-Id: 11188211 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 0119D76 for ; Mon, 14 Oct 2019 10:36:56 +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 CEC3B20663 for ; Mon, 14 Oct 2019 10:36: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="NIhWAvVX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CEC3B20663 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=YovEHX+JWJQUtFxKvLTOMTSg2nH652cwjgKdjt07zLY=; b=NIhWAvVXGrglhV /U0f9iZdKpUyvstQYqThp0IA8ZkYW0mnpPYu/DJ3aeBucgEr+Isfb3wH6w0FAzEpld1+6R9zx4zuo JBoRv8WBoeQq6YYqnBuoaC+2IVg1QAtKcguUvcVdZMPdK+xa6p9CsV4qcfZZkS+dY33lUASCFSFRU JMnT6XRMyLaCsEiCdkgIsPEcUel0eEt8DqYEc9cUAgJMetWFwko1VCGXa/+8ohp82P7IMJLu+o9zk IY/lps1ScfePpweHHwQ2BS7pHKtvtqFJrSjC/u+HhX7tBqwrnABmsCvolzvihQg8hIzNDMYjJbBqw 0XrCh47vTlLvlrUsT41Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iJxid-0008FU-0q; Mon, 14 Oct 2019 10:36:51 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iJxiZ-0008Ej-6j; Mon, 14 Oct 2019 10:36:48 +0000 X-UUID: 23df3f6d25614978a32d93edf369bc44-20191014 X-UUID: 23df3f6d25614978a32d93edf369bc44-20191014 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1473329138; Mon, 14 Oct 2019 02:36:33 -0800 Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Mon, 14 Oct 2019 03:36:32 -0700 Received: from mtkcas08.mediatek.inc (172.21.101.126) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Mon, 14 Oct 2019 18:36:31 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Mon, 14 Oct 2019 18:36:31 +0800 From: Walter Wu To: Andrey Ryabinin , Alexander Potapenko , Dmitry Vyukov , Matthias Brugger Subject: [PATCH 1/2] kasan: detect negative size in memory operation function Date: Mon, 14 Oct 2019 18:36:32 +0800 Message-ID: <20191014103632.17930-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-20191014_033647_251782_8AF527A2 X-CRM114-Status: GOOD ( 12.39 ) 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_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches 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 KASAN missed detecting size is negative numbers in memset(), memcpy(), and memmove(), it will cause out-of-bounds bug, so needs to be detected by KASAN. If size is negative numbers, then it has three reasons to be defined as heap-out-of-bounds bug type. 1) Casting negative numbers to size_t would indeed turn up as a large size_t and its value will be larger than ULONG_MAX/2, so that this can qualify as out-of-bounds. 2) If KASAN has new bug type and user-space passes negative size, then there are duplicate reports. So don't produce new bug type in order to prevent duplicate reports by some systems (e.g. syzbot) to report the same bug twice. 3) When size is negative numbers, it may be passed from user-space. So we always print heap-out-of-bounds in order to prevent that kernel-space and user-space have the same bug but have duplicate reports. KASAN report: BUG: KASAN: heap-out-of-bounds in kmalloc_memmove_invalid_size+0x70/0xa0 Read of size 18446744073709551608 at addr ffffff8069660904 by task cat/72 CPU: 2 PID: 72 Comm: cat Not tainted 5.4.0-rc1-next-20191004ajb-00001-gdb8af2f372b2-dirty #1 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x0/0x288 show_stack+0x14/0x20 dump_stack+0x10c/0x164 print_address_description.isra.9+0x68/0x378 __kasan_report+0x164/0x1a0 kasan_report+0xc/0x18 check_memory_region+0x174/0x1d0 memmove+0x34/0x88 kmalloc_memmove_invalid_size+0x70/0xa0 [1] https://bugzilla.kernel.org/show_bug.cgi?id=199341 Signed-off-by: Walter Wu Reported -by: Dmitry Vyukov Suggested-by: Dmitry Vyukov Reviewed-by: Dmitry Vyukov --- mm/kasan/common.c | 13 ++++++++----- mm/kasan/generic.c | 5 +++++ mm/kasan/generic_report.c | 18 ++++++++++++++++++ mm/kasan/tags.c | 5 +++++ mm/kasan/tags_report.c | 18 ++++++++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 6814d6d6a023..6ef0abd27f06 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -102,7 +102,8 @@ EXPORT_SYMBOL(__kasan_check_write); #undef memset void *memset(void *addr, int c, size_t len) { - check_memory_region((unsigned long)addr, len, true, _RET_IP_); + if (!check_memory_region((unsigned long)addr, len, true, _RET_IP_)) + return NULL; return __memset(addr, c, len); } @@ -110,8 +111,9 @@ void *memset(void *addr, int c, size_t len) #undef memmove 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_); + if (!check_memory_region((unsigned long)src, len, false, _RET_IP_) || + !check_memory_region((unsigned long)dest, len, true, _RET_IP_)) + return NULL; return __memmove(dest, src, len); } @@ -119,8 +121,9 @@ void *memmove(void *dest, const void *src, size_t len) #undef memcpy void *memcpy(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_); + if (!check_memory_region((unsigned long)src, len, false, _RET_IP_) || + !check_memory_region((unsigned long)dest, len, true, _RET_IP_)) + return NULL; return __memcpy(dest, src, len); } diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index 616f9dd82d12..02148a317d27 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -173,6 +173,11 @@ static __always_inline bool check_memory_region_inline(unsigned long addr, if (unlikely(size == 0)) return true; + if (unlikely((long)size < 0)) { + kasan_report(addr, size, write, ret_ip); + return false; + } + if (unlikely((void *)addr < kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) { kasan_report(addr, size, write, ret_ip); diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c index 36c645939bc9..52a92c7db697 100644 --- a/mm/kasan/generic_report.c +++ b/mm/kasan/generic_report.c @@ -107,6 +107,24 @@ static const char *get_wild_bug_type(struct kasan_access_info *info) const char *get_bug_type(struct kasan_access_info *info) { + /* + * If access_size is negative numbers, then it has three reasons + * to be defined as heap-out-of-bounds bug type. + * 1) Casting negative numbers to size_t would indeed turn up as + * a large size_t and its value will be larger than ULONG_MAX/2, + * so that this can qualify as out-of-bounds. + * 2) If KASAN has new bug type and user-space passes negative size, + * then there are duplicate reports. So don't produce new bug type + * in order to prevent duplicate reports by some systems + * (e.g. syzbot) to report the same bug twice. + * 3) When size is negative numbers, it may be passed from user-space. + * So we always print heap-out-of-bounds in order to prevent that + * kernel-space and user-space have the same bug but have duplicate + * reports. + */ + if ((long)info->access_size < 0) + return "heap-out-of-bounds"; + if (addr_has_shadow(info->access_addr)) return get_shadow_bug_type(info); return get_wild_bug_type(info); diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c index 0e987c9ca052..b829535a3ad7 100644 --- a/mm/kasan/tags.c +++ b/mm/kasan/tags.c @@ -86,6 +86,11 @@ bool check_memory_region(unsigned long addr, size_t size, bool write, if (unlikely(size == 0)) return true; + if (unlikely((long)size < 0)) { + kasan_report(addr, size, write, ret_ip); + return false; + } + tag = get_tag((const void *)addr); /* diff --git a/mm/kasan/tags_report.c b/mm/kasan/tags_report.c index 969ae08f59d7..f7ae474aef3a 100644 --- a/mm/kasan/tags_report.c +++ b/mm/kasan/tags_report.c @@ -36,6 +36,24 @@ const char *get_bug_type(struct kasan_access_info *info) { + /* + * If access_size is negative numbers, then it has three reasons + * to be defined as heap-out-of-bounds bug type. + * 1) Casting negative numbers to size_t would indeed turn up as + * a large size_t and its value will be larger than ULONG_MAX/2, + * so that this can qualify as out-of-bounds. + * 2) If KASAN has new bug type and user-space passes negative size, + * then there are duplicate reports. So don't produce new bug type + * in order to prevent duplicate reports by some systems + * (e.g. syzbot) to report the same bug twice. + * 3) When size is negative numbers, it may be passed from user-space. + * So we always print heap-out-of-bounds in order to prevent that + * kernel-space and user-space have the same bug but have duplicate + * reports. + */ + if ((long)info->access_size < 0) + return "heap-out-of-bounds"; + #ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY struct kasan_alloc_meta *alloc_meta; struct kmem_cache *cache; From patchwork Mon Oct 14 10:36:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Wu X-Patchwork-Id: 11188221 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 8F22814E5 for ; Mon, 14 Oct 2019 10:47:14 +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 650AF20873 for ; Mon, 14 Oct 2019 10:47:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="GnthXZMi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 650AF20873 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=1xjDwQ4NdQn6cyGKxh1Oc5MWBnFqUyf8o9kPzSPT6/U=; b=GnthXZMizW99gt +K2gxhaKdhJfSPjXLZqP6UI/iFXprSDEdOtCmBmSgHz0BXddtqOp4Ue8furEAMVyEjOrpMpY1mH7X du2SIzVygem0KdolZs05mZH0mdjvKKG+bDaTPmQ/LNuc1OeDVXCEQ1nkVDOjAXXqfK69ah56udBpi FIlbWm1W+ng3ekwI5GZn8zk5vR2D9UyQ9W56UOHl4cn8R2V3zHKirza6CaSTq3GBTrrv31qJwywj7 G6I3UbMrzEp3GnBfwnRAp0QLXqWlmtHiEQeUpgO/ET0F9jsbXAmNQnsuTivcUU3CdH91onIVspnG8 sOoifYcnB+fMLo3UDtGg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iJxsd-0004UQ-Tk; Mon, 14 Oct 2019 10:47:11 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iJxsb-0004Tb-4Z; Mon, 14 Oct 2019 10:47:10 +0000 X-UUID: 7b8a2e15234b46dc86a022c63f4729d0-20191014 X-UUID: 7b8a2e15234b46dc86a022c63f4729d0-20191014 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1126863446; Mon, 14 Oct 2019 02:47:01 -0800 Received: from mtkmbs08n2.mediatek.inc (172.21.101.56) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Mon, 14 Oct 2019 03:37:00 -0700 Received: from mtkcas08.mediatek.inc (172.21.101.126) by mtkmbs08n2.mediatek.inc (172.21.101.56) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Mon, 14 Oct 2019 18:36:52 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Mon, 14 Oct 2019 18:36:52 +0800 From: Walter Wu To: Andrey Ryabinin , Alexander Potapenko , Dmitry Vyukov , Matthias Brugger Subject: [PATCH 2/2] kasan: add test for invalid size in memmove Date: Mon, 14 Oct 2019 18:36:54 +0800 Message-ID: <20191014103654.17982-1-walter-zh.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 X-TM-SNTS-SMTP: 0CF6CECFA4DBB0B2BBA0BF7B47F0B4713B9EC9875EB27669122A6B9E49B63E752000:8 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191014_034709_182800_07790608 X-CRM114-Status: UNSURE ( 8.37 ) X-CRM114-Notice: Please train this message. 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 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches 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 Test size is negative numbers in memmove in order to verify whether it correctly get KASAN report. Signed-off-by: Walter Wu --- lib/test_kasan.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/test_kasan.c b/lib/test_kasan.c index 49cc4d570a40..06942cf585cc 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -283,6 +283,23 @@ static noinline void __init kmalloc_oob_in_memset(void) kfree(ptr); } +static noinline void __init kmalloc_memmove_invalid_size(void) +{ + char *ptr; + size_t size = 64; + + pr_info("invalid size 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_uaf(void) { char *ptr; @@ -773,6 +790,7 @@ static int __init kmalloc_tests_init(void) kmalloc_oob_memset_4(); kmalloc_oob_memset_8(); kmalloc_oob_memset_16(); + kmalloc_memmove_invalid_size(); kmalloc_uaf(); kmalloc_uaf_memset(); kmalloc_uaf2();