All of lore.kernel.org
 help / color / mirror / Atom feed
From: glider@google.com
To: Alexander Potapenko <glider@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Vegard Nossum <vegard.nossum@oracle.com>,
	 Dmitry Vyukov <dvyukov@google.com>,
	linux-mm@kvack.org
Subject: [PATCH RFC v1 18/26] kmsan: mm: call KMSAN hooks from SLUB code
Date: Fri, 18 Oct 2019 11:42:56 +0200	[thread overview]
Message-ID: <20191018094304.37056-19-glider@google.com> (raw)
In-Reply-To: <20191018094304.37056-1-glider@google.com>

In order to report uninitialized memory coming from heap allocations
KMSAN has to poison them unless they're created with __GFP_ZERO.

It's handy that we need KMSAN hooks in the places where
init_on_alloc/init_on_free initialization is performed.

Signed-off-by: Alexander Potapenko <glider@google.com>
To: Alexander Potapenko <glider@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: linux-mm@kvack.org
---

Change-Id: I51103b7981d3aabed747d0c85cbdc85568665871
---
 mm/slub.c | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 3d63ae320d31..3d6d4c63446e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -21,6 +21,8 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/kasan.h>
+#include <linux/kmsan.h>
+#include <linux/kmsan-checks.h> /* KMSAN_INIT_VALUE */
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
 #include <linux/mempolicy.h>
@@ -285,17 +287,27 @@ static void prefetch_freepointer(const struct kmem_cache *s, void *object)
 	prefetch(object + s->offset);
 }
 
+/*
+ * When running under KMSAN, get_freepointer_safe() may return an uninitialized
+ * pointer value in the case the current thread loses the race for the next
+ * memory chunk in the freelist. In that case this_cpu_cmpxchg_double() in
+ * slab_alloc_node() will fail, so the uninitialized value won't be used, but
+ * KMSAN will still check all arguments of cmpxchg because of imperfect
+ * handling of inline assembly.
+ * To work around this problem, use KMSAN_INIT_VALUE() to force initialize the
+ * return value of get_freepointer_safe().
+ */
 static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
 {
 	unsigned long freepointer_addr;
 	void *p;
 
 	if (!debug_pagealloc_enabled())
-		return get_freepointer(s, object);
+		return KMSAN_INIT_VALUE(get_freepointer(s, object));
 
 	freepointer_addr = (unsigned long)object + s->offset;
 	probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p));
-	return freelist_ptr(s, p, freepointer_addr);
+	return KMSAN_INIT_VALUE(freelist_ptr(s, p, freepointer_addr));
 }
 
 static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
@@ -1390,6 +1402,7 @@ static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
 	ptr = kasan_kmalloc_large(ptr, size, flags);
 	/* As ptr might get tagged, call kmemleak hook after KASAN. */
 	kmemleak_alloc(ptr, size, 1, flags);
+	kmsan_kmalloc_large(ptr, size, flags);
 	return ptr;
 }
 
@@ -1397,6 +1410,7 @@ static __always_inline void kfree_hook(void *x)
 {
 	kmemleak_free(x);
 	kasan_kfree_large(x, _RET_IP_);
+	kmsan_kfree_large(x);
 }
 
 static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x)
@@ -1453,6 +1467,12 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
 		} while (object != old_tail);
 	}
 
+	do {
+		object = next;
+		next = get_freepointer(s, object);
+		kmsan_slab_free(s, object);
+	} while (object != old_tail);
+
 /*
  * Compiler cannot detect this function can be removed if slab_free_hook()
  * evaluates to nothing.  Thus, catch all relevant config debug options here.
@@ -2769,6 +2789,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
 	if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
 		memset(object, 0, s->object_size);
 
+	kmsan_slab_alloc(s, object, gfpflags);
 	slab_post_alloc_hook(s, gfpflags, 1, &object);
 
 	return object;
@@ -2797,6 +2818,7 @@ void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
 	void *ret = slab_alloc(s, gfpflags, _RET_IP_);
 	trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags);
 	ret = kasan_kmalloc(s, ret, size, gfpflags);
+
 	return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_trace);
@@ -2809,7 +2831,6 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
 
 	trace_kmem_cache_alloc_node(_RET_IP_, ret,
 				    s->object_size, s->size, gfpflags, node);
-
 	return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
@@ -2825,6 +2846,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
 			   size, s->size, gfpflags, node);
 
 	ret = kasan_kmalloc(s, ret, size, gfpflags);
+
 	return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
@@ -3150,7 +3172,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
 			  void **p)
 {
 	struct kmem_cache_cpu *c;
-	int i;
+	int i, j;
 
 	/* memcg and kmem_cache debug support */
 	s = slab_pre_alloc_hook(s, flags);
@@ -3188,11 +3210,11 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
 
 	/* Clear memory outside IRQ disabled fastpath loop */
 	if (unlikely(slab_want_init_on_alloc(flags, s))) {
-		int j;
-
 		for (j = 0; j < i; j++)
 			memset(p[j], 0, s->object_size);
 	}
+	for (j = 0; j < i; j++)
+		kmsan_slab_alloc(s, p[j], flags);
 
 	/* memcg and kmem_cache debug support */
 	slab_post_alloc_hook(s, flags, size, p);
@@ -3793,6 +3815,7 @@ static int __init setup_slub_min_objects(char *str)
 
 __setup("slub_min_objects=", setup_slub_min_objects);
 
+__no_sanitize_memory
 void *__kmalloc(size_t size, gfp_t flags)
 {
 	struct kmem_cache *s;
@@ -5698,6 +5721,7 @@ static char *create_unique_id(struct kmem_cache *s)
 	p += sprintf(p, "%07u", s->size);
 
 	BUG_ON(p > name + ID_STR_LENGTH - 1);
+	kmsan_unpoison_shadow(name, p - name);
 	return name;
 }
 
