aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-03-12 17:52:59 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-13 01:56:29 -0500
commitc33d4568aca9028a22857f94f5e0850012b6444b (patch)
tree7a33d918e4d35b0444820595cb2aaaae1f1f5bfa /arch
parent31fe4d331729e9687db84521c3ceb8e43390efcf (diff)
[PATCH] x86-64: Fix up handling of non canonical user RIPs
EM64T CPUs have somewhat weird error reporting for non canonical RIPs in SYSRET. We can't handle any exceptions there because the exception handler would end up running on the user stack which is unsafe. To avoid problems any code that might end up with a user touched pt_regs should return using int_ret_from_syscall. int_ret_from_syscall ends up using IRET, which allows safe exceptions. Cc: Ernie Petrides <petrides@redhat.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/kernel/entry.S29
1 files changed, 11 insertions, 18 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 7c10e9009d61..22cb6ee074b9 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -178,6 +178,12 @@ rff_trace:
178 * Interrupts are off on entry. 178 * Interrupts are off on entry.
179 * Only called from user space. 179 * Only called from user space.
180 * 180 *
181 * EM64T CPUs have somewhat weird error reporting for non canonical RIPs in SYSRET.
182 * We can't handle any exceptions there because the exception handler would
183 * end up running on the user stack which is unsafe. To avoid problems
184 * any code that might end up with a user touched pt_regs should return
185 * using int_ret_from_syscall.
186 *
181 * XXX if we had a free scratch register we could save the RSP into the stack frame 187 * XXX if we had a free scratch register we could save the RSP into the stack frame
182 * and report it properly in ps. Unfortunately we haven't. 188 * and report it properly in ps. Unfortunately we haven't.
183 */ 189 */
@@ -254,7 +260,9 @@ sysret_signal:
254 xorl %esi,%esi # oldset -> arg2 260 xorl %esi,%esi # oldset -> arg2
255 call ptregscall_common 261 call ptregscall_common
2561: movl $_TIF_NEED_RESCHED,%edi 2621: movl $_TIF_NEED_RESCHED,%edi
257 jmp sysret_check 263 /* Stack frame might have been changed. The IRET path does
264 some additional checks to handle this */
265 jmp int_with_check
258 266
259badsys: 267badsys:
260 movq $-ENOSYS,RAX-ARGOFFSET(%rsp) 268 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -280,7 +288,8 @@ tracesys:
280 call syscall_trace_leave 288 call syscall_trace_leave
281 RESTORE_TOP_OF_STACK %rbx 289 RESTORE_TOP_OF_STACK %rbx
282 RESTORE_REST 290 RESTORE_REST
283 jmp ret_from_sys_call 291 /* Stack frame might have been changed. Use the more careful IRET path */
292 jmp int_ret_from_sys_call
284 CFI_ENDPROC 293 CFI_ENDPROC
285 294
286/* 295/*
@@ -408,25 +417,9 @@ ENTRY(stub_execve)
408 CFI_ADJUST_CFA_OFFSET -8 417 CFI_ADJUST_CFA_OFFSET -8
409 CFI_REGISTER rip, r11 418 CFI_REGISTER rip, r11
410 SAVE_REST 419 SAVE_REST
411 movq %r11, %r15
412 CFI_REGISTER rip, r15
413 FIXUP_TOP_OF_STACK %r11 420 FIXUP_TOP_OF_STACK %r11
414 call sys_execve 421 call sys_execve
415 GET_THREAD_INFO(%rcx)
416 bt $TIF_IA32,threadinfo_flags(%rcx)
417 CFI_REMEMBER_STATE
418 jc exec_32bit
419 RESTORE_TOP_OF_STACK %r11 422 RESTORE_TOP_OF_STACK %r11
420 movq %r15, %r11
421 CFI_REGISTER rip, r11
422 RESTORE_REST
423 pushq %r11
424 CFI_ADJUST_CFA_OFFSET 8
425 CFI_REL_OFFSET rip, 0
426 ret
427
428exec_32bit:
429 CFI_RESTORE_STATE
430 movq %rax,RAX(%rsp) 423 movq %rax,RAX(%rsp)
431 RESTORE_REST 424 RESTORE_REST
432 jmp int_ret_from_sys_call 425 jmp int_ret_from_sys_call