Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull address-limit checking fixes from Ingo Molnar: "This fixes a number of bugs in the address-limit (USER_DS) checks that got introduced in the merge window, (mostly) affecting the ARM and ARM64 platforms" * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: arm64/syscalls: Move address limit check in loop arm/syscalls: Optimize address limit check Revert "arm/syscalls: Check address limit on user-mode return" syscalls: Use CHECK_DATA_CORRUPTION for addr_limit_user_check
This commit is contained in:
commit
a4306434b7
|
@ -139,11 +139,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
|||
#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
|
||||
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
||||
#define TIF_UPROBE 3 /* breakpointed or singlestepping */
|
||||
#define TIF_FSCHECK 4 /* Check FS is USER_DS on return */
|
||||
#define TIF_SYSCALL_TRACE 5 /* syscall trace active */
|
||||
#define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 7 /* syscall tracepoint instrumentation */
|
||||
#define TIF_SECCOMP 8 /* seccomp syscall filtering active */
|
||||
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
|
||||
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||
#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
|
||||
|
||||
#define TIF_NOHZ 12 /* in adaptive nohz mode */
|
||||
#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_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
||||
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
||||
|
@ -169,8 +167,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
|||
* Change these and you break ASM code in entry-common.S
|
||||
*/
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
||||
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
||||
_TIF_FSCHECK)
|
||||
_TIF_NOTIFY_RESUME | _TIF_UPROBE)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#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;
|
||||
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))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <asm/unistd.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/unwind.h>
|
||||
#include <asm/memory.h>
|
||||
#ifdef CONFIG_AEABI
|
||||
#include <asm/unistd-oabi.h>
|
||||
#endif
|
||||
|
@ -48,12 +49,14 @@ ret_fast_syscall:
|
|||
UNWIND(.fnstart )
|
||||
UNWIND(.cantunwind )
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r2, [tsk, #TI_ADDR_LIMIT]
|
||||
cmp r2, #TASK_SIZE
|
||||
blne addr_limit_check_failed
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
tst r1, #_TIF_SYSCALL_WORK
|
||||
bne fast_work_pending
|
||||
tst r1, #_TIF_WORK_MASK
|
||||
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
bne fast_work_pending
|
||||
|
||||
|
||||
/* perform architecture specific actions before user return */
|
||||
arch_ret_to_user r1, lr
|
||||
|
||||
|
@ -76,16 +79,16 @@ ret_fast_syscall:
|
|||
UNWIND(.cantunwind )
|
||||
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ldr r2, [tsk, #TI_ADDR_LIMIT]
|
||||
cmp r2, #TASK_SIZE
|
||||
blne addr_limit_check_failed
|
||||
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||
tst r1, #_TIF_SYSCALL_WORK
|
||||
bne fast_work_pending
|
||||
tst r1, #_TIF_WORK_MASK
|
||||
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
|
||||
beq no_work_pending
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(ret_fast_syscall)
|
||||
|
||||
/* Slower path - fall through to work_pending */
|
||||
fast_work_pending:
|
||||
#endif
|
||||
|
||||
tst r1, #_TIF_SYSCALL_WORK
|
||||
|
@ -111,6 +114,9 @@ ENTRY(ret_to_user)
|
|||
ret_slow_syscall:
|
||||
disable_irq_notrace @ disable interrupts
|
||||
ENTRY(ret_to_user_from_irq)
|
||||
ldr r2, [tsk, #TI_ADDR_LIMIT]
|
||||
cmp r2, #TASK_SIZE
|
||||
blne addr_limit_check_failed
|
||||
ldr r1, [tsk, #TI_FLAGS]
|
||||
tst r1, #_TIF_WORK_MASK
|
||||
bne slow_work_pending
|
||||
|
|
|
@ -614,10 +614,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
|
|||
* Update the trace code with the current status.
|
||||
*/
|
||||
trace_hardirqs_off();
|
||||
|
||||
/* Check valid user FS if needed */
|
||||
addr_limit_user_check();
|
||||
|
||||
do {
|
||||
if (likely(thread_flags & _TIF_NEED_RESCHED)) {
|
||||
schedule();
|
||||
|
@ -678,3 +674,9 @@ struct page *get_signal_page(void)
|
|||
|
||||
return page;
|
||||
}
|
||||
|
||||
/* Defer to generic check */
|
||||
asmlinkage void addr_limit_check_failed(void)
|
||||
{
|
||||
addr_limit_user_check();
|
||||
}
|
||||
|
|
|
@ -751,10 +751,10 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
|
|||
*/
|
||||
trace_hardirqs_off();
|
||||
|
||||
do {
|
||||
/* Check valid user FS if needed */
|
||||
addr_limit_user_check();
|
||||
|
||||
do {
|
||||
if (thread_flags & _TIF_NEED_RESCHED) {
|
||||
schedule();
|
||||
} else {
|
||||
|
|
|
@ -221,22 +221,26 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
|
|||
} \
|
||||
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
|
||||
|
||||
#ifdef TIF_FSCHECK
|
||||
/*
|
||||
* Called before coming back to user-mode. Returning to user-mode with an
|
||||
* address limit different than USER_DS can allow to overwrite kernel memory.
|
||||
*/
|
||||
static inline void addr_limit_user_check(void)
|
||||
{
|
||||
|
||||
#ifdef TIF_FSCHECK
|
||||
if (!test_thread_flag(TIF_FSCHECK))
|
||||
return;
|
||||
|
||||
BUG_ON(!segment_eq(get_fs(), USER_DS));
|
||||
clear_thread_flag(TIF_FSCHECK);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS),
|
||||
"Invalid address limit on user-mode return"))
|
||||
force_sig(SIGKILL, current);
|
||||
|
||||
#ifdef TIF_FSCHECK
|
||||
clear_thread_flag(TIF_FSCHECK);
|
||||
#endif
|
||||
}
|
||||
|
||||
asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
|
||||
qid_t id, void __user *addr);
|
||||
asmlinkage long sys_time(time_t __user *tloc);
|
||||
|
|
Loading…
Reference in New Issue