From patchwork Sun May 30 04:47:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuan-Ying Lee X-Patchwork-Id: 12288073 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DC12C4708C for ; Sun, 30 May 2021 04:47:17 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 3051B61107 for ; Sun, 30 May 2021 04:47:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3051B61107 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id AE7246B006E; Sun, 30 May 2021 00:47:16 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id ABCDB6B0070; Sun, 30 May 2021 00:47:16 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9365D6B0071; Sun, 30 May 2021 00:47:16 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0248.hostedemail.com [216.40.44.248]) by kanga.kvack.org (Postfix) with ESMTP id 5E6666B006E for ; Sun, 30 May 2021 00:47:16 -0400 (EDT) Received: from smtpin26.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id DEFAE8249980 for ; Sun, 30 May 2021 04:47:15 +0000 (UTC) X-FDA: 78196663230.26.074D755 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) by imf17.hostedemail.com (Postfix) with ESMTP id 8EF494202A0C for ; Sun, 30 May 2021 04:47:08 +0000 (UTC) Received: by mail-pl1-f182.google.com with SMTP id 11so60034plk.12 for ; Sat, 29 May 2021 21:47:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iF5+piAFy1H+gDGG26ovo/7bII1xMjc8kc5KVtIH7A0=; b=tuhSD2ZsKhjXfMbK2hbROiILRtH2bDaVw3+Mh5RkfuTk2M9lgJbitrREpNNZn4cdaq /VdYZ17bwQ1VHDxGY/Q1mPbzpGgZzK7ue/WacXcLrtrriXP2X5q97Xn5Qvxoxx4hT1oo uhCRS8b/ESaet7BMEv4idV+/mYlhNcdM/gb0jAwiAbtMJTO59UX0rhm7qHawdLu7jpbd 7OljVKzSfT6OQfuHFiHPQZyzsFGs020jfX1UYO38g1V9JS+BgWUOJmRn2YXLq7t5thKd he3aRf5iCyo2bqjkfAgcQX1PHbBLtVu9dK7dy5now6pWy5D0z0tUwQ3RoPlWaWhhtZE8 nP0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iF5+piAFy1H+gDGG26ovo/7bII1xMjc8kc5KVtIH7A0=; b=G6/zQ931Vnu0XyNzR8o8h/6gX+zto2daHuuT4cgXAtfow1zsr3wjJlAH5XVzV5lZIh 4b/xqkWoUMO2pH0jrXNXs+nfSbU57yyIYtsl4T2fVBPiBvwwmb0EkBu8X9wEtfQRS2MW og3zXcy9htUwtnZ1HZc0BJRThEKzKtmMshswmyKmq60FSwI66MgbQ+6Auq2uj0f5Ir4u Ccxa8fxJAQkfeNn6NTs7aXhszWApzRqJcu6paXZq4kmmbb5suufpMCtw8F0ri6ViZpA1 YQSNh7/lOvkmDSggYlfb8wVNPBBEHDqzzmmIgQy5n+LrG0pBoSD82JbpEz0N9Lghj76K Evtw== X-Gm-Message-State: AOAM531APBzCFdvRoZCOVgQ0v+AECn9YFGmrSptU1YomjWVoGCQ8SCam PIGnN0GmgANCBYFzK0QrQBk= X-Google-Smtp-Source: ABdhPJwWFUxscK7TYaPSXHdNGMmeiXSBk/y8Q4Df+WenEGiACPYGesObTacCFgCnhHcIiI5K0V7qpg== X-Received: by 2002:a17:90a:4404:: with SMTP id s4mr12768266pjg.218.1622350034746; Sat, 29 May 2021 21:47:14 -0700 (PDT) Received: from localhost.localdomain (61-230-18-203.dynamic-ip.hinet.net. [61.230.18.203]) by smtp.gmail.com with ESMTPSA id t1sm7471108pjo.33.2021.05.29.21.47.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 May 2021 21:47:14 -0700 (PDT) From: Kuan-Ying Lee To: Andrey Ryabinin , Alexander Potapenko , Andrey Konovalov , Dmitry Vyukov , Andrew Morton Cc: kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Walter Wu , Kuan-Ying Lee Subject: [PATCH 1/1] kasan: add memory corruption identification for hardware tag-based mode Date: Sun, 30 May 2021 12:47:08 +0800 Message-Id: <20210530044708.7155-2-kylee0686026@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210530044708.7155-1-kylee0686026@gmail.com> References: <20210530044708.7155-1-kylee0686026@gmail.com> X-Rspamd-Queue-Id: 8EF494202A0C Authentication-Results: imf17.hostedemail.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=tuhSD2Zs; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf17.hostedemail.com: domain of kylee0686026@gmail.com designates 209.85.214.182 as permitted sender) smtp.mailfrom=kylee0686026@gmail.com X-Rspamd-Server: rspam03 X-Stat-Signature: krro6k3aeroekmbcy6wqqmzmn3zdx88b X-HE-Tag: 1622350028-83914 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Add memory corruption identification at bug report for hardware tag-based mode. The report shows whether it is "use-after-free" or "out-of-bound" error instead of "invalid-access" error. This will make it easier for programmers to see the memory corruption problem. We extend the slab to store five old free pointer tag and free backtrace, we can check if the tagged address is in the slab record and make a good guess if the object is more like "use-after-free" or "out-of-bound". therefore every slab memory corruption can be identified whether it's "use-after-free" or "out-of-bound". Signed-off-by: Kuan-Ying Lee --- lib/Kconfig.kasan | 8 ++++++++ mm/kasan/hw_tags.c | 25 ++++++++++++++++++++++--- mm/kasan/kasan.h | 4 ++-- mm/kasan/report_hw_tags.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index cffc2ebbf185..f7e666b23058 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -163,6 +163,14 @@ config KASAN_SW_TAGS_IDENTIFY (use-after-free or out-of-bounds) at the cost of increased memory consumption. +config KASAN_HW_TAGS_IDENTIFY + bool "Enable memory corruption identification" + depends on KASAN_HW_TAGS + help + This option enables best-effort identification of bug type + (use-after-free or out-of-bounds) at the cost of increased + memory consumption. + config KASAN_VMALLOC bool "Back mappings in vmalloc space with real shadow memory" depends on KASAN_GENERIC && HAVE_ARCH_KASAN_VMALLOC diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c index 4004388b4e4b..b1c6bb116600 100644 --- a/mm/kasan/hw_tags.c +++ b/mm/kasan/hw_tags.c @@ -220,22 +220,41 @@ void kasan_set_free_info(struct kmem_cache *cache, void *object, u8 tag) { struct kasan_alloc_meta *alloc_meta; + u8 idx = 0; alloc_meta = kasan_get_alloc_meta(cache, object); - if (alloc_meta) - kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT); + if (!alloc_meta) + return; + +#ifdef CONFIG_KASAN_HW_TAGS_IDENTIFY + idx = alloc_meta->free_track_idx; + alloc_meta->free_pointer_tag[idx] = tag; + alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS; +#endif + + kasan_set_track(&alloc_meta->free_track[idx], GFP_NOWAIT); } struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, void *object, u8 tag) { struct kasan_alloc_meta *alloc_meta; + int i = 0; alloc_meta = kasan_get_alloc_meta(cache, object); if (!alloc_meta) return NULL; - return &alloc_meta->free_track[0]; +#ifdef CONFIG_KASAN_HW_TAGS_IDENTIFY + for (i = 0; i < KASAN_NR_FREE_STACKS; i++) { + if (alloc_meta->free_pointer_tag[i] == tag) + break; + } + if (i == KASAN_NR_FREE_STACKS) + i = alloc_meta->free_track_idx; +#endif + + return &alloc_meta->free_track[i]; } #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 8f450bc28045..41b47f456130 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -153,7 +153,7 @@ struct kasan_track { depot_stack_handle_t stack; }; -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY +#if defined(CONFIG_KASAN_SW_TAGS_IDENTIFY) || defined(CONFIG_KASAN_HW_TAGS_IDENTIFY) #define KASAN_NR_FREE_STACKS 5 #else #define KASAN_NR_FREE_STACKS 1 @@ -170,7 +170,7 @@ struct kasan_alloc_meta { #else struct kasan_track free_track[KASAN_NR_FREE_STACKS]; #endif -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY +#if defined(CONFIG_KASAN_SW_TAGS_IDENTIFY) || defined(CONFIG_KASAN_HW_TAGS_IDENTIFY) u8 free_pointer_tag[KASAN_NR_FREE_STACKS]; u8 free_track_idx; #endif diff --git a/mm/kasan/report_hw_tags.c b/mm/kasan/report_hw_tags.c index 42b2168755d6..d77109b85a09 100644 --- a/mm/kasan/report_hw_tags.c +++ b/mm/kasan/report_hw_tags.c @@ -14,9 +14,37 @@ #include #include "kasan.h" +#include "../slab.h" const char *kasan_get_bug_type(struct kasan_access_info *info) { +#ifdef CONFIG_KASAN_HW_TAGS_IDENTIFY + struct kasan_alloc_meta *alloc_meta; + struct kmem_cache *cache; + struct page *page; + const void *addr; + void *object; + u8 tag; + int i; + + tag = get_tag(info->access_addr); + addr = kasan_reset_tag(info->access_addr); + page = kasan_addr_to_page(addr); + if (page && PageSlab(page)) { + cache = page->slab_cache; + object = nearest_obj(cache, page, (void *)addr); + alloc_meta = kasan_get_alloc_meta(cache, object); + + if (alloc_meta) { + for (i = 0; i < KASAN_NR_FREE_STACKS; i++) { + if (alloc_meta->free_pointer_tag[i] == tag) + return "use-after-free"; + } + } + return "out-of-bounds"; + } + +#endif return "invalid-access"; }