From: glider@google.com
To: Andrew Morton <akpm@linux-foundation.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Eric Dumazet <edumazet@google.com>,
Wolfram Sang <wsa@the-dreams.de>, Petr Mladek <pmladek@suse.com>,
Vegard Nossum <vegard.nossum@oracle.com>,
Dmitry Vyukov <dvyukov@google.com>,
Marco Elver <elver@google.com>,
Andrey Konovalov <andreyknvl@google.com>,
linux-mm@kvack.org
Cc: glider@google.com, viro@zeniv.linux.org.uk,
adilger.kernel@dilger.ca, aryabinin@virtuozzo.com,
luto@kernel.org, ard.biesheuvel@linaro.org, arnd@arndb.de,
hch@infradead.org, hch@lst.de, darrick.wong@oracle.com,
davem@davemloft.net, dmitry.torokhov@gmail.com,
ebiggers@google.com, ericvh@gmail.com, harry.wentland@amd.com,
herbert@gondor.apana.org.au, iii@linux.ibm.com, mingo@elte.hu,
jasowang@redhat.com, axboe@kernel.dk, m.szyprowski@samsung.com,
mark.rutland@arm.com, martin.petersen@oracle.com,
schwidefsky@de.ibm.com, willy@infradead.org, mst@redhat.com,
mhocko@suse.com, monstr@monstr.eu, cai@lca.pw,
rdunlap@infradead.org, robin.murphy@arm.com,
sergey.senozhatsky@gmail.com, rostedt@goodmis.org,
tiwai@suse.com, tytso@mit.edu, tglx@linutronix.de,
gor@linux.ibm.com
Subject: [PATCH RFC v4 23/42] kmsan: mm: maintain KMSAN metadata for page operations
Date: Fri, 20 Dec 2019 19:49:36 +0100 [thread overview]
Message-ID: <20191220184955.223741-24-glider@google.com> (raw)
In-Reply-To: <20191220184955.223741-1-glider@google.com>
Insert KMSAN hooks that make the necessary bookkeeping changes:
- allocate/split/deallocate metadata pages in
alloc_pages()/split_page()/free_page();
- clear page shadow and origins in clear_page(), copy_user_highpage();
- copy page metadata in copy_highpage(), wp_page_copy();
- handle vmap()/vunmap()/iounmap();
Signed-off-by: Alexander Potapenko <glider@google.com>
To: Alexander Potapenko <glider@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Marco Elver <elver@google.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: linux-mm@kvack.org
---
This patch was previously called "kmsan: call KMSAN hooks where needed"
v2:
- dropped call to kmsan_handle_vprintk, updated comment in printk.c
v3:
- put KMSAN_INIT_VALUE on a separate line in vprintk_store()
- dropped call to kmsan_handle_i2c_transfer()
- minor style fixes
v4:
- split mm-unrelated bits to other patches as requested by Andrey
Konovalov
- dropped changes to mm/compaction.c
- use kmsan_unpoison_shadow in page_64.h and highmem.h
Change-Id: I1250a928d9263bf71fdaa067a070bdee686ef47b
---
arch/x86/include/asm/page_64.h | 13 +++++++++++++
arch/x86/mm/ioremap.c | 3 +++
include/linux/highmem.h | 3 +++
lib/ioremap.c | 5 +++++
mm/gup.c | 3 +++
mm/memory.c | 2 ++
mm/page_alloc.c | 17 +++++++++++++++++
mm/vmalloc.c | 24 ++++++++++++++++++++++--
8 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index 939b1cff4a7b..045856c38f49 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -44,14 +44,27 @@ void clear_page_orig(void *page);
void clear_page_rep(void *page);
void clear_page_erms(void *page);
+/* This is an assembly header, avoid including too much of kmsan.h */
+#ifdef CONFIG_KMSAN
+void kmsan_unpoison_shadow(const void *addr, size_t size);
+#endif
+__no_sanitize_memory
static inline void clear_page(void *page)
{
+#ifdef CONFIG_KMSAN
+ /* alternative_call_2() changes |page|. */
+ void *page_copy = page;
+#endif
alternative_call_2(clear_page_orig,
clear_page_rep, X86_FEATURE_REP_GOOD,
clear_page_erms, X86_FEATURE_ERMS,
"=D" (page),
"0" (page)
: "cc", "memory", "rax", "rcx");
+#ifdef CONFIG_KMSAN
+ /* Clear KMSAN shadow for the pages that have it. */
+ kmsan_unpoison_shadow(page_copy, PAGE_SIZE);
+#endif
}
void copy_page(void *to, void *from);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index b3a2936377b5..e93585dbfc49 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -7,6 +7,7 @@
* (C) Copyright 1995 1996 Linus Torvalds
*/
+#include <linux/kmsan.h>
#include <linux/memblock.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -451,6 +452,8 @@ void iounmap(volatile void __iomem *addr)
return;
}
+ kmsan_iounmap_page_range((unsigned long)addr,
+ (unsigned long)addr + get_vm_area_size(p));
free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
/* Finally remove it */
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index ea5cdbd8c2c3..9f6efa26e9b5 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -5,6 +5,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/bug.h>
+#include <linux/kmsan.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>
@@ -255,6 +256,7 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
vfrom = kmap_atomic(from);
vto = kmap_atomic(to);
copy_user_page(vto, vfrom, vaddr, to);
+ kmsan_unpoison_shadow(page_address(to), PAGE_SIZE);
kunmap_atomic(vto);
kunmap_atomic(vfrom);
}
@@ -270,6 +272,7 @@ static inline void copy_highpage(struct page *to, struct page *from)
vfrom = kmap_atomic(from);
vto = kmap_atomic(to);
copy_page(vto, vfrom);
+ kmsan_copy_page_meta(to, from);
kunmap_atomic(vto);
kunmap_atomic(vfrom);
}
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 3f0e18543de8..14b0325b6fa9 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -6,6 +6,7 @@
*
* (C) Copyright 1995 1996 Linus Torvalds
*/
+#include <linux/kmsan.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/sched.h>
@@ -214,6 +215,8 @@ int ioremap_page_range(unsigned long addr,
unsigned long start;
unsigned long next;
int err;
+ unsigned long old_addr = addr;
+ phys_addr_t old_phys_addr = phys_addr;
might_sleep();
BUG_ON(addr >= end);
@@ -228,6 +231,8 @@ int ioremap_page_range(unsigned long addr,
} while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
flush_cache_vmap(start, end);
+ if (!err)
+ kmsan_ioremap_page_range(old_addr, end, old_phys_addr, prot);
return err;
}
diff --git a/mm/gup.c b/mm/gup.c
index 7646bf993b25..f2f4a6bbadf9 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -4,6 +4,7 @@
#include <linux/err.h>
#include <linux/spinlock.h>
+#include <linux/kmsan.h>
#include <linux/mm.h>
#include <linux/memremap.h>
#include <linux/pagemap.h>
@@ -2363,6 +2364,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
gup_fast_permitted(start, end)) {
local_irq_save(flags);
gup_pgd_range(start, end, write ? FOLL_WRITE : 0, pages, &nr);
+ kmsan_gup_pgd_range(pages, nr);
local_irq_restore(flags);
}
@@ -2432,6 +2434,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages,
gup_fast_permitted(start, end)) {
local_irq_disable();
gup_pgd_range(addr, end, gup_flags, pages, &nr);
+ kmsan_gup_pgd_range(pages, nr);
local_irq_enable();
ret = nr;
}
diff --git a/mm/memory.c b/mm/memory.c
index 606da187d1de..143ce6549f02 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -51,6 +51,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/memremap.h>
+#include <linux/kmsan.h>
#include <linux/ksm.h>
#include <linux/rmap.h>
#include <linux/export.h>
@@ -2423,6 +2424,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
put_page(old_page);
return 0;
}
+ kmsan_copy_page_meta(new_page, old_page);
}
if (mem_cgroup_try_charge_delay(new_page, mm, GFP_KERNEL, &memcg, false))
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4785a8a2040e..4940901b79b3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -26,6 +26,8 @@
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/kasan.h>
+#include <linux/kmsan.h>
+#include <linux/kmsan-checks.h>
#include <linux/module.h>
#include <linux/suspend.h>
#include <linux/pagevec.h>
@@ -1133,6 +1135,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
VM_BUG_ON_PAGE(PageTail(page), page);
trace_mm_page_free(page, order);
+ kmsan_free_page(page, order);
/*
* Check tail pages before head page information is cleared to
@@ -3129,6 +3132,7 @@ void split_page(struct page *page, unsigned int order)
VM_BUG_ON_PAGE(PageCompound(page), page);
VM_BUG_ON_PAGE(!page_count(page), page);
+ kmsan_split_page(page, order);
for (i = 1; i < (1 << order); i++)
set_page_refcounted(page + i);
split_page_owner(page, order);
@@ -3261,6 +3265,14 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
/*
* Allocate a page from the given zone. Use pcplists for order-0 allocations.
*/
+
+/*
+ * Do not instrument rmqueue() with KMSAN. This function may call
+ * __msan_poison_alloca() through a call to set_pfnblock_flags_mask().
+ * If __msan_poison_alloca() attempts to allocate pages for the stack depot, it
+ * may call rmqueue() again, which will result in a deadlock.
+ */
+__no_sanitize_memory
static inline
struct page *rmqueue(struct zone *preferred_zone,
struct zone *zone, unsigned int order,
@@ -4784,6 +4796,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
trace_mm_page_alloc(page, order, alloc_mask, ac.migratetype);
+ if (page)
+ if (kmsan_alloc_page(page, order, gfp_mask)) {
+ __free_pages(page, order);
+ page = NULL;
+ }
return page;
}
EXPORT_SYMBOL(__alloc_pages_nodemask);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 4d3b3d60d893..409ef632a24e 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -29,6 +29,7 @@
#include <linux/rcupdate.h>
#include <linux/pfn.h>
#include <linux/kmemleak.h>
+#include <linux/kmsan.h>
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/llist.h>
@@ -119,7 +120,8 @@ static void vunmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end)
} while (p4d++, addr = next, addr != end);
}
-static void vunmap_page_range(unsigned long addr, unsigned long end)
+/* Exported for KMSAN, visible in mm/kmsan/kmsan.h only. */
+void __vunmap_page_range(unsigned long addr, unsigned long end)
{
pgd_t *pgd;
unsigned long next;
@@ -133,6 +135,13 @@ static void vunmap_page_range(unsigned long addr, unsigned long end)
vunmap_p4d_range(pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
+EXPORT_SYMBOL(__vunmap_page_range);
+
+static void vunmap_page_range(unsigned long addr, unsigned long end)
+{
+ kmsan_vunmap_page_range(addr, end);
+ __vunmap_page_range(addr, end);
+}
static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
unsigned long end, pgprot_t prot, struct page **pages, int *nr)
@@ -216,8 +225,11 @@ static int vmap_p4d_range(pgd_t *pgd, unsigned long addr,
* will have pfns corresponding to the "pages" array.
*
* Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
+ *
+ * This function is exported for use in KMSAN, but is only declared in KMSAN
+ * headers.
*/
-static int vmap_page_range_noflush(unsigned long start, unsigned long end,
+int __vmap_page_range_noflush(unsigned long start, unsigned long end,
pgprot_t prot, struct page **pages)
{
pgd_t *pgd;
@@ -237,6 +249,14 @@ static int vmap_page_range_noflush(unsigned long start, unsigned long end,
return nr;
}
+EXPORT_SYMBOL(__vmap_page_range_noflush);
+
+static int vmap_page_range_noflush(unsigned long start, unsigned long end,
+ pgprot_t prot, struct page **pages)
+{
+ kmsan_vmap_page_range_noflush(start, end, prot, pages);
+ return __vmap_page_range_noflush(start, end, prot, pages);
+}
static int vmap_page_range(unsigned long start, unsigned long end,
pgprot_t prot, struct page **pages)
--
2.24.1.735.g03f4e72817-goog
next prev parent reply other threads:[~2019-12-20 18:51 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-20 18:49 [PATCH RFC v4 00/42] Add KernelMemorySanitizer infrastructure glider
2019-12-20 18:49 ` [PATCH RFC v4 01/42] stackdepot: check depot_index before accessing the stack slab glider
2019-12-20 18:49 ` [PATCH RFC v4 02/42] stackdepot: build with -fno-builtin glider
2020-01-03 17:37 ` Steven Rostedt
2019-12-20 18:49 ` [PATCH RFC v4 03/42] kasan: stackdepot: move filter_irq_stacks() to stackdepot.c glider
2019-12-20 18:49 ` [PATCH RFC v4 04/42] stackdepot: reserve 5 extra bits in depot_stack_handle_t glider
2019-12-20 18:49 ` [PATCH RFC v4 05/42] kmsan: add ReST documentation glider
2019-12-20 18:49 ` [PATCH RFC v4 06/42] kmsan: gfp: introduce __GFP_NO_KMSAN_SHADOW glider
2019-12-20 18:49 ` [PATCH RFC v4 07/42] kmsan: introduce __no_sanitize_memory and __SANITIZE_MEMORY__ glider
2019-12-20 18:49 ` [PATCH RFC v4 08/42] kmsan: reduce vmalloc space glider
2019-12-20 18:49 ` [PATCH RFC v4 09/42] kmsan: add KMSAN runtime core glider
2019-12-20 18:49 ` [PATCH RFC v4 10/42] kmsan: KMSAN compiler API implementation glider
2019-12-20 18:49 ` [PATCH RFC v4 11/42] kmsan: add KMSAN hooks for kernel subsystems glider
2019-12-20 18:49 ` [PATCH RFC v4 12/42] kmsan: stackdepot: don't allocate KMSAN metadata for stackdepot glider
2019-12-20 18:49 ` [PATCH RFC v4 13/42] kmsan: define READ_ONCE_NOCHECK() glider
2019-12-20 18:49 ` [PATCH RFC v4 14/42] kmsan: make READ_ONCE_TASK_STACK() return initialized values glider
2019-12-20 18:49 ` [PATCH RFC v4 15/42] kmsan: x86: sync metadata pages on page fault glider
2019-12-20 18:49 ` [PATCH RFC v4 16/42] kmsan: add tests for KMSAN glider
2019-12-20 18:49 ` [PATCH RFC v4 17/42] crypto: kmsan: disable accelerated configs under KMSAN glider
2019-12-20 19:44 ` Eric Biggers
2020-01-09 14:56 ` Alexander Potapenko
2019-12-20 18:49 ` [PATCH RFC v4 18/42] kmsan: x86: disable UNWINDER_ORC " glider
2019-12-20 18:49 ` [PATCH RFC v4 19/42] kmsan: x86/asm: softirq: add KMSAN IRQ entry hooks glider
2019-12-23 19:58 ` kbuild test robot
2019-12-24 14:38 ` kbuild test robot
2019-12-20 18:49 ` [PATCH RFC v4 20/42] kmsan: x86: increase stack sizes in KMSAN builds glider
2019-12-30 17:39 ` Arnd Bergmann
2020-01-08 15:31 ` Alexander Potapenko
2019-12-20 18:49 ` [PATCH RFC v4 21/42] kmsan: disable KMSAN instrumentation for certain kernel parts glider
2019-12-20 18:49 ` [PATCH RFC v4 22/42] kmsan: mm: call KMSAN hooks from SLUB code glider
2019-12-20 18:49 ` glider [this message]
2019-12-20 18:49 ` [PATCH RFC v4 24/42] kmsan: handle memory sent to/from USB glider
2019-12-20 18:49 ` [PATCH RFC v4 25/42] kmsan: handle task creation and exiting glider
2019-12-20 18:49 ` [PATCH RFC v4 26/42] kmsan: net: check the value of skb before sending it to the network glider
2019-12-20 18:49 ` [PATCH RFC v4 27/42] kmsan: printk: treat the result of vscnprintf() as initialized glider
2019-12-20 18:49 ` [PATCH RFC v4 28/42] kmsan: disable instrumentation of certain functions glider
2019-12-20 18:49 ` [PATCH RFC v4 29/42] kmsan: unpoison |tlb| in arch_tlb_gather_mmu() glider
2019-12-20 18:49 ` [PATCH RFC v4 30/42] kmsan: use __msan_ string functions where possible glider
2019-12-20 18:49 ` [PATCH RFC v4 31/42] kmsan: hooks for copy_to_user() and friends glider
2019-12-24 4:50 ` kbuild test robot
2019-12-24 4:50 ` kbuild test robot
2019-12-20 18:49 ` [PATCH RFC v4 32/42] kmsan: init: call KMSAN initialization routines glider
2019-12-20 18:49 ` [PATCH RFC v4 33/42] kmsan: enable KMSAN builds glider
2019-12-20 18:49 ` [PATCH RFC v4 34/42] kmsan: handle /dev/[u]random glider
2019-12-20 18:49 ` [PATCH RFC v4 35/42] kmsan: virtio: check/unpoison scatterlist in vring_map_one_sg() glider
2019-12-20 18:49 ` [PATCH RFC v4 36/42] kmsan: disable strscpy() optimization under KMSAN glider
2019-12-20 18:49 ` [PATCH RFC v4 37/42] kmsan: add iomap support glider
2019-12-20 18:49 ` [PATCH RFC v4 38/42] kmsan: dma: unpoison memory mapped by dma_direct_map_page() glider
2019-12-20 18:49 ` [PATCH RFC v4 39/42] kmsan: disable physical page merging in biovec glider
2019-12-20 18:49 ` [PATCH RFC v4 40/42] kmsan: ext4: skip block merging logic in ext4_mpage_readpages for KMSAN glider
2019-12-20 19:18 ` Eric Biggers
2020-01-08 16:14 ` Alexander Potapenko
2019-12-20 18:49 ` [PATCH RFC v4 41/42] x86: kasan: kmsan: support CONFIG_GENERIC_CSUM on x86, enable it for KASAN/KMSAN glider
2019-12-20 18:49 ` [PATCH RFC v4 42/42] kmsan: x86/uprobes: unpoison regs in arch_uprobe_exception_notify() glider
2019-12-23 7:51 ` [PATCH RFC v4 00/42] Add KernelMemorySanitizer infrastructure Leon Romanovsky
2020-01-09 14:38 ` Alexander Potapenko
2020-01-09 16:29 ` Thomas Gleixner
2020-03-25 11:04 ` Alexander Potapenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191220184955.223741-24-glider@google.com \
--to=glider@google.com \
--cc=adilger.kernel@dilger.ca \
--cc=akpm@linux-foundation.org \
--cc=andreyknvl@google.com \
--cc=ard.biesheuvel@linaro.org \
--cc=arnd@arndb.de \
--cc=aryabinin@virtuozzo.com \
--cc=axboe@kernel.dk \
--cc=cai@lca.pw \
--cc=darrick.wong@oracle.com \
--cc=davem@davemloft.net \
--cc=dmitry.torokhov@gmail.com \
--cc=dvyukov@google.com \
--cc=ebiggers@google.com \
--cc=edumazet@google.com \
--cc=elver@google.com \
--cc=ericvh@gmail.com \
--cc=gor@linux.ibm.com \
--cc=gregkh@linuxfoundation.org \
--cc=harry.wentland@amd.com \
--cc=hch@infradead.org \
--cc=hch@lst.de \
--cc=herbert@gondor.apana.org.au \
--cc=iii@linux.ibm.com \
--cc=jasowang@redhat.com \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=mark.rutland@arm.com \
--cc=martin.petersen@oracle.com \
--cc=mhocko@suse.com \
--cc=mingo@elte.hu \
--cc=monstr@monstr.eu \
--cc=mst@redhat.com \
--cc=pmladek@suse.com \
--cc=rdunlap@infradead.org \
--cc=robin.murphy@arm.com \
--cc=rostedt@goodmis.org \
--cc=schwidefsky@de.ibm.com \
--cc=sergey.senozhatsky@gmail.com \
--cc=tglx@linutronix.de \
--cc=tiwai@suse.com \
--cc=tytso@mit.edu \
--cc=vegard.nossum@oracle.com \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=wsa@the-dreams.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.