|
|
Message-ID: <CAKv+Gu_-xeux7Q5Sm6HSiV4TvjcKy8C9_tnAGkeReT9-SMEdPg@mail.gmail.com>
Date: Wed, 7 Nov 2018 08:51:27 +0100
From: Ard Biesheuvel <ard.biesheuvel@...aro.org>
To: Will Deacon <will.deacon@....com>
Cc: linux-arm-kernel <linux-arm-kernel@...ts.infradead.org>, Kees Cook <keescook@...omium.org>,
Kernel Hardening <kernel-hardening@...ts.openwall.com>, Laura Abbott <labbott@...hat.com>,
Jann Horn <jannh@...gle.com>, Mark Rutland <mark.rutland@....com>,
James Morse <james.morse@....com>, Catalin Marinas <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 6 November 2018 at 22:54, Will Deacon <will.deacon@....com> wrote:
> 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!
>
Thanks
>> 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?
>
I had managed to convince myself that this is problematic due to the
fact that rodata= is parsed twice, with early_param() in the arm64
code and with __setup() in generic code, and both use strtobool()
which will return an error on 'full'.
However, that does not actually appear to matter, although it is
slightly nasty to rely on that.
>> + 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".
>
Will fix
>> + 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
>
Will fix'
>> + 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.
>
I can easily infer it from set_mask == __pgprot(PTE_RDONLY) ||
clear_mask == __pgprot(PTE_RDONLY) so that should be doable yes.
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.