@@ -5847,6 +5871,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
 	al->name = name;
 	al->next = alias_list;
 	alias_list = al;
+	kmsan_unpoison_shadow(al, sizeof(struct saved_alias));
 	return 0;
 }
 
-- 
2.23.0.866.gb869b98d4c-goog



  parent reply	other threads:[~2019-10-18  9:44 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18  9:42 [PATCH RFC v1 00/26] Add KernelMemorySanitizer infrastructure glider
2019-10-18  9:42 ` [PATCH RFC v1 01/26] stackdepot: check depot_index before accessing the stack slab glider
2019-10-18  9:42 ` [PATCH RFC v1 02/26] stackdepot: prevent Clang from optimizing away stackdepot_memcmp() glider
2019-10-18  9:42 ` [PATCH RFC v1 03/26] kasan: stackdepot: move filter_irq_stacks() to stackdepot.c glider
2019-10-18  9:42 ` [PATCH RFC v1 04/26] stackdepot: reserve 5 extra bits in depot_stack_handle_t glider
2019-10-18  9:42 ` [PATCH RFC v1 05/26] printk_safe: externalize printk_context glider
2019-10-21  9:09   ` Petr Mladek
2019-10-23 17:57     ` Alexander Potapenko
2019-10-23 18:00       ` Alexander Potapenko
2019-10-24 12:46       ` Petr Mladek
2019-10-28 13:09         ` Alexander Potapenko
2019-10-29 12:02           ` Petr Mladek
2019-10-29 12:45             ` Alexander Potapenko
2019-10-18  9:42 ` [PATCH RFC v1 06/26] kasan: compiler.h: rename __no_kasan_or_inline into __no_memory_tool_or_inline glider
2019-10-18  9:42 ` [PATCH RFC v1 07/26] kmsan: add ReST documentation glider
2019-10-18  9:42 ` [PATCH RFC v1 08/26] kmsan: gfp: introduce __GFP_NO_KMSAN_SHADOW glider
2019-10-18  9:42 ` [PATCH RFC v1 09/26] kmsan: introduce __no_sanitize_memory and __SANITIZE_MEMORY__ glider
2019-10-18  9:42 ` [PATCH RFC v1 10/26] kmsan: reduce vmalloc space glider
2019-10-18  9:42 ` [PATCH RFC v1 11/26] kmsan: add KMSAN runtime glider
2019-10-18  9:42 ` [PATCH RFC v1 12/26] kmsan: x86: sync metadata pages on page fault glider
2019-10-18  9:42 ` [PATCH RFC v1 13/26] kmsan: add tests for KMSAN glider
2019-10-18  9:42 ` [PATCH RFC v1 14/26] kmsan: make READ_ONCE_TASK_STACK() return initialized values glider
2019-10-18  9:42 ` [PATCH RFC v1 15/26] kmsan: Kconfig changes to disable options incompatible with KMSAN glider
2019-10-21 14:11   ` Harry Wentland
2019-10-18  9:42 ` [PATCH RFC v1 16/26] kmsan: Changing existing files to enable KMSAN builds glider
2019-10-18  9:42 ` [PATCH RFC v1 17/26] kmsan: disable KMSAN instrumentation for certain kernel parts glider
2019-10-18  9:42 ` glider [this message]
2019-10-18 13:22   ` [PATCH RFC v1 18/26] kmsan: mm: call KMSAN hooks from SLUB code Qian Cai
2019-10-18 13:33     ` Alexander Potapenko
2019-10-18 13:41       ` Qian Cai
2019-10-18 13:55         ` Alexander Potapenko
2019-10-18 14:42           ` Qian Cai
2019-10-18 14:54             ` Alexander Potapenko
2019-10-18 15:13               ` Qian Cai
2019-10-18 15:30                 ` Alexander Potapenko
2019-10-18 16:08                   ` Qian Cai
2019-10-18  9:42 ` [PATCH RFC v1 19/26] kmsan: call KMSAN hooks where needed glider
2019-10-18 15:02   ` Qian Cai
2019-10-29 14:09     ` Alexander Potapenko
2019-10-29 14:56       ` Qian Cai
2019-10-21  9:25   ` Petr Mladek
2019-10-29 13:59     ` Alexander Potapenko
2019-10-18  9:42 ` [PATCH RFC v1 20/26] kmsan: disable instrumentation of certain functions glider
2019-10-18  9:42 ` [PATCH RFC v1 21/26] kmsan: unpoison |tlb| in arch_tlb_gather_mmu() glider
2019-10-18  9:43 ` [PATCH RFC v1 22/26] kmsan: use __msan_memcpy() where possible glider
2019-10-18  9:43 ` [PATCH RFC v1 23/26] kmsan: unpoisoning buffers from devices etc glider
2019-10-18 15:27   ` Christoph Hellwig
2019-10-18 16:22   ` Matthew Wilcox
2019-10-29 14:45     ` Alexander Potapenko
2019-10-30 12:43       ` Alexander Potapenko
2019-10-18  9:43 ` [PATCH RFC v1 24/26] kmsan: hooks for copy_to_user() and friends glider
2019-10-18  9:43 ` [PATCH RFC v1 25/26] kmsan: disable strscpy() optimization under KMSAN glider
2019-10-18  9:43 ` [PATCH RFC v1 26/26] net: kasan: kmsan: support CONFIG_GENERIC_CSUM on x86, enable it for KASAN/KMSAN glider
2019-10-19  3:20   ` Randy Dunlap

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=20191018094304.37056-19-glider@google.com \
    --to=glider@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=dvyukov@google.com \
    --cc=linux-mm@kvack.org \
    --cc=vegard.nossum@oracle.com \
    /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.