aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-02-22 17:09:29 -0500
committerKees Cook <keescook@chromium.org>2016-06-10 18:57:50 -0400
commit9a49a528dcf3c2022ff89f700d5d0345b9abf288 (patch)
tree946dc7b2e73cf54e9b349f881970d47755060c42
parent426f3a53d4a1ffbe228f268e5c4af148686b7346 (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/Makefile8
-rw-r--r--drivers/misc/lkdtm.h6
-rw-r--r--drivers/misc/lkdtm_core.c24
-rw-r--r--drivers/misc/lkdtm_rodata.c10
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/
59obj-$(CONFIG_PANEL) += panel.o 59obj-$(CONFIG_PANEL) += panel.o
60 60
61lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o 61lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
62lkdtm-$(CONFIG_LKDTM) += lkdtm_rodata_objcopy.o
63
64OBJCOPYFLAGS :=
65OBJCOPYFLAGS_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
4void 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
349static void noinline execute_location(void *dst) 353static 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
7void lkdtm_rodata_do_nothing(void)
8{
9 /* Does nothing. We just want an architecture agnostic "return". */
10}