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

Changed files
+38 -31
arch
arm
arm64
kernel
include
linux
+6 -9
arch/arm/include/asm/thread_info.h
··· 139 139 #define TIF_NEED_RESCHED 1 /* rescheduling necessary */ 140 140 #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ 141 141 #define TIF_UPROBE 3 /* breakpointed or singlestepping */ 142 - #define TIF_FSCHECK 4 /* Check FS is USER_DS on return */ 143 - #define TIF_SYSCALL_TRACE 5 /* syscall trace active */ 144 - #define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */ 145 - #define TIF_SYSCALL_TRACEPOINT 7 /* syscall tracepoint instrumentation */ 146 - #define TIF_SECCOMP 8 /* seccomp syscall filtering active */ 142 + #define TIF_SYSCALL_TRACE 4 /* syscall trace active */ 143 + #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ 144 + #define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */ 145 + #define TIF_SECCOMP 7 /* seccomp syscall filtering active */ 147 146 148 147 #define TIF_NOHZ 12 /* in adaptive nohz mode */ 149 148 #define TIF_USING_IWMMXT 17 ··· 153 154 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) 154 155 #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) 155 156 #define _TIF_UPROBE (1 << TIF_UPROBE) 156 - #define _TIF_FSCHECK (1 << TIF_FSCHECK) 157 157 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 158 158 #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) 159 159 #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) ··· 166 168 /* 167 169 * Change these and you break ASM code in entry-common.S 168 170 */ 169 - #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ 170 - _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ 171 - _TIF_FSCHECK) 171 + #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ 172 + _TIF_NOTIFY_RESUME | _TIF_UPROBE) 172 173 173 174 #endif /* __KERNEL__ */ 174 175 #endif /* __ASM_ARM_THREAD_INFO_H */
-2
arch/arm/include/asm/uaccess.h
··· 70 70 { 71 71 current_thread_info()->addr_limit = fs; 72 72 modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); 73 - /* On user-mode return, check fs is correct */ 74 - set_thread_flag(TIF_FSCHECK); 75 73 } 76 74 77 75 #define segment_eq(a, b) ((a) == (b))
+13 -7
arch/arm/kernel/entry-common.S
··· 12 12 #include <asm/unistd.h> 13 13 #include <asm/ftrace.h> 14 14 #include <asm/unwind.h> 15 + #include <asm/memory.h> 15 16 #ifdef CONFIG_AEABI 16 17 #include <asm/unistd-oabi.h> 17 18 #endif ··· 49 48 UNWIND(.fnstart ) 50 49 UNWIND(.cantunwind ) 51 50 disable_irq_notrace @ disable interrupts 51 + ldr r2, [tsk, #TI_ADDR_LIMIT] 52 + cmp r2, #TASK_SIZE 53 + blne addr_limit_check_failed 52 54 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 53 - tst r1, #_TIF_SYSCALL_WORK 55 + tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK 54 56 bne fast_work_pending 55 - tst r1, #_TIF_WORK_MASK 56 - bne fast_work_pending 57 + 57 58 58 59 /* perform architecture specific actions before user return */ 59 60 arch_ret_to_user r1, lr ··· 79 76 UNWIND(.cantunwind ) 80 77 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 81 78 disable_irq_notrace @ disable interrupts 79 + ldr r2, [tsk, #TI_ADDR_LIMIT] 80 + cmp r2, #TASK_SIZE 81 + blne addr_limit_check_failed 82 82 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 83 - tst r1, #_TIF_SYSCALL_WORK 84 - bne fast_work_pending 85 - tst r1, #_TIF_WORK_MASK 83 + tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK 86 84 beq no_work_pending 87 85 UNWIND(.fnend ) 88 86 ENDPROC(ret_fast_syscall) 89 87 90 88 /* Slower path - fall through to work_pending */ 91 - fast_work_pending: 92 89 #endif 93 90 94 91 tst r1, #_TIF_SYSCALL_WORK ··· 114 111 ret_slow_syscall: 115 112 disable_irq_notrace @ disable interrupts 116 113 ENTRY(ret_to_user_from_irq) 114 + ldr r2, [tsk, #TI_ADDR_LIMIT] 115 + cmp r2, #TASK_SIZE 116 + blne addr_limit_check_failed 117 117 ldr r1, [tsk, #TI_FLAGS] 118 118 tst r1, #_TIF_WORK_MASK 119 119 bne slow_work_pending
+6 -4
arch/arm/kernel/signal.c
··· 614 614 * Update the trace code with the current status. 615 615 */ 616 616 trace_hardirqs_off(); 617 - 618 - /* Check valid user FS if needed */ 619 - addr_limit_user_check(); 620 - 621 617 do { 622 618 if (likely(thread_flags & _TIF_NEED_RESCHED)) { 623 619 schedule(); ··· 673 677 flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); 674 678 675 679 return page; 680 + } 681 + 682 + /* Defer to generic check */ 683 + asmlinkage void addr_limit_check_failed(void) 684 + { 685 + addr_limit_user_check(); 676 686 }
+3 -3
arch/arm64/kernel/signal.c
··· 751 751 */ 752 752 trace_hardirqs_off(); 753 753 754 - /* Check valid user FS if needed */ 755 - addr_limit_user_check(); 756 - 757 754 do { 755 + /* Check valid user FS if needed */ 756 + addr_limit_user_check(); 757 + 758 758 if (thread_flags & _TIF_NEED_RESCHED) { 759 759 schedule(); 760 760 } else {
+10 -6
include/linux/syscalls.h
··· 221 221 } \ 222 222 static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 223 223 224 - #ifdef TIF_FSCHECK 225 224 /* 226 225 * Called before coming back to user-mode. Returning to user-mode with an 227 226 * address limit different than USER_DS can allow to overwrite kernel memory. 228 227 */ 229 228 static inline void addr_limit_user_check(void) 230 229 { 231 - 230 + #ifdef TIF_FSCHECK 232 231 if (!test_thread_flag(TIF_FSCHECK)) 233 232 return; 234 - 235 - BUG_ON(!segment_eq(get_fs(), USER_DS)); 236 - clear_thread_flag(TIF_FSCHECK); 237 - } 238 233 #endif 234 + 235 + if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS), 236 + "Invalid address limit on user-mode return")) 237 + force_sig(SIGKILL, current); 238 + 239 + #ifdef TIF_FSCHECK 240 + clear_thread_flag(TIF_FSCHECK); 241 + #endif 242 + } 239 243 240 244 asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special, 241 245 qid_t id, void __user *addr);