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

Commit ca359208 authored by Laura Abbott's avatar Laura Abbott Committed by Rohit Vaswani
Browse files

arm64: add better page protections to arm64



Add page protections for arm64 similar to those in arm.
This is for security reasons to prevent certain classes
of exploits. The current method:

- Map all memory as either RWX or RW. We round to the nearest
  section to avoid creating page tables before everything is mapped
- Once everything is mapped, if either end of the RWX section should
  not be X, we split the PMD and remap as necessary
- When initmem is to be freed, we change the permissions back to
  RW (using stop machine if necessary to flush the TLB)
- If CONFIG_DEBUG_RODATA is set, the read only sections are set
  read only.

Change-Id: I4f772643edbde1b91b3de79391e6490c2d3bec48
Acked-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: default avatarKees Cook <keescook@chromium.org>
Tested-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarLaura Abbott <lauraa@codeaurora.org>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Git-commit: da141706aea52c1a9fbd28cb8d289b78819f5436
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


[rvaswani@codeaurora.org: fixed merge conflicts]
Signed-off-by: default avatarRohit Vaswani <rvaswani@codeaurora.org>
parent 00516964
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -101,4 +101,28 @@ config KERNEL_TEXT_RDONLY
	  performance impact.

          If unsure, say N.

config DEBUG_RODATA
	bool "Make kernel text and rodata read-only"
	help
	  If this is set, kernel text and rodata will be made read-only. This
	  is to help catch accidental or malicious attempts to change the
	  kernel's executable code. Additionally splits rodata from kernel
	  text so it can be made explicitly non-executable.

          If in doubt, say Y

config DEBUG_ALIGN_RODATA
	depends on DEBUG_RODATA && !ARM64_64K_PAGES
	bool "Align linker sections up to SECTION_SIZE"
	help
	  If this option is enabled, sections that may potentially be marked as
	  read only or non-executable will be aligned up to the section size of
	  the kernel. This prevents sections from being split into pages and
	  avoids a potential TLB penalty. The downside is an increase in
	  alignment and potentially wasted space. Turn on this option if
	  performance is more important than memory pressure.

	  If in doubt, say N

endmenu
+5 −0
Original line number Diff line number Diff line
@@ -160,6 +160,11 @@ int set_memory_ro(unsigned long addr, int numpages);
int set_memory_rw(unsigned long addr, int numpages);
int set_memory_x(unsigned long addr, int numpages);
int set_memory_nx(unsigned long addr, int numpages);

#ifdef CONFIG_DEBUG_RODATA
void mark_rodata_ro(void);
#endif

#ifdef CONFIG_KERNEL_TEXT_RDONLY
void set_kernel_text_ro(void);
#else
+15 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
#include <asm/pgtable.h>

#include "image.h"

@@ -37,6 +38,14 @@ jiffies = jiffies_64;
	*(.hyp.text)					\
	VMLINUX_SYMBOL(__hyp_text_end) = .;

#ifdef CONFIG_DEBUG_ALIGN_RODATA
#define ALIGN_DEBUG_RO			. = ALIGN(1<<SECTION_SHIFT);
#define ALIGN_DEBUG_RO_MIN(min)		ALIGN_DEBUG_RO
#else
#define ALIGN_DEBUG_RO
#define ALIGN_DEBUG_RO_MIN(min)		. = ALIGN(min);
#endif

SECTIONS
{
	/*
@@ -59,6 +68,7 @@ SECTIONS
		_text = .;
		HEAD_TEXT
	}
	ALIGN_DEBUG_RO
	.text : {			/* Real text segment		*/
		_stext = .;		/* Text and read-only data	*/
			__exception_text_start = .;
@@ -75,19 +85,22 @@ SECTIONS
		*(.got)			/* Global offset table		*/
	}

	ALIGN_DEBUG_RO
	RO_DATA(PAGE_SIZE)
	EXCEPTION_TABLE(8)
	NOTES
	ALIGN_DEBUG_RO
	_etext = .;			/* End of text and rodata section */

	. = ALIGN(PAGE_SIZE);
	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
	__init_begin = .;

	INIT_TEXT_SECTION(8)
	.exit.text : {
		ARM_EXIT_KEEP(EXIT_TEXT)
	}
	. = ALIGN(16);

	ALIGN_DEBUG_RO_MIN(16)
	.init.data : {
		INIT_DATA
		INIT_SETUP(16)
+1 −0
Original line number Diff line number Diff line
@@ -331,6 +331,7 @@ static inline void poison_init_mem(void *s, size_t count)

void free_initmem(void)
{
	fixup_init();
	free_initmem_default(0);
}

+1 −0
Original line number Diff line number Diff line
extern void __init bootmem_init(void);
extern void __init arm64_swiotlb_init(void);
void fixup_init(void);
Loading