Skip to content

Commit

Permalink
arm64: add better page protections to arm64
Browse files Browse the repository at this point in the history
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.

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Kees Cook <keescook@chromium.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Laura Abbott authored and Catalin Marinas committed Jan 22, 2015
1 parent 2f896d5 commit da14170
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 26 deletions.
23 changes: 23 additions & 0 deletions arch/arm64/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,27 @@ config DEBUG_SET_MODULE_RONX
against certain classes of kernel exploits.
If in doubt, 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 changes: 5 additions & 0 deletions arch/arm64/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,9 @@ 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

#endif
17 changes: 15 additions & 2 deletions arch/arm64/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
#include <asm/pgtable.h>

#include "image.h"

Expand Down Expand Up @@ -49,6 +50,14 @@ PECOFF_FILE_ALIGNMENT = 0x200;
#define PECOFF_EDATA_PADDING
#endif

#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
{
/*
Expand All @@ -71,6 +80,7 @@ SECTIONS
_text = .;
HEAD_TEXT
}
ALIGN_DEBUG_RO
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
__exception_text_start = .;
Expand All @@ -87,19 +97,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)
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ void __init mem_init(void)

void free_initmem(void)
{
fixup_init();
free_initmem_default(0);
free_alternatives_memory();
}
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/mm/mm.h
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
extern void __init bootmem_init(void);

void fixup_init(void);
Loading

0 comments on commit da14170

Please sign in to comment.