Skip to content

Commit a430643

Browse files
committed
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
2 parents a302824 + a2048e3 commit a430643

File tree

6 files changed

+36
-29
lines changed

6 files changed

+36
-29
lines changed

arch/arm/include/asm/thread_info.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
139139
#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
140140
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
141141
#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 */
147146

148147
#define TIF_NOHZ 12 /* in adaptive nohz mode */
149148
#define TIF_USING_IWMMXT 17
@@ -154,7 +153,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
154153
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
155154
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
156155
#define _TIF_UPROBE (1 << TIF_UPROBE)
157-
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
158156
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
159157
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
160158
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
@@ -168,9 +166,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
168166
/*
169167
* Change these and you break ASM code in entry-common.S
170168
*/
171-
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
172-
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
173-
_TIF_FSCHECK)
169+
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
170+
_TIF_NOTIFY_RESUME | _TIF_UPROBE)
174171

175172
#endif /* __KERNEL__ */
176173
#endif /* __ASM_ARM_THREAD_INFO_H */

arch/arm/include/asm/uaccess.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ static inline void set_fs(mm_segment_t fs)
7070
{
7171
current_thread_info()->addr_limit = fs;
7272
modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
73-
/* On user-mode return, check fs is correct */
74-
set_thread_flag(TIF_FSCHECK);
7573
}
7674

7775
#define segment_eq(a, b) ((a) == (b))

arch/arm/kernel/entry-common.S

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <asm/unistd.h>
1313
#include <asm/ftrace.h>
1414
#include <asm/unwind.h>
15+
#include <asm/memory.h>
1516
#ifdef CONFIG_AEABI
1617
#include <asm/unistd-oabi.h>
1718
#endif
@@ -48,12 +49,14 @@ ret_fast_syscall:
4849
UNWIND(.fnstart )
4950
UNWIND(.cantunwind )
5051
disable_irq_notrace @ disable interrupts
52+
ldr r2, [tsk, #TI_ADDR_LIMIT]
53+
cmp r2, #TASK_SIZE
54+
blne addr_limit_check_failed
5155
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
52-
tst r1, #_TIF_SYSCALL_WORK
53-
bne fast_work_pending
54-
tst r1, #_TIF_WORK_MASK
56+
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
5557
bne fast_work_pending
5658

59+
5760
/* perform architecture specific actions before user return */
5861
arch_ret_to_user r1, lr
5962

@@ -76,16 +79,16 @@ ret_fast_syscall:
7679
UNWIND(.cantunwind )
7780
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
7881
disable_irq_notrace @ disable interrupts
82+
ldr r2, [tsk, #TI_ADDR_LIMIT]
83+
cmp r2, #TASK_SIZE
84+
blne addr_limit_check_failed
7985
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
80-
tst r1, #_TIF_SYSCALL_WORK
81-
bne fast_work_pending
82-
tst r1, #_TIF_WORK_MASK
86+
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
8387
beq no_work_pending
8488
UNWIND(.fnend )
8589
ENDPROC(ret_fast_syscall)
8690

8791
/* Slower path - fall through to work_pending */
88-
fast_work_pending:
8992
#endif
9093

9194
tst r1, #_TIF_SYSCALL_WORK
@@ -111,6 +114,9 @@ ENTRY(ret_to_user)
111114
ret_slow_syscall:
112115
disable_irq_notrace @ disable interrupts
113116
ENTRY(ret_to_user_from_irq)
117+
ldr r2, [tsk, #TI_ADDR_LIMIT]
118+
cmp r2, #TASK_SIZE
119+
blne addr_limit_check_failed
114120
ldr r1, [tsk, #TI_FLAGS]
115121
tst r1, #_TIF_WORK_MASK
116122
bne slow_work_pending

arch/arm/kernel/signal.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
614614
* Update the trace code with the current status.
615615
*/
616616
trace_hardirqs_off();
617-
618-
/* Check valid user FS if needed */
619-
addr_limit_user_check();
620-
621617
do {
622618
if (likely(thread_flags & _TIF_NEED_RESCHED)) {
623619
schedule();
@@ -678,3 +674,9 @@ struct page *get_signal_page(void)
678674

679675
return page;
680676
}
677+
678+
/* Defer to generic check */
679+
asmlinkage void addr_limit_check_failed(void)
680+
{
681+
addr_limit_user_check();
682+
}

arch/arm64/kernel/signal.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,10 +751,10 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
751751
*/
752752
trace_hardirqs_off();
753753

754-
/* Check valid user FS if needed */
755-
addr_limit_user_check();
756-
757754
do {
755+
/* Check valid user FS if needed */
756+
addr_limit_user_check();
757+
758758
if (thread_flags & _TIF_NEED_RESCHED) {
759759
schedule();
760760
} else {

include/linux/syscalls.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,21 +221,25 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
221221
} \
222222
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
223223

224-
#ifdef TIF_FSCHECK
225224
/*
226225
* Called before coming back to user-mode. Returning to user-mode with an
227226
* address limit different than USER_DS can allow to overwrite kernel memory.
228227
*/
229228
static inline void addr_limit_user_check(void)
230229
{
231-
230+
#ifdef TIF_FSCHECK
232231
if (!test_thread_flag(TIF_FSCHECK))
233232
return;
233+
#endif
234234

235-
BUG_ON(!segment_eq(get_fs(), USER_DS));
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
236240
clear_thread_flag(TIF_FSCHECK);
237-
}
238241
#endif
242+
}
239243

240244
asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
241245
qid_t id, void __user *addr);

0 commit comments

Comments
 (0)