ARM: mm: allow text and rodata sections to be read-only
This introduces CONFIG_DEBUG_RODATA, making kernel text and rodata read-only. Additionally, this splits rodata from text so that rodata can also be NX, which may lead to wasted memory when aligning to SECTION_SIZE. The read-only areas are made writable during ftrace updates and kexec. Signed-off-by: Kees Cook <keescook@chromium.org> Tested-by: Laura Abbott <lauraa@codeaurora.org> Acked-by: Nicolas Pitre <nico@linaro.org>
This commit is contained in:
@@ -622,9 +622,10 @@ struct section_perm {
|
||||
unsigned long end;
|
||||
pmdval_t mask;
|
||||
pmdval_t prot;
|
||||
pmdval_t clear;
|
||||
};
|
||||
|
||||
struct section_perm nx_perms[] = {
|
||||
static struct section_perm nx_perms[] = {
|
||||
/* Make pages tables, etc before _stext RW (set NX). */
|
||||
{
|
||||
.start = PAGE_OFFSET,
|
||||
@@ -639,8 +640,35 @@ struct section_perm nx_perms[] = {
|
||||
.mask = ~PMD_SECT_XN,
|
||||
.prot = PMD_SECT_XN,
|
||||
},
|
||||
#ifdef CONFIG_DEBUG_RODATA
|
||||
/* Make rodata NX (set RO in ro_perms below). */
|
||||
{
|
||||
.start = (unsigned long)__start_rodata,
|
||||
.end = (unsigned long)__init_begin,
|
||||
.mask = ~PMD_SECT_XN,
|
||||
.prot = PMD_SECT_XN,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_RODATA
|
||||
static struct section_perm ro_perms[] = {
|
||||
/* Make kernel code and rodata RX (set RO). */
|
||||
{
|
||||
.start = (unsigned long)_stext,
|
||||
.end = (unsigned long)__init_begin,
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
.mask = ~PMD_SECT_RDONLY,
|
||||
.prot = PMD_SECT_RDONLY,
|
||||
#else
|
||||
.mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE),
|
||||
.prot = PMD_SECT_APX | PMD_SECT_AP_WRITE,
|
||||
.clear = PMD_SECT_AP_WRITE,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Updates section permissions only for the current mm (sections are
|
||||
* copied into each mm). During startup, this is the init_mm. Is only
|
||||
@@ -704,6 +732,24 @@ static inline void fix_kernmem_perms(void)
|
||||
{
|
||||
set_section_perms(nx_perms, prot);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_RODATA
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
set_section_perms(ro_perms, prot);
|
||||
}
|
||||
|
||||
void set_kernel_text_rw(void)
|
||||
{
|
||||
set_section_perms(ro_perms, clear);
|
||||
}
|
||||
|
||||
void set_kernel_text_ro(void)
|
||||
{
|
||||
set_section_perms(ro_perms, prot);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_RODATA */
|
||||
|
||||
#else
|
||||
static inline void fix_kernmem_perms(void) { }
|
||||
#endif /* CONFIG_ARM_KERNMEM_PERMS */
|
||||
|
Reference in New Issue
Block a user