summaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2019-07-11 23:53:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-12 14:05:41 -0400
commit966fede8e4be15bcc08e3c390080d3f9072a5367 (patch)
tree93fcad54232f4e760a1d5bd6ae6ecf1ba1e5a7f7 /drivers/misc
parenta64b53780ec35b77daf817210c88aa42d172c98f (diff)
lkdtm/heap: add tests for freelist hardening
This adds tests for double free and cross-cache freeing, which should both be caught by CONFIG_SLAB_FREELIST_HARDENED. Link: http://lkml.kernel.org/r/20190530045017.15252-4-keescook@chromium.org Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Alexander Popov <alex.popov@linux.com> Cc: Alexander Potapenko <glider@google.com> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Pekka Enberg <penberg@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/lkdtm/core.c5
-rw-r--r--drivers/misc/lkdtm/heap.c72
-rw-r--r--drivers/misc/lkdtm/lkdtm.h5
3 files changed, 82 insertions, 0 deletions
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index bba49abb6750..c7a507482051 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -120,6 +120,9 @@ static const struct crashtype crashtypes[] = {
120 CRASHTYPE(READ_AFTER_FREE), 120 CRASHTYPE(READ_AFTER_FREE),
121 CRASHTYPE(WRITE_BUDDY_AFTER_FREE), 121 CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
122 CRASHTYPE(READ_BUDDY_AFTER_FREE), 122 CRASHTYPE(READ_BUDDY_AFTER_FREE),
123 CRASHTYPE(SLAB_FREE_DOUBLE),
124 CRASHTYPE(SLAB_FREE_CROSS),
125 CRASHTYPE(SLAB_FREE_PAGE),
123 CRASHTYPE(SOFTLOCKUP), 126 CRASHTYPE(SOFTLOCKUP),
124 CRASHTYPE(HARDLOCKUP), 127 CRASHTYPE(HARDLOCKUP),
125 CRASHTYPE(SPINLOCKUP), 128 CRASHTYPE(SPINLOCKUP),
@@ -426,6 +429,7 @@ static int __init lkdtm_module_init(void)
426 lkdtm_bugs_init(&recur_count); 429 lkdtm_bugs_init(&recur_count);
427 lkdtm_perms_init(); 430 lkdtm_perms_init();
428 lkdtm_usercopy_init(); 431 lkdtm_usercopy_init();
432 lkdtm_heap_init();
429 433
430 /* Register debugfs interface */ 434 /* Register debugfs interface */
431 lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); 435 lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
@@ -472,6 +476,7 @@ static void __exit lkdtm_module_exit(void)
472 debugfs_remove_recursive(lkdtm_debugfs_root); 476 debugfs_remove_recursive(lkdtm_debugfs_root);
473 477
474 /* Handle test-specific clean-up. */ 478 /* Handle test-specific clean-up. */
479 lkdtm_heap_exit();
475 lkdtm_usercopy_exit(); 480 lkdtm_usercopy_exit();
476 481
477 if (lkdtm_kprobe != NULL) 482 if (lkdtm_kprobe != NULL)
diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c
index 65026d7de130..3c5cec85edce 100644
--- a/drivers/misc/lkdtm/heap.c
+++ b/drivers/misc/lkdtm/heap.c
@@ -7,6 +7,10 @@
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9 9
10static struct kmem_cache *double_free_cache;
11static struct kmem_cache *a_cache;
12static struct kmem_cache *b_cache;
13
10/* 14/*
11 * This tries to stay within the next largest power-of-2 kmalloc cache 15 * This tries to stay within the next largest power-of-2 kmalloc cache
12 * to avoid actually overwriting anything important if it's not detected 16 * to avoid actually overwriting anything important if it's not detected
@@ -146,3 +150,71 @@ void lkdtm_READ_BUDDY_AFTER_FREE(void)
146 150
147 kfree(val); 151 kfree(val);
148} 152}
153
154void lkdtm_SLAB_FREE_DOUBLE(void)
155{
156 int *val;
157
158 val = kmem_cache_alloc(double_free_cache, GFP_KERNEL);
159 if (!val) {
160 pr_info("Unable to allocate double_free_cache memory.\n");
161 return;
162 }
163
164 /* Just make sure we got real memory. */
165 *val = 0x12345678;
166 pr_info("Attempting double slab free ...\n");
167 kmem_cache_free(double_free_cache, val);
168 kmem_cache_free(double_free_cache, val);
169}
170
171void lkdtm_SLAB_FREE_CROSS(void)
172{
173 int *val;
174
175 val = kmem_cache_alloc(a_cache, GFP_KERNEL);
176 if (!val) {
177 pr_info("Unable to allocate a_cache memory.\n");
178 return;
179 }
180
181 /* Just make sure we got real memory. */
182 *val = 0x12345679;
183 pr_info("Attempting cross-cache slab free ...\n");
184 kmem_cache_free(b_cache, val);
185}
186
187void lkdtm_SLAB_FREE_PAGE(void)
188{
189 unsigned long p = __get_free_page(GFP_KERNEL);
190
191 pr_info("Attempting non-Slab slab free ...\n");
192 kmem_cache_free(NULL, (void *)p);
193 free_page(p);
194}
195
196/*
197 * We have constructors to keep the caches distinctly separated without
198 * needing to boot with "slab_nomerge".
199 */
200static void ctor_double_free(void *region)
201{ }
202static void ctor_a(void *region)
203{ }
204static void ctor_b(void *region)
205{ }
206
207void __init lkdtm_heap_init(void)
208{
209 double_free_cache = kmem_cache_create("lkdtm-heap-double_free",
210 64, 0, 0, ctor_double_free);
211 a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a);
212 b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b);
213}
214
215void __exit lkdtm_heap_exit(void)
216{
217 kmem_cache_destroy(double_free_cache);
218 kmem_cache_destroy(a_cache);
219 kmem_cache_destroy(b_cache);
220}
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 23dc565b4307..c5ae0b37587d 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -28,11 +28,16 @@ void lkdtm_STACK_GUARD_PAGE_LEADING(void);
28void lkdtm_STACK_GUARD_PAGE_TRAILING(void); 28void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
29 29
30/* lkdtm_heap.c */ 30/* lkdtm_heap.c */
31void __init lkdtm_heap_init(void);
32void __exit lkdtm_heap_exit(void);
31void lkdtm_OVERWRITE_ALLOCATION(void); 33void lkdtm_OVERWRITE_ALLOCATION(void);
32void lkdtm_WRITE_AFTER_FREE(void); 34void lkdtm_WRITE_AFTER_FREE(void);
33void lkdtm_READ_AFTER_FREE(void); 35void lkdtm_READ_AFTER_FREE(void);
34void lkdtm_WRITE_BUDDY_AFTER_FREE(void); 36void lkdtm_WRITE_BUDDY_AFTER_FREE(void);
35void lkdtm_READ_BUDDY_AFTER_FREE(void); 37void lkdtm_READ_BUDDY_AFTER_FREE(void);
38void lkdtm_SLAB_FREE_DOUBLE(void);
39void lkdtm_SLAB_FREE_CROSS(void);
40void lkdtm_SLAB_FREE_PAGE(void);
36 41
37/* lkdtm_perms.c */ 42/* lkdtm_perms.c */
38void __init lkdtm_perms_init(void); 43void __init lkdtm_perms_init(void);