|
Message-ID: <20181106215450.GB31487@brain-police> Date: Tue, 6 Nov 2018 21:54:58 +0000 From: Will Deacon <will.deacon@....com> To: Ard Biesheuvel <ard.biesheuvel@...aro.org> Cc: linux-arm-kernel@...ts.infradead.org, keescook@...omium.org, kernel-hardening@...ts.openwall.com, labbott@...hat.com, jannh@...gle.com, mark.rutland@....com, james.morse@....com, catalin.marinas@....com Subject: Re: [PATCH v3 2/2] arm64: mm: apply r/o permissions of VM areas to its linear alias as well On Tue, Nov 06, 2018 at 10:44:04PM +0100, Ard Biesheuvel wrote: > On arm64, we use block mappings and contiguous hints to map the linear > region, to minimize the TLB footprint. However, this means that the > entire region is mapped using read/write permissions, and so the linear > aliases of pages belonging to read-only mappings (executable or otherwise) > in the vmalloc region could potentially be abused to modify things like > module code, bpf JIT code or read-only data. > > So let's fix this, by extending the set_memory_ro/rw routines to take > the linear alias into account. The consequence of enabling this is > that we can no longer use block mappings or contiguous hints, so in > cases where the TLB footprint of the linear region is a bottleneck, > performance may be affected. > > Therefore, allow this feature to be runtime disabled, by setting > rola=off on the kernel command line. Also, allow the default value > to be set via a Kconfig option. > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@...aro.org> > --- > arch/arm64/Kconfig | 14 +++++++++ > arch/arm64/include/asm/mmu_context.h | 2 ++ > arch/arm64/mm/mmu.c | 2 +- > arch/arm64/mm/pageattr.c | 30 ++++++++++++++++---- > 4 files changed, 42 insertions(+), 6 deletions(-) Nice -- this is looking pretty good! > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > index 787d7850e064..d000c379b670 100644 > --- a/arch/arm64/Kconfig > +++ b/arch/arm64/Kconfig > @@ -958,6 +958,20 @@ config ARM64_SSBD > > If unsure, say Y. > > +config ROLA_DEFAULT_ENABLED Any reason not to piggyback on rodata as you suggested before? > + bool "Apply read-only permissions of VM areas also to its linear alias" This reads strangely as it mixes plural ("VM areas") with singular "its linear alias". > + default y > + help > + Apply read-only attributes of VM areas to the linear alias of > + the backing pages as well. This prevents code or read/only data typo: read/only > + from being modified (inadvertently or intentionally) via another > + mapping of the same memory page. This can be turned off at runtime > + by passing rola=off (and turned on with rola=on if this option is > + set to 'n') > + > + This requires the linear region to be mapped down to pages, > + which may adversely affect performance in some cases. > menuconfig ARMV8_DEPRECATED > bool "Emulate deprecated/obsolete ARMv8 instructions" > depends on COMPAT > diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h > index 1e58bf58c22b..df39a07fe5f0 100644 > --- a/arch/arm64/include/asm/mmu_context.h > +++ b/arch/arm64/include/asm/mmu_context.h > @@ -35,6 +35,8 @@ > #include <asm/sysreg.h> > #include <asm/tlbflush.h> > > +extern bool rola_enabled; > + > static inline void contextidr_thread_switch(struct task_struct *next) > { > if (!IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR)) > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c > index d1d6601b385d..79fd3bf102fa 100644 > --- a/arch/arm64/mm/mmu.c > +++ b/arch/arm64/mm/mmu.c > @@ -451,7 +451,7 @@ static void __init map_mem(pgd_t *pgdp) > struct memblock_region *reg; > int flags = 0; > > - if (debug_pagealloc_enabled()) > + if (rola_enabled || debug_pagealloc_enabled()) > flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; > > /* > diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c > index f8cf5bc1d1f8..1dddb69e6f1c 100644 > --- a/arch/arm64/mm/pageattr.c > +++ b/arch/arm64/mm/pageattr.c > @@ -25,6 +25,13 @@ struct page_change_data { > pgprot_t clear_mask; > }; > > +bool rola_enabled __ro_after_init = IS_ENABLED(CONFIG_ROLA_DEFAULT_ENABLED); > +static int __init parse_rola(char *arg) > +{ > + return strtobool(arg, &rola_enabled); > +} > +early_param("rola", parse_rola); > + > static int change_page_range(pte_t *ptep, pgtable_t token, unsigned long addr, > void *data) > { > @@ -58,12 +65,14 @@ static int __change_memory_common(unsigned long start, unsigned long size, > } > > static int change_memory_common(unsigned long addr, int numpages, > - pgprot_t set_mask, pgprot_t clear_mask) > + pgprot_t set_mask, pgprot_t clear_mask, > + bool remap_alias) Can we drop the remap_alias parameter an infer the behaviour based on whether we're messing with PTE_RDONLY? I find APIs with bool parameters really hard to read at the callsite. Will
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.