arm64: Introduce uaccess_{disable,enable} functionality based on TTBR0_EL1
This patch adds the uaccess macros/functions to disable access to user space by setting TTBR0_EL1 to a reserved zeroed page. Since the value written to TTBR0_EL1 must be a physical address, for simplicity this patch introduces a reserved_ttbr0 page at a constant offset from swapper_pg_dir. The uaccess_disable code uses the ttbr1_el1 value adjusted by the reserved_ttbr0 offset. Enabling access to user is done by restoring TTBR0_EL1 with the value from the struct thread_info ttbr0 variable. Interrupts must be disabled during the uaccess_ttbr0_enable code to ensure the atomicity of the thread_info.ttbr0 read and TTBR0_EL1 write. This patch also moves the get_thread_info asm macro from entry.S to assembler.h for reuse in the uaccess_ttbr0_* macros. Cc: Will Deacon <will.deacon@arm.com> Cc: James Morse <james.morse@arm.com> Cc: Kees Cook <keescook@chromium.org> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
@@ -39,6 +39,9 @@ int main(void)
|
||||
DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
|
||||
DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count));
|
||||
DEFINE(TSK_TI_ADDR_LIMIT, offsetof(struct task_struct, thread_info.addr_limit));
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0));
|
||||
#endif
|
||||
DEFINE(TSK_STACK, offsetof(struct task_struct, stack));
|
||||
BLANK();
|
||||
DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context));
|
||||
|
@@ -47,6 +47,7 @@ unsigned int compat_elf_hwcap2 __read_mostly;
|
||||
#endif
|
||||
|
||||
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
|
||||
EXPORT_SYMBOL(cpu_hwcaps);
|
||||
|
||||
DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS);
|
||||
EXPORT_SYMBOL(cpu_hwcap_keys);
|
||||
|
@@ -183,10 +183,6 @@ alternative_else_nop_endif
|
||||
eret // return to kernel
|
||||
.endm
|
||||
|
||||
.macro get_thread_info, rd
|
||||
mrs \rd, sp_el0
|
||||
.endm
|
||||
|
||||
.macro irq_stack_entry
|
||||
mov x19, sp // preserve the original sp
|
||||
|
||||
|
@@ -326,14 +326,14 @@ __create_page_tables:
|
||||
* dirty cache lines being evicted.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
bl __inval_cache_range
|
||||
|
||||
/*
|
||||
* Clear the idmap and swapper page tables.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
1: stp xzr, xzr, [x0], #16
|
||||
stp xzr, xzr, [x0], #16
|
||||
stp xzr, xzr, [x0], #16
|
||||
@@ -412,7 +412,7 @@ __create_page_tables:
|
||||
* tables again to remove any speculatively loaded cache lines.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
dmb sy
|
||||
bl __inval_cache_range
|
||||
|
||||
|
@@ -216,6 +216,11 @@ SECTIONS
|
||||
swapper_pg_dir = .;
|
||||
. += SWAPPER_DIR_SIZE;
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
reserved_ttbr0 = .;
|
||||
. += RESERVED_TTBR0_SIZE;
|
||||
#endif
|
||||
|
||||
_end = .;
|
||||
|
||||
STABS_DEBUG
|
||||
|
Reference in New Issue
Block a user