Skip to content

Commit

Permalink
mm: add arch-independent testcases for RODATA
Browse files Browse the repository at this point in the history
This patch makes arch-independent testcases for RODATA.  Both x86 and
x86_64 already have testcases for RODATA, But they are arch-specific
because using inline assembly directly.

And cacheflush.h is not a suitable location for rodata-test related
things.  Since they were in cacheflush.h, If someone change the state of
CONFIG_DEBUG_RODATA_TEST, It cause overhead of kernel build.

To solve the above issues, write arch-independent testcases and move it
to shared location.

[[email protected]: fix config dependency]
  Link: http://lkml.kernel.org/r/20170209131625.GA16954@pjb1027-Latitude-E5410
Link: http://lkml.kernel.org/r/20170129105436.GA9303@pjb1027-Latitude-E5410
Signed-off-by: Jinbum Park <[email protected]>
Acked-by: Kees Cook <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Arjan van de Ven <[email protected]>
Cc: Laura Abbott <[email protected]>
Cc: Russell King <[email protected]>
Cc: Valentin Rothberg <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
jinb-park authored and torvalds committed Feb 28, 2017
1 parent 8d85063 commit 2959a5f
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 105 deletions.
8 changes: 0 additions & 8 deletions arch/x86/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,6 @@ config EFI_PGT_DUMP
issues with the mapping of the EFI runtime regions into that
table.

config DEBUG_RODATA_TEST
bool "Testcase for the marking rodata read-only"
default y
---help---
This option enables a testcase for the setting rodata read-only
as well as for the change_page_attr() infrastructure.
If in doubt, say "N"

config DEBUG_WX
bool "Warn on W+X mappings at boot"
select X86_PTDUMP_CORE
Expand Down
10 changes: 0 additions & 10 deletions arch/x86/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,8 @@ void clflush_cache_range(void *addr, unsigned int size);

#define mmio_flush_range(addr, size) clflush_cache_range(addr, size)

extern const int rodata_test_data;
extern int kernel_set_to_readonly;
void set_kernel_text_rw(void);
void set_kernel_text_ro(void);

#ifdef CONFIG_DEBUG_RODATA_TEST
int rodata_test(void);
#else
static inline int rodata_test(void)
{
return 0;
}
#endif

#endif /* _ASM_X86_CACHEFLUSH_H */
1 change: 0 additions & 1 deletion arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_APB_TIMER) += apb_timer.o

obj-$(CONFIG_AMD_NB) += amd_nb.o
obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o

obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o
Expand Down
75 changes: 0 additions & 75 deletions arch/x86/kernel/test_rodata.c

This file was deleted.

4 changes: 0 additions & 4 deletions arch/x86/mm/init_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,9 +864,6 @@ static noinline int do_test_wp_bit(void)
return flag;
}

const int rodata_test_data = 0xC3;
EXPORT_SYMBOL_GPL(rodata_test_data);

int kernel_set_to_readonly __read_mostly;

void set_kernel_text_rw(void)
Expand Down Expand Up @@ -939,7 +936,6 @@ void mark_rodata_ro(void)
set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
size >> 10);
rodata_test();

#ifdef CONFIG_CPA_DEBUG
printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, start + size);
Expand Down
5 changes: 0 additions & 5 deletions arch/x86/mm/init_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,9 +1000,6 @@ void __init mem_init(void)
mem_init_print_info(NULL);
}

const int rodata_test_data = 0xC3;
EXPORT_SYMBOL_GPL(rodata_test_data);

int kernel_set_to_readonly;

void set_kernel_text_rw(void)
Expand Down Expand Up @@ -1071,8 +1068,6 @@ void mark_rodata_ro(void)
all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT);

rodata_test();

#ifdef CONFIG_CPA_DEBUG
printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end);
set_memory_rw(start, (end-start) >> PAGE_SHIFT);
Expand Down
23 changes: 23 additions & 0 deletions include/linux/rodata_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* rodata_test.h: functional test for mark_rodata_ro function
*
* (C) Copyright 2008 Intel Corporation
* Author: Arjan van de Ven <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/

#ifndef _RODATA_TEST_H
#define _RODATA_TEST_H

#ifdef CONFIG_DEBUG_RODATA_TEST
extern const int rodata_test_data;
void rodata_test(void);
#else
static inline void rodata_test(void) {}
#endif

#endif /* _RODATA_TEST_H */
6 changes: 4 additions & 2 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
#include <linux/proc_ns.h>
#include <linux/io.h>
#include <linux/cache.h>
#include <linux/rodata_test.h>

#include <asm/io.h>
#include <asm/bugs.h>
Expand Down Expand Up @@ -935,9 +936,10 @@ __setup("rodata=", set_debug_rodata);
#ifdef CONFIG_STRICT_KERNEL_RWX
static void mark_readonly(void)
{
if (rodata_enabled)
if (rodata_enabled) {
mark_rodata_ro();
else
rodata_test();
} else
pr_info("Kernel memory protection disabled.\n");
}
#else
Expand Down
6 changes: 6 additions & 0 deletions mm/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@ config DEBUG_PAGE_REF
careful when enabling this feature because it adds about 30 KB to the
kernel code. However the runtime performance overhead is virtually
nil until the tracepoints are actually enabled.

config DEBUG_RODATA_TEST
bool "Testcase for the marking rodata read-only"
depends on STRICT_KERNEL_RWX
---help---
This option enables a testcase for the setting rodata read-only.
1 change: 1 addition & 0 deletions mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o
obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
obj-$(CONFIG_DEBUG_RODATA_TEST) += rodata_test.o
obj-$(CONFIG_PAGE_OWNER) += page_owner.o
obj-$(CONFIG_CLEANCACHE) += cleancache.o
obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
Expand Down
56 changes: 56 additions & 0 deletions mm/rodata_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* rodata_test.c: functional test for mark_rodata_ro function
*
* (C) Copyright 2008 Intel Corporation
* Author: Arjan van de Ven <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/uaccess.h>
#include <asm/sections.h>

const int rodata_test_data = 0xC3;
EXPORT_SYMBOL_GPL(rodata_test_data);

void rodata_test(void)
{
unsigned long start, end;
int zero = 0;

/* test 1: read the value */
/* If this test fails, some previous testrun has clobbered the state */
if (!rodata_test_data) {
pr_err("rodata_test: test 1 fails (start data)\n");
return;
}

/* test 2: write to the variable; this should fault */
if (!probe_kernel_write((void *)&rodata_test_data,
(void *)&zero, sizeof(zero))) {
pr_err("rodata_test: test data was not read only\n");
return;
}

/* test 3: check the value hasn't changed */
if (rodata_test_data == zero) {
pr_err("rodata_test: test data was changed\n");
return;
}

/* test 4: check if the rodata section is PAGE_SIZE aligned */
start = (unsigned long)__start_rodata;
end = (unsigned long)__end_rodata;
if (start & (PAGE_SIZE - 1)) {
pr_err("rodata_test: start of .rodata is not page size aligned\n");
return;
}
if (end & (PAGE_SIZE - 1)) {
pr_err("rodata_test: end of .rodata is not page size aligned\n");
return;
}

pr_info("rodata_test: all tests were successful\n");
}

0 comments on commit 2959a5f

Please sign in to comment.