From patchwork Thu Oct 17 01:25:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 11194621 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 8BD831668 for ; Thu, 17 Oct 2019 01:25:23 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 304A221A49 for ; Thu, 17 Oct 2019 01:25:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=axtens.net header.i=@axtens.net header.b="Row3BVm4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 304A221A49 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 4DBC28E0007; Wed, 16 Oct 2019 21:25:22 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 48D268E0001; Wed, 16 Oct 2019 21:25:22 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 355FC8E0007; Wed, 16 Oct 2019 21:25:22 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0173.hostedemail.com [216.40.44.173]) by kanga.kvack.org (Postfix) with ESMTP id 0DF6F8E0001 for ; Wed, 16 Oct 2019 21:25:22 -0400 (EDT) Received: from smtpin04.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id A8E705DEE for ; Thu, 17 Oct 2019 01:25:21 +0000 (UTC) X-FDA: 76051533642.04.mice53_4bc129555f704 X-Spam-Summary: 2,0,0,7b6c78fe514c6bfb,d41d8cd98f00b204,dja@axtens.net,:kasan-dev@googlegroups.com::x86@kernel.org:aryabinin@virtuozzo.com:glider@google.com:luto@kernel.org:linux-kernel@vger.kernel.org:mark.rutland@arm.com:dvyukov@google.com:christophe.leroy@c-s.fr:linuxppc-dev@lists.ozlabs.org:gor@linux.ibm.com:dja@axtens.net,RULES_HIT:41:69:327:355:379:541:800:960:966:967:968:973:988:989:1260:1311:1314:1345:1359:1431:1437:1515:1605:1730:1747:1777:1792:1801:1981:2194:2196:2198:2199:2200:2201:2393:2525:2553:2559:2563:2682:2685:2689:2693:2731:2736:2740:2859:2901:2902:2903:2904:2918:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3743:3865:3866:3867:3868:3870:3871:3872:3873:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4250:4321:4385:4605:5007:6119:6261:6653:6691:7875:7903:7904:8603:8660:9025:9036:9121:10004:11026:11232:11233:11473:11658:11914:12043:12048:12291:12296:12297:12438:12517:12519:12555:12663:12679:12683:12698:12737:12895:12986:13146:131 48:13153 X-HE-Tag: mice53_4bc129555f704 X-Filterd-Recvd-Size: 27602 Received: from mail-pf1-f195.google.com (mail-pf1-f195.google.com [209.85.210.195]) by imf09.hostedemail.com (Postfix) with ESMTP for ; Thu, 17 Oct 2019 01:25:20 +0000 (UTC) Received: by mail-pf1-f195.google.com with SMTP id x127so506409pfb.7 for ; Wed, 16 Oct 2019 18:25:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WlOCKK/87ao2YHg1b+fMfj/LaWGJtfOKqzSoMaiSqF4=; b=Row3BVm4DVbKWhjvDdMAPMmLP3ujE2nJY4Ak3MwfE6jcWDfqcMGQxmq3fpfyYjWMpb YHPy/nOM1ZurMLnbdC6yd2y7hEzCSosQLnAl32IOZIXfxXztLY2p9HvsoaX6A0zA+Hfy Zhrgg+tfSOObtS0XZoZ5ug69fGmNnOQbTALAs= 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:mime-version:content-transfer-encoding; bh=WlOCKK/87ao2YHg1b+fMfj/LaWGJtfOKqzSoMaiSqF4=; b=SDL3eCDEfILpXf0EDBJ/fP0uLEXTPklMZP4G1Ozydw+ox7BUyJDijPnF5inwDfZieB BpUGYw3lRyXKvjC3ayaj0WLLCa40K7PzgI6ydapjo++L6X2aPX+R/4argwUBwobwBxw5 IA6ioepUkkugrU4NHxSJb3jXkkJphb3vKNdGo4JjSE/6ujq0tvGV8BL0Y3DX4lzSufO3 vSnlleeC1tYDa6Ak0QFExykYYhdzwVecE1YH1/bwc7tVoXZtifKw6PXw1ejmWwP0q/Db 3mzOaJc1xYugDtSKF1LdszY8/iksET0T7x5WDftHZWenZ5oN8FSLylADM72YIdXRRPm/ 2GtA== X-Gm-Message-State: APjAAAUPDvvrfKPcwv5+rXbpsOE9o4sfrPrE2J/urqli9VQO7qPJ2CBo KJhwwQpTeJ6C2JuRoXGivfay6w== X-Google-Smtp-Source: APXvYqwFfIEp4zaxhZk5gkvUN/m2xdHyRnlS5AhgxThgNkcmDlHdgbyzn8CoJecqqXNw2hIQUbb/nQ== X-Received: by 2002:a63:ff08:: with SMTP id k8mr1228826pgi.8.1571275518486; Wed, 16 Oct 2019 18:25:18 -0700 (PDT) Received: from localhost (ppp167-251-205.static.internode.on.net. [59.167.251.205]) by smtp.gmail.com with ESMTPSA id d2sm282660pgq.74.2019.10.16.18.25.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2019 18:25:17 -0700 (PDT) From: Daniel Axtens To: kasan-dev@googlegroups.com, linux-mm@kvack.org, x86@kernel.org, aryabinin@virtuozzo.com, glider@google.com, luto@kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, dvyukov@google.com, christophe.leroy@c-s.fr Cc: linuxppc-dev@lists.ozlabs.org, gor@linux.ibm.com, Daniel Axtens Subject: [PATCH v9 1/5] kasan: support backing vmalloc space with real shadow memory Date: Thu, 17 Oct 2019 12:25:02 +1100 Message-Id: <20191017012506.28503-2-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017012506.28503-1-dja@axtens.net> References: <20191017012506.28503-1-dja@axtens.net> MIME-Version: 1.0 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: Hook into vmalloc and vmap, and dynamically allocate real shadow memory to back the mappings. Most mappings in vmalloc space are small, requiring less than a full page of shadow space. Allocating a full shadow page per mapping would therefore be wasteful. Furthermore, to ensure that different mappings use different shadow pages, mappings would have to be aligned to KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE. Instead, share backing space across multiple mappings. Allocate a backing page when a mapping in vmalloc space uses a particular page of the shadow region. This page can be shared by other vmalloc mappings later on. We hook in to the vmap infrastructure to lazily clean up unused shadow memory. To avoid the difficulties around swapping mappings around, this code expects that the part of the shadow region that covers the vmalloc space will not be covered by the early shadow page, but will be left unmapped. This will require changes in arch-specific code. This allows KASAN with VMAP_STACK, and may be helpful for architectures that do not have a separate module space (e.g. powerpc64, which I am currently working on). It also allows relaxing the module alignment back to PAGE_SIZE. Link: https://bugzilla.kernel.org/show_bug.cgi?id=202009 Acked-by: Vasily Gorbik Co-developed-by: Mark Rutland Signed-off-by: Mark Rutland [shadow rework] Signed-off-by: Daniel Axtens --- [I haven't tried to resolve the question of spurious faults. My understanding is that in order to see the issue, you'd need to: a) on CPU 0, allocate shadow memory for memory in the vmalloc or module region, where the allocation is located at a fixed address, and b) on CPU 1, access that shadow memory via the fixed address (to avoid the dependency that would otherwise require the correct ordering) If this is an issue on x86, we can fix it in the x86 enablement patch. Hopefully someone from x86land can let us know.] v2: let kasan_unpoison_shadow deal with ranges that do not use a full shadow byte. v3: relax module alignment rename to kasan_populate_vmalloc which is a much better name deal with concurrency correctly v4: Mark's rework Poision pages on vfree Handle allocation failures v5: Per Christophe Leroy, split out test and dynamically free pages. v6: Guard freeing page properly. Drop WARN_ON_ONCE(pte_none(*ptep)), on reflection it's unnecessary debugging cruft with too high a false positive rate. v7: tlb flush, thanks Mark. explain more clearly how freeing works and is concurrency-safe. v9: - Pull in Uladzislau Rezki's changes to better line up with the design of the new vmalloc implementation. Thanks Vlad. - clarify comment explaining smp_wmb() per Mark and Andrey's discussion - tighten up the allocation of backing memory so that it only happens for vmalloc or module space allocations. Thanks Andrey Ryabinin. - A TLB flush in the freeing path, thanks Mark Rutland. --- Documentation/dev-tools/kasan.rst | 63 +++++++++ include/linux/kasan.h | 31 +++++ include/linux/moduleloader.h | 2 +- include/linux/vmalloc.h | 12 ++ lib/Kconfig.kasan | 16 +++ mm/kasan/common.c | 211 ++++++++++++++++++++++++++++++ mm/kasan/generic_report.c | 3 + mm/kasan/kasan.h | 1 + mm/vmalloc.c | 48 ++++++- 9 files changed, 381 insertions(+), 6 deletions(-) diff --git Documentation/dev-tools/kasan.rst Documentation/dev-tools/kasan.rst index 525296121d89..e4d66e7c50de 100644 --- Documentation/dev-tools/kasan.rst +++ Documentation/dev-tools/kasan.rst @@ -218,3 +218,66 @@ brk handler is used to print bug reports. A potential expansion of this mode is a hardware tag-based mode, which would use hardware memory tagging support instead of compiler instrumentation and manual shadow memory manipulation. + +What memory accesses are sanitised by KASAN? +-------------------------------------------- + +The kernel maps memory in a number of different parts of the address +space. This poses something of a problem for KASAN, which requires +that all addresses accessed by instrumented code have a valid shadow +region. + +The range of kernel virtual addresses is large: there is not enough +real memory to support a real shadow region for every address that +could be accessed by the kernel. + +By default +~~~~~~~~~~ + +By default, architectures only map real memory over the shadow region +for the linear mapping (and potentially other small areas). For all +other areas - such as vmalloc and vmemmap space - a single read-only +page is mapped over the shadow area. This read-only shadow page +declares all memory accesses as permitted. + +This presents a problem for modules: they do not live in the linear +mapping, but in a dedicated module space. By hooking in to the module +allocator, KASAN can temporarily map real shadow memory to cover +them. This allows detection of invalid accesses to module globals, for +example. + +This also creates an incompatibility with ``VMAP_STACK``: if the stack +lives in vmalloc space, it will be shadowed by the read-only page, and +the kernel will fault when trying to set up the shadow data for stack +variables. + +CONFIG_KASAN_VMALLOC +~~~~~~~~~~~~~~~~~~~~ + +With ``CONFIG_KASAN_VMALLOC``, KASAN can cover vmalloc space at the +cost of greater memory usage. Currently this is only supported on x86. + +This works by hooking into vmalloc and vmap, and dynamically +allocating real shadow memory to back the mappings. + +Most mappings in vmalloc space are small, requiring less than a full +page of shadow space. Allocating a full shadow page per mapping would +therefore be wasteful. Furthermore, to ensure that different mappings +use different shadow pages, mappings would have to be aligned to +``KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE``. + +Instead, we share backing space across multiple mappings. We allocate +a backing page when a mapping in vmalloc space uses a particular page +of the shadow region. This page can be shared by other vmalloc +mappings later on. + +We hook in to the vmap infrastructure to lazily clean up unused shadow +memory. + +To avoid the difficulties around swapping mappings around, we expect +that the part of the shadow region that covers the vmalloc space will +not be covered by the early shadow page, but will be left +unmapped. This will require changes in arch-specific code. + +This allows ``VMAP_STACK`` support on x86, and can simplify support of +architectures that do not have a fixed module region. diff --git include/linux/kasan.h include/linux/kasan.h index cc8a03cc9674..4f404c565db1 100644 --- include/linux/kasan.h +++ include/linux/kasan.h @@ -70,8 +70,18 @@ struct kasan_cache { int free_meta_offset; }; +/* + * These functions provide a special case to support backing module + * allocations with real shadow memory. With KASAN vmalloc, the special + * case is unnecessary, as the work is handled in the generic case. + */ +#ifndef CONFIG_KASAN_VMALLOC int kasan_module_alloc(void *addr, size_t size); void kasan_free_shadow(const struct vm_struct *vm); +#else +static inline int kasan_module_alloc(void *addr, size_t size) { return 0; } +static inline void kasan_free_shadow(const struct vm_struct *vm) {} +#endif int kasan_add_zero_shadow(void *start, unsigned long size); void kasan_remove_zero_shadow(void *start, unsigned long size); @@ -194,4 +204,25 @@ static inline void *kasan_reset_tag(const void *addr) #endif /* CONFIG_KASAN_SW_TAGS */ +#ifdef CONFIG_KASAN_VMALLOC +int kasan_populate_vmalloc(unsigned long requested_size, + struct vm_struct *area); +void kasan_poison_vmalloc(void *start, unsigned long size); +void kasan_release_vmalloc(unsigned long start, unsigned long end, + unsigned long free_region_start, + unsigned long free_region_end); +#else +static inline int kasan_populate_vmalloc(unsigned long requested_size, + struct vm_struct *area) +{ + return 0; +} + +static inline void kasan_poison_vmalloc(void *start, unsigned long size) {} +static inline void kasan_release_vmalloc(unsigned long start, + unsigned long end, + unsigned long free_region_start, + unsigned long free_region_end) {} +#endif + #endif /* LINUX_KASAN_H */ diff --git include/linux/moduleloader.h include/linux/moduleloader.h index 5229c18025e9..ca92aea8a6bd 100644 --- include/linux/moduleloader.h +++ include/linux/moduleloader.h @@ -91,7 +91,7 @@ void module_arch_cleanup(struct module *mod); /* Any cleanup before freeing mod->module_init */ void module_arch_freeing_init(struct module *mod); -#ifdef CONFIG_KASAN +#if defined(CONFIG_KASAN) && !defined(CONFIG_KASAN_VMALLOC) #include #define MODULE_ALIGN (PAGE_SIZE << KASAN_SHADOW_SCALE_SHIFT) #else diff --git include/linux/vmalloc.h include/linux/vmalloc.h index 4e7809408073..61c43d1a29ca 100644 --- include/linux/vmalloc.h +++ include/linux/vmalloc.h @@ -22,6 +22,18 @@ struct notifier_block; /* in notifier.h */ #define VM_UNINITIALIZED 0x00000020 /* vm_struct is not fully initialized */ #define VM_NO_GUARD 0x00000040 /* don't add guard page */ #define VM_KASAN 0x00000080 /* has allocated kasan shadow memory */ + +/* + * VM_KASAN is used slighly differently depending on CONFIG_KASAN_VMALLOC. + * + * If IS_ENABLED(CONFIG_KASAN_VMALLOC), VM_KASAN is set on a vm_struct after + * shadow memory has been mapped. It's used to handle allocation errors so that + * we don't try to poision shadow on free if it was never allocated. + * + * Otherwise, VM_KASAN is set for kasan_module_alloc() allocations and used to + * determine which allocations need the module shadow freed. + */ + /* * Memory with VM_FLUSH_RESET_PERMS cannot be freed in an interrupt or with * vfree_atomic(). diff --git lib/Kconfig.kasan lib/Kconfig.kasan index 6c9682ce0254..81f5464ea9e1 100644 --- lib/Kconfig.kasan +++ lib/Kconfig.kasan @@ -6,6 +6,9 @@ config HAVE_ARCH_KASAN config HAVE_ARCH_KASAN_SW_TAGS bool +config HAVE_ARCH_KASAN_VMALLOC + bool + config CC_HAS_KASAN_GENERIC def_bool $(cc-option, -fsanitize=kernel-address) @@ -142,6 +145,19 @@ config KASAN_SW_TAGS_IDENTIFY (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 && HAVE_ARCH_KASAN_VMALLOC + help + By default, the shadow region for vmalloc space is the read-only + zero page. This means that KASAN cannot detect errors involving + vmalloc space. + + Enabling this option will hook in to vmap/vmalloc and back those + mappings with real shadow memory allocated on demand. This allows + for KASAN to detect more sorts of errors (and to support vmapped + stacks), but at the cost of higher memory usage. + config TEST_KASAN tristate "Module for testing KASAN for bug detection" depends on m && KASAN diff --git mm/kasan/common.c mm/kasan/common.c index 6814d6d6a023..81521d180bec 100644 --- mm/kasan/common.c +++ mm/kasan/common.c @@ -36,6 +36,8 @@ #include #include +#include + #include "kasan.h" #include "../slab.h" @@ -590,6 +592,7 @@ void kasan_kfree_large(void *ptr, unsigned long ip) /* The object will be poisoned by page_alloc. */ } +#ifndef CONFIG_KASAN_VMALLOC int kasan_module_alloc(void *addr, size_t size) { void *ret; @@ -625,6 +628,7 @@ void kasan_free_shadow(const struct vm_struct *vm) if (vm->flags & VM_KASAN) vfree(kasan_mem_to_shadow(vm->addr)); } +#endif extern void __kasan_report(unsigned long addr, size_t size, bool is_write, unsigned long ip); @@ -744,3 +748,210 @@ static int __init kasan_memhotplug_init(void) core_initcall(kasan_memhotplug_init); #endif + +#ifdef CONFIG_KASAN_VMALLOC +static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr, + void *unused) +{ + unsigned long page; + pte_t pte; + + if (likely(!pte_none(*ptep))) + return 0; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + memset((void *)page, KASAN_VMALLOC_INVALID, PAGE_SIZE); + pte = pfn_pte(PFN_DOWN(__pa(page)), PAGE_KERNEL); + + /* + * This barrier is to ensure that the poisoning is fully written out + * and visible to other CPUs before setting the PTE. + * + * We're relying on the absence of a TLB entry preventing another CPU + * from loading the corresponding shadow shadow memory until its PTE + * has been populated (after the poisioning is visible). Consequently + * there is no barrier on the other side, and just a control-dependency + * (which would be insufficient on its own). + */ + smp_wmb(); + + spin_lock(&init_mm.page_table_lock); + if (likely(pte_none(*ptep))) { + set_pte_at(&init_mm, addr, ptep, pte); + page = 0; + } + spin_unlock(&init_mm.page_table_lock); + if (page) + free_page(page); + return 0; +} + +int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area) +{ + unsigned long shadow_start, shadow_end; + int ret; + + shadow_start = (unsigned long)kasan_mem_to_shadow(area->addr); + shadow_start = ALIGN_DOWN(shadow_start, PAGE_SIZE); + shadow_end = (unsigned long)kasan_mem_to_shadow(area->addr + + area->size); + shadow_end = ALIGN(shadow_end, PAGE_SIZE); + + ret = apply_to_page_range(&init_mm, shadow_start, + shadow_end - shadow_start, + kasan_populate_vmalloc_pte, NULL); + if (ret) + return ret; + + kasan_unpoison_shadow(area->addr, requested_size); + + area->flags |= VM_KASAN; + + return 0; +} + +/* + * Poison the shadow for a vmalloc region. Called as part of the + * freeing process at the time the region is freed. + */ +void kasan_poison_vmalloc(void *start, unsigned long size) +{ + size = round_up(size, KASAN_SHADOW_SCALE_SIZE); + kasan_poison_shadow(start, size, KASAN_VMALLOC_INVALID); +} + +static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr, + void *unused) +{ + unsigned long page; + + page = (unsigned long)__va(pte_pfn(*ptep) << PAGE_SHIFT); + + spin_lock(&init_mm.page_table_lock); + + if (likely(!pte_none(*ptep))) { + pte_clear(&init_mm, addr, ptep); + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); + free_page(page); + } + spin_unlock(&init_mm.page_table_lock); + + return 0; +} + +/* + * Release the backing for the vmalloc region [start, end), which + * lies within the free region [free_region_start, free_region_end). + * + * This can be run lazily, long after the region was freed. It runs + * under vmap_area_lock, so it's not safe to interact with the vmalloc/vmap + * infrastructure. + * + * How does this work? + * ------------------- + * + * We have a region that is page aligned, labelled as A. + * That might not map onto the shadow in a way that is page-aligned: + * + * start end + * v v + * |????????|????????|AAAAAAAA|AA....AA|AAAAAAAA|????????| < vmalloc + * -------- -------- -------- -------- -------- + * | | | | | + * | | | /-------/ | + * \-------\|/------/ |/---------------/ + * ||| || + * |??AAAAAA|AAAAAAAA|AA??????| < shadow + * (1) (2) (3) + * + * First we align the start upwards and the end downwards, so that the + * shadow of the region aligns with shadow page boundaries. In the + * example, this gives us the shadow page (2). This is the shadow entirely + * covered by this allocation. + * + * Then we have the tricky bits. We want to know if we can free the + * partially covered shadow pages - (1) and (3) in the example. For this, + * we are given the start and end of the free region that contains this + * allocation. Extending our previous example, we could have: + * + * free_region_start free_region_end + * | start end | + * v v v v + * |FFFFFFFF|FFFFFFFF|AAAAAAAA|AA....AA|AAAAAAAA|FFFFFFFF| < vmalloc + * -------- -------- -------- -------- -------- + * | | | | | + * | | | /-------/ | + * \-------\|/------/ |/---------------/ + * ||| || + * |FFAAAAAA|AAAAAAAA|AAF?????| < shadow + * (1) (2) (3) + * + * Once again, we align the start of the free region up, and the end of + * the free region down so that the shadow is page aligned. So we can free + * page (1) - we know no allocation currently uses anything in that page, + * because all of it is in the vmalloc free region. But we cannot free + * page (3), because we can't be sure that the rest of it is unused. + * + * We only consider pages that contain part of the original region for + * freeing: we don't try to free other pages from the free region or we'd + * end up trying to free huge chunks of virtual address space. + * + * Concurrency + * ----------- + * + * How do we know that we're not freeing a page that is simultaneously + * being used for a fresh allocation in kasan_populate_vmalloc(_pte)? + * + * We _can_ have kasan_release_vmalloc and kasan_populate_vmalloc running + * at the same time. While we run under vmap_area_lock, the population + * code does not: alloc_vmap_area and the per-cpu allocator both take the + * lock before calling __alloc_vmap_area to identify and reserve a region, + * and both release the lock before we call kasan_populate_vmalloc. + * + * vmap_area_lock instead operates to ensure that the larger range + * [free_region_start, free_region_end) is safe: because __alloc_vmap_area + * is excluded, no space identified as free will become non-free while we + * are running. This means that so long as we are careful with alignment + * and only free shadow pages entirely covered by the free region, we will + * not run in to trouble - any simultaneous allocations will be for + * disjoint regions. + */ +void kasan_release_vmalloc(unsigned long start, unsigned long end, + unsigned long free_region_start, + unsigned long free_region_end) +{ + void *shadow_start, *shadow_end; + unsigned long region_start, region_end; + + region_start = ALIGN(start, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); + region_end = ALIGN_DOWN(end, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); + + free_region_start = ALIGN(free_region_start, + PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); + + if (start != region_start && + free_region_start < region_start) + region_start -= PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE; + + free_region_end = ALIGN_DOWN(free_region_end, + PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); + + if (end != region_end && + free_region_end > region_end) + region_end += PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE; + + shadow_start = kasan_mem_to_shadow((void *)region_start); + shadow_end = kasan_mem_to_shadow((void *)region_end); + + if (shadow_end > shadow_start) { + apply_to_page_range(&init_mm, (unsigned long)shadow_start, + (unsigned long)(shadow_end - shadow_start), + kasan_depopulate_vmalloc_pte, NULL); + flush_tlb_kernel_range((unsigned long)shadow_start, + (unsigned long)shadow_end); + } +} +#endif diff --git mm/kasan/generic_report.c mm/kasan/generic_report.c index 36c645939bc9..2d97efd4954f 100644 --- mm/kasan/generic_report.c +++ mm/kasan/generic_report.c @@ -86,6 +86,9 @@ static const char *get_shadow_bug_type(struct kasan_access_info *info) case KASAN_ALLOCA_RIGHT: bug_type = "alloca-out-of-bounds"; break; + case KASAN_VMALLOC_INVALID: + bug_type = "vmalloc-out-of-bounds"; + break; } return bug_type; diff --git mm/kasan/kasan.h mm/kasan/kasan.h index 35cff6bbb716..3a083274628e 100644 --- mm/kasan/kasan.h +++ mm/kasan/kasan.h @@ -25,6 +25,7 @@ #endif #define KASAN_GLOBAL_REDZONE 0xFA /* redzone for global variable */ +#define KASAN_VMALLOC_INVALID 0xF9 /* unallocated space in vmapped page */ /* * Stack redzone shadow values diff --git mm/vmalloc.c mm/vmalloc.c index 96903a6a763b..93e73644bdc9 100644 --- mm/vmalloc.c +++ mm/vmalloc.c @@ -682,7 +682,7 @@ insert_vmap_area_augment(struct vmap_area *va, * free area is inserted. If VA has been merged, it is * freed. */ -static __always_inline void +static __always_inline struct vmap_area * merge_or_add_vmap_area(struct vmap_area *va, struct rb_root *root, struct list_head *head) { @@ -749,7 +749,10 @@ merge_or_add_vmap_area(struct vmap_area *va, /* Free vmap_area object. */ kmem_cache_free(vmap_area_cachep, va); - return; + + /* Point to the new merged area. */ + va = sibling; + merged = true; } } @@ -758,6 +761,8 @@ merge_or_add_vmap_area(struct vmap_area *va, link_va(va, root, parent, link, head); augment_tree_propagate_from(va); } + + return va; } static __always_inline bool @@ -1171,7 +1176,7 @@ static void __free_vmap_area(struct vmap_area *va) /* * Merge VA with its neighbors, otherwise just add it. */ - merge_or_add_vmap_area(va, + (void) merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list); } @@ -1278,15 +1283,20 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end) spin_lock(&vmap_area_lock); llist_for_each_entry_safe(va, n_va, valist, purge_list) { unsigned long nr = (va->va_end - va->va_start) >> PAGE_SHIFT; + unsigned long orig_start = va->va_start; + unsigned long orig_end = va->va_end; /* * Finally insert or merge lazily-freed area. It is * detached and there is no need to "unlink" it from * anything. */ - merge_or_add_vmap_area(va, + va = merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list); + kasan_release_vmalloc(orig_start, + orig_end, va->va_start, va->va_end); + atomic_long_sub(nr, &vmap_lazy_nr); if (atomic_long_read(&vmap_lazy_nr) < resched_threshold) @@ -2068,6 +2078,22 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, setup_vmalloc_vm(area, va, flags, caller); + /* + * For KASAN, if we are in vmalloc space, we need to cover the shadow + * area with real memory. If we come here through VM_ALLOC, this is + * done by a higher level function that has access to the true size, + * which might not be a full page. + * + * We assume module space comes via VM_ALLOC path. + */ + if (is_vmalloc_addr(area->addr) && !(area->flags & VM_ALLOC)) { + if (kasan_populate_vmalloc(area->size, area)) { + unmap_vmap_area(va); + kfree(area); + return NULL; + } + } + return area; } @@ -2245,6 +2271,9 @@ static void __vunmap(const void *addr, int deallocate_pages) debug_check_no_locks_freed(area->addr, get_vm_area_size(area)); debug_check_no_obj_freed(area->addr, get_vm_area_size(area)); + if (area->flags & VM_KASAN) + kasan_poison_vmalloc(area->addr, area->size); + vm_remove_mappings(area, deallocate_pages); if (deallocate_pages) { @@ -2497,6 +2526,11 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, if (!addr) return NULL; + if (is_vmalloc_or_module_addr(area->addr)) { + if (kasan_populate_vmalloc(real_size, area)) + return NULL; + } + /* * In this function, newly allocated vm_struct has VM_UNINITIALIZED * flag. It means that vm_struct is not fully initialized. @@ -3351,10 +3385,14 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets, spin_unlock(&vmap_area_lock); /* insert all vm's */ - for (area = 0; area < nr_vms; area++) + for (area = 0; area < nr_vms; area++) { setup_vmalloc_vm(vms[area], vas[area], VM_ALLOC, pcpu_get_vm_areas); + /* assume success here */ + kasan_populate_vmalloc(sizes[area], vms[area]); + } + kfree(vas); return vms; From patchwork Thu Oct 17 01:25:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 11194623 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 92E9F1575 for ; Thu, 17 Oct 2019 01:25:26 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 5FE7121A4C for ; Thu, 17 Oct 2019 01:25:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=axtens.net header.i=@axtens.net header.b="m1ApeOEB" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5FE7121A4C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 8F9AB8E0008; Wed, 16 Oct 2019 21:25:25 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 8AC6D8E0001; Wed, 16 Oct 2019 21:25:25 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7993E8E0008; Wed, 16 Oct 2019 21:25:25 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0007.hostedemail.com [216.40.44.7]) by kanga.kvack.org (Postfix) with ESMTP id 54F5F8E0001 for ; Wed, 16 Oct 2019 21:25:25 -0400 (EDT) Received: from smtpin16.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with SMTP id DECF6180ACEFC for ; Thu, 17 Oct 2019 01:25:24 +0000 (UTC) X-FDA: 76051533768.16.verse87_4c5451f7e1050 X-Spam-Summary: 2,0,0,5cc18ccb88535650,d41d8cd98f00b204,dja@axtens.net,:kasan-dev@googlegroups.com::x86@kernel.org:aryabinin@virtuozzo.com:glider@google.com:luto@kernel.org:linux-kernel@vger.kernel.org:mark.rutland@arm.com:dvyukov@google.com:christophe.leroy@c-s.fr:linuxppc-dev@lists.ozlabs.org:gor@linux.ibm.com:dja@axtens.net,RULES_HIT:41:355:379:541:800:960:966:973:988:989:1260:1311:1314:1345:1359:1431:1437:1515:1534:1541:1711:1730:1747:1777:1792:2196:2199:2393:2559:2562:2693:3138:3139:3140:3141:3142:3352:3865:3866:3867:3868:3874:4250:4321:4385:5007:6261:6653:7903:10004:11026:11473:11658:11914:12043:12048:12291:12297:12438:12517:12519:12555:12895:13069:13311:13357:13894:14181:14384:14394:14721:21080:21444:21451:21627:30054,0,RBL:209.85.214.196:@axtens.net:.lbl8.mailshell.net-62.2.0.100 66.100.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:37,LUA_SUMMARY:none X-HE-Tag: verse87_4c5451f7e1050 X-Filterd-Recvd-Size: 4259 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by imf50.hostedemail.com (Postfix) with ESMTP for ; Thu, 17 Oct 2019 01:25:24 +0000 (UTC) Received: by mail-pl1-f196.google.com with SMTP id q24so270608plr.13 for ; Wed, 16 Oct 2019 18:25:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=whmCcgz4VjZeRv6SREyqmZaNFMJpz8TJQeqtX9KJOOU=; b=m1ApeOEBceEitnwnVhSqb3qb8hNwH66tjcLagM1+mI6PFnNgrn5Dqs68VEyged3ZLe H/uKj71qyeGCmqzt29SEJYhu5OVDWqcQKVYk4MRoeokuQpyzBpo+zlze/ugO7ZWt0PW/ 0BZ4YdnuvAP9ZUNSyjzYEvtHn3WSIILR8Lnf4= 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:mime-version:content-transfer-encoding; bh=whmCcgz4VjZeRv6SREyqmZaNFMJpz8TJQeqtX9KJOOU=; b=rGXxyM/pHS1V5QCJERY9T4PbCMi0+svWSmD32KKj74eIsIludiMK1uNvatbO+2PvAi yX2+iDJ4PBhcN37H/dFalOwJ3YZTbJRs0+SCKb/zlAUgm55zyRPhkVIKc7ibx86Hcbs8 JwdeyjOH1Upo7UI89POsoKD4ILr5CGmCukH9C5z5OErRPHNLAIxd+rrGj+8fbyYo3zy7 tBsOU7F7+NWmI64fDLCqez7pg0bDdYm6SCc2Ytfq4fTiX9MGLdKQzx+ofgStaO+sYE1I KvfV/y1dabx2sN49d3dcHNhQ5UFyfw4JwhYbp2pqf3bCowiDUqUM/x//lcDIeEzKr+ac RMwg== X-Gm-Message-State: APjAAAUNi5APAfZHKUsHsabFJ52QvJFW/gNNomfXO4gtRHz/raIDuZSP C4vmMN0CSZmulERB5kbi9nS7qQ== X-Google-Smtp-Source: APXvYqwsR4962cnxMoM3dLvmhRD0TpVziHNmalYqRChEROjKsnzFNViD40UQgLnKTQ4n4Gd/NeT1qg== X-Received: by 2002:a17:902:9a88:: with SMTP id w8mr1250860plp.129.1571275523512; Wed, 16 Oct 2019 18:25:23 -0700 (PDT) Received: from localhost (ppp167-251-205.static.internode.on.net. [59.167.251.205]) by smtp.gmail.com with ESMTPSA id 14sm340879pfn.21.2019.10.16.18.25.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2019 18:25:22 -0700 (PDT) From: Daniel Axtens To: kasan-dev@googlegroups.com, linux-mm@kvack.org, x86@kernel.org, aryabinin@virtuozzo.com, glider@google.com, luto@kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, dvyukov@google.com, christophe.leroy@c-s.fr Cc: linuxppc-dev@lists.ozlabs.org, gor@linux.ibm.com, Daniel Axtens Subject: [PATCH v9 2/5] kasan: add test for vmalloc Date: Thu, 17 Oct 2019 12:25:03 +1100 Message-Id: <20191017012506.28503-3-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017012506.28503-1-dja@axtens.net> References: <20191017012506.28503-1-dja@axtens.net> MIME-Version: 1.0 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: Test kasan vmalloc support by adding a new test to the module. Signed-off-by: Daniel Axtens --- v5: split out per Christophe Leroy --- lib/test_kasan.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git lib/test_kasan.c lib/test_kasan.c index 49cc4d570a40..328d33beae36 100644 --- lib/test_kasan.c +++ lib/test_kasan.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -748,6 +749,30 @@ static noinline void __init kmalloc_double_kzfree(void) kzfree(ptr); } +#ifdef CONFIG_KASAN_VMALLOC +static noinline void __init vmalloc_oob(void) +{ + void *area; + + pr_info("vmalloc out-of-bounds\n"); + + /* + * We have to be careful not to hit the guard page. + * The MMU will catch that and crash us. + */ + area = vmalloc(3000); + if (!area) { + pr_err("Allocation failed\n"); + return; + } + + ((volatile char *)area)[3100]; + vfree(area); +} +#else +static void __init vmalloc_oob(void) {} +#endif + static int __init kmalloc_tests_init(void) { /* @@ -793,6 +818,7 @@ static int __init kmalloc_tests_init(void) kasan_strings(); kasan_bitops(); kmalloc_double_kzfree(); + vmalloc_oob(); kasan_restore_multi_shot(multishot); From patchwork Thu Oct 17 01:25:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 11194625 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 EC9B81668 for ; Thu, 17 Oct 2019 01:25:30 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id B9AFA21A4C for ; Thu, 17 Oct 2019 01:25:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=axtens.net header.i=@axtens.net header.b="YSJ6KAHi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B9AFA21A4C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id E79938E0009; Wed, 16 Oct 2019 21:25:29 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id E28BF8E0001; Wed, 16 Oct 2019 21:25:29 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D17668E0009; Wed, 16 Oct 2019 21:25:29 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0107.hostedemail.com [216.40.44.107]) by kanga.kvack.org (Postfix) with ESMTP id AD8D28E0001 for ; Wed, 16 Oct 2019 21:25:29 -0400 (EDT) Received: from smtpin18.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with SMTP id 532A65DEE for ; Thu, 17 Oct 2019 01:25:29 +0000 (UTC) X-FDA: 76051533978.18.arm15_4cf7632c2c13a X-Spam-Summary: 2,0,0,853ab8f041a8b6ca,d41d8cd98f00b204,dja@axtens.net,:kasan-dev@googlegroups.com::x86@kernel.org:aryabinin@virtuozzo.com:glider@google.com:luto@kernel.org:linux-kernel@vger.kernel.org:mark.rutland@arm.com:dvyukov@google.com:christophe.leroy@c-s.fr:linuxppc-dev@lists.ozlabs.org:gor@linux.ibm.com:dja@axtens.net,RULES_HIT:41:355:379:541:800:960:973:988:989:1260:1311:1314:1345:1359:1431:1437:1515:1534:1542:1711:1730:1747:1777:1792:2393:2559:2562:2689:2898:3138:3139:3140:3141:3142:3353:3865:3866:3867:3868:3870:3871:3873:3874:4250:4321:4470:5007:6261:6653:7875:8784:10004:11026:11232:11473:11658:11914:12043:12048:12296:12297:12438:12517:12519:12555:12895:12986:13894:14093:14096:14181:14394:14721:14877:21063:21080:21444:21451:21627:30054:30070:30091,0,RBL:209.85.210.196:@axtens.net:.lbl8.mailshell.net-62.2.0.100 66.100.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:24,LUA_SUMMA RY:none X-HE-Tag: arm15_4cf7632c2c13a X-Filterd-Recvd-Size: 4955 Received: from mail-pf1-f196.google.com (mail-pf1-f196.google.com [209.85.210.196]) by imf07.hostedemail.com (Postfix) with ESMTP for ; Thu, 17 Oct 2019 01:25:28 +0000 (UTC) Received: by mail-pf1-f196.google.com with SMTP id q5so491329pfg.13 for ; Wed, 16 Oct 2019 18:25:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1Qk9PXHlMYGMSaAT4No+OXlpNbokcwpw05BcYMTN8o0=; b=YSJ6KAHiGnESyfIOPhPKg1SYOVmjMBpomipuFXEhixlmLzKVW8KvRvn5hHyn6j2Y1i p0eSmpQseV9wxx3eeTbQ1axx5VnzPdFc8iQC+dfYkX4tE20eVuU8xw8dU0mQPGkNS4RJ MaD1w2zcSOG1GUeN4MR3fRhoXpOaM2LU5n7Zc= 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:mime-version:content-transfer-encoding; bh=1Qk9PXHlMYGMSaAT4No+OXlpNbokcwpw05BcYMTN8o0=; b=XL+GTgG5bS60oMS5y0hFgjCJJEABA9U1RCOYlKoG688vag/w9xgODAnm+B7TUhUXKA 6qmIHpN5Csq7rgjD5uCWyFjU9RT7KNXLBZKOg/1Fyzo5/XirHl3pMgwNQFoOZ9TpqExX 3afrzlTxCJ3qFbL5ePe78XmiU2Eh3uCkgLzB1f2gqZt0eHLjShh5uWwbgtF2ak5yUMGD XLdGUZ7p5ieJSBEWX/fB7mGguztAt2D6xabc+bXPpo15jMU31KVPl06yNJ+iFhgZrD9i iQy6mG1faAuZbXX1J8c+GpxtIqJkUcmvZDzJx4nBDVa/n04oQrCQ0JY/Gj3jkPG2dkiu rplw== X-Gm-Message-State: APjAAAUlIyRWHZpWQ+EwVL4SkGVypksqNTUKqAwYJiXk7eDCweGU35by 6/KRPD1PQs+iLaAqZ61NDZluog== X-Google-Smtp-Source: APXvYqxXibUE0U8yVD2FdPr0YPQf1k44k2wbp/Do/vRXY+EPhK1zFPUYH2gqnpMbv50YR9NpPNR7KQ== X-Received: by 2002:a17:90a:868b:: with SMTP id p11mr1154784pjn.58.1571275527734; Wed, 16 Oct 2019 18:25:27 -0700 (PDT) Received: from localhost (ppp167-251-205.static.internode.on.net. [59.167.251.205]) by smtp.gmail.com with ESMTPSA id 127sm351343pfy.56.2019.10.16.18.25.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2019 18:25:27 -0700 (PDT) From: Daniel Axtens To: kasan-dev@googlegroups.com, linux-mm@kvack.org, x86@kernel.org, aryabinin@virtuozzo.com, glider@google.com, luto@kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, dvyukov@google.com, christophe.leroy@c-s.fr Cc: linuxppc-dev@lists.ozlabs.org, gor@linux.ibm.com, Daniel Axtens Subject: [PATCH v9 3/5] fork: support VMAP_STACK with KASAN_VMALLOC Date: Thu, 17 Oct 2019 12:25:04 +1100 Message-Id: <20191017012506.28503-4-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017012506.28503-1-dja@axtens.net> References: <20191017012506.28503-1-dja@axtens.net> MIME-Version: 1.0 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: Supporting VMAP_STACK with KASAN_VMALLOC is straightforward: - clear the shadow region of vmapped stacks when swapping them in - tweak Kconfig to allow VMAP_STACK to be turned on with KASAN Reviewed-by: Dmitry Vyukov Signed-off-by: Daniel Axtens --- arch/Kconfig | 9 +++++---- kernel/fork.c | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git arch/Kconfig arch/Kconfig index 5f8a5d84dbbe..2d914990402f 100644 --- arch/Kconfig +++ arch/Kconfig @@ -843,16 +843,17 @@ config HAVE_ARCH_VMAP_STACK config VMAP_STACK default y bool "Use a virtually-mapped stack" - depends on HAVE_ARCH_VMAP_STACK && !KASAN + depends on HAVE_ARCH_VMAP_STACK + depends on !KASAN || KASAN_VMALLOC ---help--- Enable this if you want the use virtually-mapped kernel stacks with guard pages. This causes kernel stack overflows to be caught immediately rather than causing difficult-to-diagnose corruption. - This is presently incompatible with KASAN because KASAN expects - the stack to map directly to the KASAN shadow map using a formula - that is incorrect if the stack is in vmalloc space. + To use this with KASAN, the architecture must support backing + virtual mappings with real shadow memory, and KASAN_VMALLOC must + be enabled. config ARCH_OPTIONAL_KERNEL_RWX def_bool n diff --git kernel/fork.c kernel/fork.c index bcdf53125210..484ca6b0ae6c 100644 --- kernel/fork.c +++ kernel/fork.c @@ -94,6 +94,7 @@ #include #include #include +#include #include #include @@ -224,6 +225,9 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node) if (!s) continue; + /* Clear the KASAN shadow of the stack. */ + kasan_unpoison_shadow(s->addr, THREAD_SIZE); + /* Clear stale pointers from reused stack. */ memset(s->addr, 0, THREAD_SIZE); From patchwork Thu Oct 17 01:25:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 11194627 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 A05B11668 for ; Thu, 17 Oct 2019 01:25:35 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 6084C21928 for ; Thu, 17 Oct 2019 01:25:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=axtens.net header.i=@axtens.net header.b="EK4oU0BZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6084C21928 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 9975D8E000A; Wed, 16 Oct 2019 21:25:34 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 9473E8E0001; Wed, 16 Oct 2019 21:25:34 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 80E5C8E000A; Wed, 16 Oct 2019 21:25:34 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0101.hostedemail.com [216.40.44.101]) by kanga.kvack.org (Postfix) with ESMTP id 619A88E0001 for ; Wed, 16 Oct 2019 21:25:34 -0400 (EDT) Received: from smtpin04.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id 07DD2583F for ; Thu, 17 Oct 2019 01:25:34 +0000 (UTC) X-FDA: 76051534188.04.rate74_4da0d9a05ea32 X-Spam-Summary: 2,0,0,057ba0280f035db5,d41d8cd98f00b204,dja@axtens.net,:kasan-dev@googlegroups.com::x86@kernel.org:aryabinin@virtuozzo.com:glider@google.com:luto@kernel.org:linux-kernel@vger.kernel.org:mark.rutland@arm.com:dvyukov@google.com:christophe.leroy@c-s.fr:linuxppc-dev@lists.ozlabs.org:gor@linux.ibm.com:dja@axtens.net,RULES_HIT:41:355:379:541:800:960:973:988:989:1260:1311:1314:1345:1359:1437:1515:1535:1543:1711:1730:1747:1777:1792:2393:2559:2562:2914:3138:3139:3140:3141:3142:3355:3865:3866:3867:3868:3870:3871:3872:3874:4117:4250:4605:5007:6117:6119:6261:6653:7875:7903:10004:11026:11233:11473:11658:11914:12043:12048:12291:12296:12297:12438:12517:12519:12555:12683:12895:13141:13230:13894:14096:14181:14394:14721:21080:21444:21451:21627:30054:30070,0,RBL:209.85.215.193:@axtens.net:.lbl8.mailshell.net-62.2.175.100 66.100.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:27,LUA_SUMMARY:n one X-HE-Tag: rate74_4da0d9a05ea32 X-Filterd-Recvd-Size: 6739 Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by imf31.hostedemail.com (Postfix) with ESMTP for ; Thu, 17 Oct 2019 01:25:33 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id e15so280773pgu.13 for ; Wed, 16 Oct 2019 18:25:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=isMm51VtK/oRU6lGsD9w6jqnjg5iuBGo4uf1ljxv9U4=; b=EK4oU0BZG1V6UaQsnBNZnjXP8g8KxL/hhWkVyT8+14E8rqLSg3p2oglexNRbLfDRyD uEfvJrRT1xB9OLiujVi/H6ZYlpgtsIXX7v5bz1AeiKn7Cf5lHwzOGKals+WHChh0ctti rZVxpfdH6wI8CAMhz4odtR5tkZaQNKlfoegVk= 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:mime-version:content-transfer-encoding; bh=isMm51VtK/oRU6lGsD9w6jqnjg5iuBGo4uf1ljxv9U4=; b=DdjMeGdhnKYhcrARErqXrrUmlrcwDai7nghu2TI5IjXes0y9fEzUaBtdhwuTakAh1M 2nXQscCswcRnrAxMeqTeabSK1PM+lgoXnKlRE5fmOYVuBVdGYVDKK0guEoVmB3LjGYB+ jLO66DJBEOas+X8EiMA4i03vJus65F2Bdpn9T3CsFWj4Tt0ofmT7/si4yM8Wgun2H8e0 rhYFT8xek3DUYFtVQ8MO/k7x1wPG3JxtiaRGHatHWad5vWXV4Mo0SyuE4Mo/RBliW12i cIbYGeQthsCY/OHXx5YpbumspOaqs8OFn1kp7R3G3217CGSVycL9PKYu13+QkIHGYyJY fz0A== X-Gm-Message-State: APjAAAUlrxnDhuFcVJS7g9YtZuO3CANWx/8GMg0wBSHnTA1Jq9bpqmQR ElVFJc+vA39h1Uwc6e+uq5Jx4w== X-Google-Smtp-Source: APXvYqz8KIe0XQW6K5vnFa8nQQJeKdiESpPZJX7VNQmEzPXTQBBRxJ6FkEGke8hAC3oYssSRd5RjMQ== X-Received: by 2002:a63:d916:: with SMTP id r22mr1243029pgg.46.1571275532214; Wed, 16 Oct 2019 18:25:32 -0700 (PDT) Received: from localhost (ppp167-251-205.static.internode.on.net. [59.167.251.205]) by smtp.gmail.com with ESMTPSA id f89sm391422pje.20.2019.10.16.18.25.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2019 18:25:31 -0700 (PDT) From: Daniel Axtens To: kasan-dev@googlegroups.com, linux-mm@kvack.org, x86@kernel.org, aryabinin@virtuozzo.com, glider@google.com, luto@kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, dvyukov@google.com, christophe.leroy@c-s.fr Cc: linuxppc-dev@lists.ozlabs.org, gor@linux.ibm.com, Daniel Axtens Subject: [PATCH v9 4/5] x86/kasan: support KASAN_VMALLOC Date: Thu, 17 Oct 2019 12:25:05 +1100 Message-Id: <20191017012506.28503-5-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017012506.28503-1-dja@axtens.net> References: <20191017012506.28503-1-dja@axtens.net> MIME-Version: 1.0 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: In the case where KASAN directly allocates memory to back vmalloc space, don't map the early shadow page over it. We prepopulate pgds/p4ds for the range that would otherwise be empty. This is required to get it synced to hardware on boot, allowing the lower levels of the page tables to be filled dynamically. Acked-by: Dmitry Vyukov Signed-off-by: Daniel Axtens --- v5: fix some checkpatch CHECK warnings. There are some that remain around lines ending with '(': I have not changed these because it's consistent with the rest of the file and it's not easy to see how to fix it without creating an overlong line or lots of temporary variables. v2: move from faulting in shadow pgds to prepopulating --- arch/x86/Kconfig | 1 + arch/x86/mm/kasan_init_64.c | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git arch/x86/Kconfig arch/x86/Kconfig index abe822d52167..92f5d5d5c78a 100644 --- arch/x86/Kconfig +++ arch/x86/Kconfig @@ -135,6 +135,7 @@ config X86 select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_KASAN if X86_64 + select HAVE_ARCH_KASAN_VMALLOC if X86_64 select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT diff --git arch/x86/mm/kasan_init_64.c arch/x86/mm/kasan_init_64.c index 296da58f3013..8f00f462709e 100644 --- arch/x86/mm/kasan_init_64.c +++ arch/x86/mm/kasan_init_64.c @@ -245,6 +245,51 @@ static void __init kasan_map_early_shadow(pgd_t *pgd) } while (pgd++, addr = next, addr != end); } +static void __init kasan_shallow_populate_p4ds(pgd_t *pgd, + unsigned long addr, + unsigned long end, + int nid) +{ + p4d_t *p4d; + unsigned long next; + void *p; + + p4d = p4d_offset(pgd, addr); + do { + next = p4d_addr_end(addr, end); + + if (p4d_none(*p4d)) { + p = early_alloc(PAGE_SIZE, nid, true); + p4d_populate(&init_mm, p4d, p); + } + } while (p4d++, addr = next, addr != end); +} + +static void __init kasan_shallow_populate_pgds(void *start, void *end) +{ + unsigned long addr, next; + pgd_t *pgd; + void *p; + int nid = early_pfn_to_nid((unsigned long)start); + + addr = (unsigned long)start; + pgd = pgd_offset_k(addr); + do { + next = pgd_addr_end(addr, (unsigned long)end); + + if (pgd_none(*pgd)) { + p = early_alloc(PAGE_SIZE, nid, true); + pgd_populate(&init_mm, pgd, p); + } + + /* + * we need to populate p4ds to be synced when running in + * four level mode - see sync_global_pgds_l4() + */ + kasan_shallow_populate_p4ds(pgd, addr, next, nid); + } while (pgd++, addr = next, addr != (unsigned long)end); +} + #ifdef CONFIG_KASAN_INLINE static int kasan_die_handler(struct notifier_block *self, unsigned long val, @@ -352,9 +397,24 @@ void __init kasan_init(void) shadow_cpu_entry_end = (void *)round_up( (unsigned long)shadow_cpu_entry_end, PAGE_SIZE); + /* + * If we're in full vmalloc mode, don't back vmalloc space with early + * shadow pages. Instead, prepopulate pgds/p4ds so they are synced to + * the global table and we can populate the lower levels on demand. + */ +#ifdef CONFIG_KASAN_VMALLOC + kasan_shallow_populate_pgds( + kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM), + kasan_mem_to_shadow((void *)VMALLOC_END)); + + kasan_populate_early_shadow( + kasan_mem_to_shadow((void *)VMALLOC_END + 1), + shadow_cpu_entry_begin); +#else kasan_populate_early_shadow( kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM), shadow_cpu_entry_begin); +#endif kasan_populate_shadow((unsigned long)shadow_cpu_entry_begin, (unsigned long)shadow_cpu_entry_end, 0); From patchwork Thu Oct 17 01:25:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 11194629 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 7314E1575 for ; Thu, 17 Oct 2019 01:25:40 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 34D0321928 for ; Thu, 17 Oct 2019 01:25:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=axtens.net header.i=@axtens.net header.b="kPLzGqgg" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 34D0321928 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 662448E000B; Wed, 16 Oct 2019 21:25:39 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 611B38E0001; Wed, 16 Oct 2019 21:25:39 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 500508E000B; Wed, 16 Oct 2019 21:25:39 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0208.hostedemail.com [216.40.44.208]) by kanga.kvack.org (Postfix) with ESMTP id 2C1F98E0001 for ; Wed, 16 Oct 2019 21:25:39 -0400 (EDT) Received: from smtpin03.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id BC3415845 for ; Thu, 17 Oct 2019 01:25:38 +0000 (UTC) X-FDA: 76051534356.03.fight98_4e557de7cc710 X-Spam-Summary: 2,0,0,69ced370a5a6bd65,d41d8cd98f00b204,dja@axtens.net,:kasan-dev@googlegroups.com::x86@kernel.org:aryabinin@virtuozzo.com:glider@google.com:luto@kernel.org:linux-kernel@vger.kernel.org:mark.rutland@arm.com:dvyukov@google.com:christophe.leroy@c-s.fr:linuxppc-dev@lists.ozlabs.org:gor@linux.ibm.com:dja@axtens.net,RULES_HIT:41:355:379:421:541:800:960:966:973:988:989:1260:1311:1314:1345:1359:1431:1437:1515:1535:1542:1711:1730:1747:1777:1792:2196:2199:2393:2559:2562:3138:3139:3140:3141:3142:3354:3865:3866:3867:3868:3870:3872:4385:4605:5007:6261:6653:7875:7903:8700:10004:11026:11473:11658:11914:12043:12048:12291:12296:12297:12438:12517:12519:12555:12663:12895:13894:14096:14181:14394:14721:21080:21444:21451:21627:30034:30054:30070,0,RBL:209.85.214.195:@axtens.net:.lbl8.mailshell.net-62.2.0.100 66.100.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: fight98_4e557de7cc710 X-Filterd-Recvd-Size: 5590 Received: from mail-pl1-f195.google.com (mail-pl1-f195.google.com [209.85.214.195]) by imf45.hostedemail.com (Postfix) with ESMTP for ; Thu, 17 Oct 2019 01:25:38 +0000 (UTC) Received: by mail-pl1-f195.google.com with SMTP id q24so270872plr.13 for ; Wed, 16 Oct 2019 18:25:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=OYfGHq7Ua8XlIFWVnYrWlfnb+Qaiu3AuIcv4KZ3ENBU=; b=kPLzGqggNUsPFDxV/H8ftNKVOlHtZarUZ2uO5M1Cl+hwXsMbW/vTrWwIjhfQ+3DWYJ BAJOSuNbGvc+wZSDF5mXHgUtEzM/UBmDJTY+ncpQRCjrnopVjD47CaQs12J79yMzbmaJ 2HoVzjwx6/PntMBB3luM9yU1+3Xh96sr83vp0= 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:mime-version:content-transfer-encoding; bh=OYfGHq7Ua8XlIFWVnYrWlfnb+Qaiu3AuIcv4KZ3ENBU=; b=GZi9QNvrq1B2TbW4Pq+WgzK5/wXzSc4zd7wML62Cze8ltPI4miNpZE7ouujhDLNXcS ar1g5tcPcGc/otfKf70Itx7Td4h2I325OWZRCYE3FiwFFu0D2hgmKoDgv0VSBFH6h8DQ jHjR0QU9SDerJLbnERXDE+3wgqrCKAuV2ODfeZZppZArRZZyyrpO4IX2lVsBqIl1ACPw eB7wZNHEKu7C7dskcBZZcCUsVuH/RqxaSacGyXJ77giiJGChcmwXKSaremntNEtUT+Uf eWJZvO+9NiEy1zeV7jj8rgcyud8vMtv2L3czcj4iviFUm7fObbCOR8x1uc2AIQqJ7Imw +XAg== X-Gm-Message-State: APjAAAVAljZ0f5gbeOeijGTFWSpN/sV47i2UL2zOD3pVTo+HlhHzNCHa +U6a0WYGdMB+aNk3eck0UxgTGg== X-Google-Smtp-Source: APXvYqwQlBhRRBicY30cw6VPEISaJYd+4/odDPgj5HED+MoQwNbayPMmtq4wGs1t8T3sUU1Hp+309g== X-Received: by 2002:a17:902:8ec1:: with SMTP id x1mr1189452plo.314.1571275537371; Wed, 16 Oct 2019 18:25:37 -0700 (PDT) Received: from localhost (ppp167-251-205.static.internode.on.net. [59.167.251.205]) by smtp.gmail.com with ESMTPSA id d4sm381964pjs.9.2019.10.16.18.25.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Oct 2019 18:25:36 -0700 (PDT) From: Daniel Axtens To: kasan-dev@googlegroups.com, linux-mm@kvack.org, x86@kernel.org, aryabinin@virtuozzo.com, glider@google.com, luto@kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, dvyukov@google.com, christophe.leroy@c-s.fr Cc: linuxppc-dev@lists.ozlabs.org, gor@linux.ibm.com, Daniel Axtens Subject: [PATCH v9 5/5] kasan debug: track pages allocated for vmalloc shadow Date: Thu, 17 Oct 2019 12:25:06 +1100 Message-Id: <20191017012506.28503-6-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191017012506.28503-1-dja@axtens.net> References: <20191017012506.28503-1-dja@axtens.net> MIME-Version: 1.0 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: Provide the current number of vmalloc shadow pages in /sys/kernel/debug/kasan/vmalloc_shadow_pages. Signed-off-by: Daniel Axtens --- v8: rename kasan_vmalloc/shadow_pages -> kasan/vmalloc_shadow_pages On v4 (no dynamic freeing), I saw the following approximate figures on my test VM: - fresh boot: 720 - after test_vmalloc: ~14000 With v5 (lazy dynamic freeing): - boot: ~490-500 - running modprobe test_vmalloc pushes the figures up to sometimes as high as ~14000, but they drop down to ~560 after the test ends. I'm not sure where the extra sixty pages are from, but running the test repeately doesn't cause the number to keep growing, so I don't think we're leaking. - with vmap_stack, spawning tasks pushes the figure up to ~4200, then some clearing kicks in and drops it down to previous levels again. --- mm/kasan/common.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git mm/kasan/common.c mm/kasan/common.c index 81521d180bec..ac05038afa5a 100644 --- mm/kasan/common.c +++ mm/kasan/common.c @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -750,6 +751,8 @@ core_initcall(kasan_memhotplug_init); #endif #ifdef CONFIG_KASAN_VMALLOC +static u64 vmalloc_shadow_pages; + static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr, void *unused) { @@ -782,6 +785,7 @@ static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr, if (likely(pte_none(*ptep))) { set_pte_at(&init_mm, addr, ptep, pte); page = 0; + vmalloc_shadow_pages++; } spin_unlock(&init_mm.page_table_lock); if (page) @@ -836,6 +840,7 @@ static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr, pte_clear(&init_mm, addr, ptep); flush_tlb_kernel_range(addr, addr + PAGE_SIZE); free_page(page); + vmalloc_shadow_pages--; } spin_unlock(&init_mm.page_table_lock); @@ -954,4 +959,25 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, (unsigned long)shadow_end); } } + +static __init int kasan_init_debugfs(void) +{ + struct dentry *root, *count; + + root = debugfs_create_dir("kasan", NULL); + if (IS_ERR(root)) { + if (PTR_ERR(root) == -ENODEV) + return 0; + return PTR_ERR(root); + } + + count = debugfs_create_u64("vmalloc_shadow_pages", 0444, root, + &vmalloc_shadow_pages); + + if (IS_ERR(count)) + return PTR_ERR(root); + + return 0; +} +late_initcall(kasan_init_debugfs); #endif