Revert "arm/syscalls: Check address limit on user-mode return"
This reverts commit 73ac5d6a2b
.
The work pending loop can call set_fs after addr_limit_user_check
removed the _TIF_FSCHECK flag. This may happen at anytime based on how
ARM handles alignment exceptions. It leads to an infinite loop condition.
After discussion, it has been agreed that the generic approach is not
tailored to the ARM architecture and any fix might not be complete. This
patch will be replaced by an architecture specific implementation. The
work flag approach will be kept for other architectures.
Reported-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Thomas Garnier <thgarnie@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Pratyush Anand <panand@redhat.com>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: Will Drewry <wad@chromium.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-api@vger.kernel.org
Cc: Yonghong Song <yhs@fb.com>
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1504798247-48833-3-git-send-email-keescook@chromium.org
This commit is contained in:
parent
bf29ed1567
commit
2404269bc4
|
@ -139,11 +139,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
||||||
#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
|
#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
|
||||||
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
||||||
#define TIF_UPROBE 3 /* breakpointed or singlestepping */
|
#define TIF_UPROBE 3 /* breakpointed or singlestepping */
|
||||||
#define TIF_FSCHECK 4 /* Check FS is USER_DS on return */
|
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
|
||||||
#define TIF_SYSCALL_TRACE 5 /* syscall trace active */
|
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||||
#define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */
|
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||||
#define TIF_SYSCALL_TRACEPOINT 7 /* syscall tracepoint instrumentation */
|
#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
|
||||||
#define TIF_SECCOMP 8 /* seccomp syscall filtering active */
|
|
||||||
|
|
||||||
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
||||||
#define TIF_USING_IWMMXT 17
|
#define TIF_USING_IWMMXT 17
|
||||||
|
@ -154,7 +153,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
||||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||||
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
||||||
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
|
|
||||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||||
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
||||||
|
@ -168,9 +166,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
||||||
/*
|
/*
|
||||||
* Change these and you break ASM code in entry-common.S
|
* Change these and you break ASM code in entry-common.S
|
||||||
*/
|
*/
|
||||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||||
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
_TIF_NOTIFY_RESUME | _TIF_UPROBE)
|
||||||
_TIF_FSCHECK)
|
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif /* __ASM_ARM_THREAD_INFO_H */
|
#endif /* __ASM_ARM_THREAD_INFO_H */
|
||||||
|
|
|
@ -70,8 +70,6 @@ static inline void set_fs(mm_segment_t fs)
|
||||||
{
|
{
|
||||||
current_thread_info()->addr_limit = fs;
|
current_thread_info()->addr_limit = fs;
|
||||||
modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
|
modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
|
||||||
/* On user-mode return, check fs is correct */
|
|
||||||
set_thread_flag(TIF_FSCHECK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define segment_eq(a, b) ((a) == (b))
|
#define segment_eq(a, b) ((a) == (b))
|
||||||
|
|
|
@ -49,9 +49,7 @@ ret_fast_syscall:
|
||||||
UNWIND(.cantunwind )
|
UNWIND(.cantunwind )
|
||||||
disable_irq_notrace @ disable interrupts
|
disable_irq_notrace @ disable interrupts
|
||||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||||
tst r1, #_TIF_SYSCALL_WORK
|
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||||
bne fast_work_pending
|
|
||||||
tst r1, #_TIF_WORK_MASK
|
|
||||||
bne fast_work_pending
|
bne fast_work_pending
|
||||||
|
|
||||||
/* perform architecture specific actions before user return */
|
/* perform architecture specific actions before user return */
|
||||||
|
@ -77,15 +75,12 @@ ret_fast_syscall:
|
||||||
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
|
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
|
||||||
disable_irq_notrace @ disable interrupts
|
disable_irq_notrace @ disable interrupts
|
||||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||||
tst r1, #_TIF_SYSCALL_WORK
|
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||||
bne fast_work_pending
|
|
||||||
tst r1, #_TIF_WORK_MASK
|
|
||||||
beq no_work_pending
|
beq no_work_pending
|
||||||
UNWIND(.fnend )
|
UNWIND(.fnend )
|
||||||
ENDPROC(ret_fast_syscall)
|
ENDPROC(ret_fast_syscall)
|
||||||
|
|
||||||
/* Slower path - fall through to work_pending */
|
/* Slower path - fall through to work_pending */
|
||||||
fast_work_pending:
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tst r1, #_TIF_SYSCALL_WORK
|
tst r1, #_TIF_SYSCALL_WORK
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/tracehook.h>
|
#include <linux/tracehook.h>
|
||||||
#include <linux/uprobes.h>
|
#include <linux/uprobes.h>
|
||||||
#include <linux/syscalls.h>
|
|
||||||
|
|
||||||
#include <asm/elf.h>
|
#include <asm/elf.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
@ -614,10 +613,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
|
||||||
* Update the trace code with the current status.
|
* Update the trace code with the current status.
|
||||||
*/
|
*/
|
||||||
trace_hardirqs_off();
|
trace_hardirqs_off();
|
||||||
|
|
||||||
/* Check valid user FS if needed */
|
|
||||||
addr_limit_user_check();
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (likely(thread_flags & _TIF_NEED_RESCHED)) {
|
if (likely(thread_flags & _TIF_NEED_RESCHED)) {
|
||||||
schedule();
|
schedule();
|
||||||
|
|
Loading…
Reference in New Issue