diff options
author | Kees Cook <keescook@chromium.org> | 2016-02-22 17:09:29 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2016-06-10 18:57:50 -0400 |
commit | 9a49a528dcf3c2022ff89f700d5d0345b9abf288 (patch) | |
tree | 946dc7b2e73cf54e9b349f881970d47755060c42 | |
parent | 426f3a53d4a1ffbe228f268e5c4af148686b7346 (diff) |
lkdtm: add function for testing .rodata section
This adds a function that lives in the .rodata section. The section
flags are corrected using objcopy since there is no way with gcc to
declare section flags in an architecture-agnostic way.
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | drivers/misc/Makefile | 8 | ||||
-rw-r--r-- | drivers/misc/lkdtm.h | 6 | ||||
-rw-r--r-- | drivers/misc/lkdtm_core.c | 24 | ||||
-rw-r--r-- | drivers/misc/lkdtm_rodata.c | 10 |
4 files changed, 41 insertions, 7 deletions
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c3cb6ad8cc37..7d45ed4a1549 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -59,3 +59,11 @@ obj-$(CONFIG_CXL_BASE) += cxl/ | |||
59 | obj-$(CONFIG_PANEL) += panel.o | 59 | obj-$(CONFIG_PANEL) += panel.o |
60 | 60 | ||
61 | lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o | 61 | lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o |
62 | lkdtm-$(CONFIG_LKDTM) += lkdtm_rodata_objcopy.o | ||
63 | |||
64 | OBJCOPYFLAGS := | ||
65 | OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \ | ||
66 | --set-section-flags .text=alloc,readonly \ | ||
67 | --rename-section .text=.rodata | ||
68 | $(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o | ||
69 | $(call if_changed,objcopy) | ||
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h new file mode 100644 index 000000000000..9531fa3be4c3 --- /dev/null +++ b/drivers/misc/lkdtm.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __LKDTM_H | ||
2 | #define __LKDTM_H | ||
3 | |||
4 | void lkdtm_rodata_do_nothing(void); | ||
5 | |||
6 | #endif | ||
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c index 605050c60f10..187cd9b63e9a 100644 --- a/drivers/misc/lkdtm_core.c +++ b/drivers/misc/lkdtm_core.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/ide.h> | 52 | #include <linux/ide.h> |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #include "lkdtm.h" | ||
56 | |||
55 | /* | 57 | /* |
56 | * Make sure our attempts to over run the kernel stack doesn't trigger | 58 | * Make sure our attempts to over run the kernel stack doesn't trigger |
57 | * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we | 59 | * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we |
@@ -103,6 +105,7 @@ enum ctype { | |||
103 | CT_EXEC_STACK, | 105 | CT_EXEC_STACK, |
104 | CT_EXEC_KMALLOC, | 106 | CT_EXEC_KMALLOC, |
105 | CT_EXEC_VMALLOC, | 107 | CT_EXEC_VMALLOC, |
108 | CT_EXEC_RODATA, | ||
106 | CT_EXEC_USERSPACE, | 109 | CT_EXEC_USERSPACE, |
107 | CT_ACCESS_USERSPACE, | 110 | CT_ACCESS_USERSPACE, |
108 | CT_WRITE_RO, | 111 | CT_WRITE_RO, |
@@ -145,6 +148,7 @@ static char* cp_type[] = { | |||
145 | "EXEC_STACK", | 148 | "EXEC_STACK", |
146 | "EXEC_KMALLOC", | 149 | "EXEC_KMALLOC", |
147 | "EXEC_VMALLOC", | 150 | "EXEC_VMALLOC", |
151 | "EXEC_RODATA", | ||
148 | "EXEC_USERSPACE", | 152 | "EXEC_USERSPACE", |
149 | "ACCESS_USERSPACE", | 153 | "ACCESS_USERSPACE", |
150 | "WRITE_RO", | 154 | "WRITE_RO", |
@@ -346,15 +350,18 @@ static noinline void corrupt_stack(void) | |||
346 | memset((void *)data, 0, 64); | 350 | memset((void *)data, 0, 64); |
347 | } | 351 | } |
348 | 352 | ||
349 | static void noinline execute_location(void *dst) | 353 | static noinline void execute_location(void *dst, bool write) |
350 | { | 354 | { |
351 | void (*func)(void) = dst; | 355 | void (*func)(void) = dst; |
352 | 356 | ||
353 | pr_info("attempting ok execution at %p\n", do_nothing); | 357 | pr_info("attempting ok execution at %p\n", do_nothing); |
354 | do_nothing(); | 358 | do_nothing(); |
355 | 359 | ||
356 | memcpy(dst, do_nothing, EXEC_SIZE); | 360 | if (write) { |
357 | flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); | 361 | memcpy(dst, do_nothing, EXEC_SIZE); |
362 | flush_icache_range((unsigned long)dst, | ||
363 | (unsigned long)dst + EXEC_SIZE); | ||
364 | } | ||
358 | pr_info("attempting bad execution at %p\n", func); | 365 | pr_info("attempting bad execution at %p\n", func); |
359 | func(); | 366 | func(); |
360 | } | 367 | } |
@@ -551,25 +558,28 @@ static void lkdtm_do_action(enum ctype which) | |||
551 | schedule(); | 558 | schedule(); |
552 | break; | 559 | break; |
553 | case CT_EXEC_DATA: | 560 | case CT_EXEC_DATA: |
554 | execute_location(data_area); | 561 | execute_location(data_area, true); |
555 | break; | 562 | break; |
556 | case CT_EXEC_STACK: { | 563 | case CT_EXEC_STACK: { |
557 | u8 stack_area[EXEC_SIZE]; | 564 | u8 stack_area[EXEC_SIZE]; |
558 | execute_location(stack_area); | 565 | execute_location(stack_area, true); |
559 | break; | 566 | break; |
560 | } | 567 | } |
561 | case CT_EXEC_KMALLOC: { | 568 | case CT_EXEC_KMALLOC: { |
562 | u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL); | 569 | u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL); |
563 | execute_location(kmalloc_area); | 570 | execute_location(kmalloc_area, true); |
564 | kfree(kmalloc_area); | 571 | kfree(kmalloc_area); |
565 | break; | 572 | break; |
566 | } | 573 | } |
567 | case CT_EXEC_VMALLOC: { | 574 | case CT_EXEC_VMALLOC: { |
568 | u32 *vmalloc_area = vmalloc(EXEC_SIZE); | 575 | u32 *vmalloc_area = vmalloc(EXEC_SIZE); |
569 | execute_location(vmalloc_area); | 576 | execute_location(vmalloc_area, true); |
570 | vfree(vmalloc_area); | 577 | vfree(vmalloc_area); |
571 | break; | 578 | break; |
572 | } | 579 | } |
580 | case CT_EXEC_RODATA: | ||
581 | execute_location(lkdtm_rodata_do_nothing, false); | ||
582 | break; | ||
573 | case CT_EXEC_USERSPACE: { | 583 | case CT_EXEC_USERSPACE: { |
574 | unsigned long user_addr; | 584 | unsigned long user_addr; |
575 | 585 | ||
diff --git a/drivers/misc/lkdtm_rodata.c b/drivers/misc/lkdtm_rodata.c new file mode 100644 index 000000000000..4d0d851f02b9 --- /dev/null +++ b/drivers/misc/lkdtm_rodata.c | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * This includes functions that are meant to live entirely in .rodata | ||
3 | * (via objcopy tricks), to validate the non-executability of .rodata. | ||
4 | */ | ||
5 | #include <linux/kernel.h> | ||
6 | |||
7 | void lkdtm_rodata_do_nothing(void) | ||
8 | { | ||
9 | /* Does nothing. We just want an architecture agnostic "return". */ | ||
10 | } | ||