Commit 979046bd authored by Yury Norov's avatar Yury Norov Committed by Zheng Zengkai
Browse files

arm64: fix current_thread_info()->addr_limit setup

hulk inclusion
category: bugfix
bugzilla: 51408
CVE: NA

-------------------------------------------------------------------------

At elf loading in flush_old_exec() in fs/exec.c, generic code sets
current_thread_info()->addr_limit to one that corresponds aarch64 value,
and ignores compat mode there as corresponding status setup happens
later on in load_elf_binary() by SET_PERSONALITY() macro. As result,
compat task has wrong addr_limit, and it may cause various bugs.

This patch fixes it. It also fixes USER_DS macro to return different
values depending on compat at runtime.

It was discovered during ilp32 development. See details here:
https://lkml.org/lkml/2016/5/11/975



v2:
flush tpidrro_el0 unconditionally in tls_thread_flush() as if exec() is
called by aarch64 task, is_compat_task() fails even if new thread is
aarch32.

Signed-off-by: default avatarYury Norov <ynorov@caviumnetworks>
Signed-off-by: default avatarZhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: default avatarHanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: default avatarHanjun Guo <guohanjun@huawei.com>
Signed-off-by: default avatarzhangyi (F) <yi.zhang@huawei.com>

 Conflicts:
	arch/arm64/include/asm/uaccess.h
	arch/arm64/kernel/process.c
	fs/exec.c
[wang: expand macro USER_DS in entry.S according to commit: ee20d8797f06
("arm64: Make USER_DS an inclusive limit")]
Signed-off-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: default avatarJiahao Chen <chenjiahao16@huawei.com>
Reviewed-by: default avatarChang Liao <liaochang1@huawei.com>
Signed-off-by: default avatarChen Jun <chenjun102@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent f1659e5b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9,7 +9,8 @@
#define __ASM_PROCESSOR_H

#define KERNEL_DS		UL(-1)
#define USER_DS			((UL(1) << VA_BITS) - 1)
#define USER_DS			(is_compat_task() ? \
				(UL(0x100000000) - 1) : (TASK_SIZE - 1))

/*
 * On arm64 systems, unaligned accesses by the CPU are cheap, and so there is
+2 −1
Original line number Diff line number Diff line
@@ -219,7 +219,8 @@ alternative_else_nop_endif
	/* Save the task's original addr_limit and set USER_DS */
	ldr	x20, [tsk, #TSK_TI_ADDR_LIMIT]
	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
	mov	x20, #USER_DS
	/* expand USER_DS here using its value while is_compat_task() is false */
	mov	x20, #((UL(1) << VA_BITS) - 1)
	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
	/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
	.endif /* \el == 0 */
+7 −0
Original line number Diff line number Diff line
@@ -625,6 +625,13 @@ unsigned long arch_align_stack(unsigned long sp)
 */
void arch_setup_new_exec(void)
{
	/*
	 * set the address limit for the new executable.
	 * Here we reset the addr_limit only for the scenario
	 * where is_compat_task() is set in AARCH64 kernel.
	 */
	set_fs(USER_DS);

	current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;

	ptrauth_thread_init_user(current);