Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a49a528 authored by Kees Cook's avatar Kees Cook
Browse files

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: default avatarKees Cook <keescook@chromium.org>
parent 426f3a53
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -59,3 +59,11 @@ obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_PANEL)             += panel.o

lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
lkdtm-$(CONFIG_LKDTM)		+= lkdtm_rodata_objcopy.o

OBJCOPYFLAGS :=
OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \
			--set-section-flags .text=alloc,readonly \
			--rename-section .text=.rodata
$(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o
	$(call if_changed,objcopy)

drivers/misc/lkdtm.h

0 → 100644
+6 −0
Original line number Diff line number Diff line
#ifndef __LKDTM_H
#define __LKDTM_H

void lkdtm_rodata_do_nothing(void);

#endif
+17 −7
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@
#include <linux/ide.h>
#endif

#include "lkdtm.h"

/*
 * Make sure our attempts to over run the kernel stack doesn't trigger
 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -103,6 +105,7 @@ enum ctype {
	CT_EXEC_STACK,
	CT_EXEC_KMALLOC,
	CT_EXEC_VMALLOC,
	CT_EXEC_RODATA,
	CT_EXEC_USERSPACE,
	CT_ACCESS_USERSPACE,
	CT_WRITE_RO,
@@ -145,6 +148,7 @@ static char* cp_type[] = {
	"EXEC_STACK",
	"EXEC_KMALLOC",
	"EXEC_VMALLOC",
	"EXEC_RODATA",
	"EXEC_USERSPACE",
	"ACCESS_USERSPACE",
	"WRITE_RO",
@@ -346,15 +350,18 @@ static noinline void corrupt_stack(void)
	memset((void *)data, 0, 64);
}

static void noinline execute_location(void *dst)
static noinline void execute_location(void *dst, bool write)
{
	void (*func)(void) = dst;

	pr_info("attempting ok execution at %p\n", do_nothing);
	do_nothing();

	if (write) {
		memcpy(dst, do_nothing, EXEC_SIZE);
	flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
		flush_icache_range((unsigned long)dst,
				   (unsigned long)dst + EXEC_SIZE);
	}
	pr_info("attempting bad execution at %p\n", func);
	func();
}
@@ -551,25 +558,28 @@ static void lkdtm_do_action(enum ctype which)
		schedule();
		break;
	case CT_EXEC_DATA:
		execute_location(data_area);
		execute_location(data_area, true);
		break;
	case CT_EXEC_STACK: {
		u8 stack_area[EXEC_SIZE];
		execute_location(stack_area);
		execute_location(stack_area, true);
		break;
	}
	case CT_EXEC_KMALLOC: {
		u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL);
		execute_location(kmalloc_area);
		execute_location(kmalloc_area, true);
		kfree(kmalloc_area);
		break;
	}
	case CT_EXEC_VMALLOC: {
		u32 *vmalloc_area = vmalloc(EXEC_SIZE);
		execute_location(vmalloc_area);
		execute_location(vmalloc_area, true);
		vfree(vmalloc_area);
		break;
	}
	case CT_EXEC_RODATA:
		execute_location(lkdtm_rodata_do_nothing, false);
		break;
	case CT_EXEC_USERSPACE: {
		unsigned long user_addr;

+10 −0
Original line number Diff line number Diff line
/*
 * This includes functions that are meant to live entirely in .rodata
 * (via objcopy tricks), to validate the non-executability of .rodata.
 */
#include <linux/kernel.h>

void lkdtm_rodata_do_nothing(void)
{
	/* Does nothing. We just want an architecture agnostic "return". */
}