Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Andi Kleen and committed by
Linus Torvalds
c33d4568 31fe4d33

+11 -18
+11 -18
arch/x86_64/kernel/entry.S
··· 178 178 * Interrupts are off on entry. 179 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 187 * XXX if we had a free scratch register we could save the RSP into the stack frame 182 188 * and report it properly in ps. Unfortunately we haven't. 183 189 */ ··· 260 254 xorl %esi,%esi # oldset -> arg2 261 255 call ptregscall_common 262 256 1: movl $_TIF_NEED_RESCHED,%edi 263 - jmp sysret_check 257 + /* Stack frame might have been changed. The IRET path does 258 + some additional checks to handle this */ 259 + jmp int_with_check 264 260 265 261 badsys: 266 262 movq $-ENOSYS,RAX-ARGOFFSET(%rsp) ··· 288 280 call syscall_trace_leave 289 281 RESTORE_TOP_OF_STACK %rbx 290 282 RESTORE_REST 291 - jmp ret_from_sys_call 283 + /* Stack frame might have been changed. Use the more careful IRET path */ 284 + jmp int_ret_from_sys_call 292 285 CFI_ENDPROC 293 286 294 287 /* ··· 417 408 CFI_ADJUST_CFA_OFFSET -8 418 409 CFI_REGISTER rip, r11 419 410 SAVE_REST 420 - movq %r11, %r15 421 - CFI_REGISTER rip, r15 422 411 FIXUP_TOP_OF_STACK %r11 423 412 call sys_execve 424 - GET_THREAD_INFO(%rcx) 425 - bt $TIF_IA32,threadinfo_flags(%rcx) 426 - CFI_REMEMBER_STATE 427 - jc exec_32bit 428 413 RESTORE_TOP_OF_STACK %r11 429 - movq %r15, %r11 430 - CFI_REGISTER rip, r11 431 - RESTORE_REST 432 - pushq %r11 433 - CFI_ADJUST_CFA_OFFSET 8 434 - CFI_REL_OFFSET rip, 0 435 - ret 436 - 437 - exec_32bit: 438 - CFI_RESTORE_STATE 439 414 movq %rax,RAX(%rsp) 440 415 RESTORE_REST 441 416 jmp int_ret_from_sys_call