Skip to content

Commit 8142b21

Browse files
swegenerH. Peter Anvin
authored andcommitted
x86_32, entry: Store badsys error code in %eax
Commit 554086d ("x86_32, entry: Do syscall exit work on badsys (CVE-2014-4508)") introduced a regression in the x86_32 syscall entry code, resulting in syscall() not returning proper errors for undefined syscalls on CPUs supporting the sysenter feature. The following code: > int result = syscall(666); > printf("result=%d errno=%d error=%s\n", result, errno, strerror(errno)); results in: > result=666 errno=0 error=Success Obviously, the syscall return value is the called syscall number, but it should have been an ENOSYS error. When run under ptrace it behaves correctly, which makes it hard to debug in the wild: > result=-1 errno=38 error=Function not implemented The %eax register is the return value register. For debugging via ptrace the syscall entry code stores the complete register context on the stack. The badsys handlers only store the ENOSYS error code in the ptrace register set and do not set %eax like a regular syscall handler would. The old resume_userspace call chain contains code that clobbers %eax and it restores %eax from the ptrace registers afterwards. The same goes for the ptrace-enabled call chain. When ptrace is not used, the syscall return value is the passed-in syscall number from the untouched %eax register. Use %eax as the return value register in syscall_badsys and sysenter_badsys, like a real syscall handler does, and have the caller push the value onto the stack for ptrace access. Signed-off-by: Sven Wegener <sven.wegener@stealer.net> Link: http://lkml.kernel.org/r/alpine.LNX.2.11.1407221022380.31021@titan.int.lan.stealer.net Reviewed-and-tested-by: Andy Lutomirski <luto@amacapital.net> Cc: <stable@vger.kernel.org> # If 554086d is backported Signed-off-by: H. Peter Anvin <hpa@zytor.com>
1 parent 9a3c414 commit 8142b21

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

arch/x86/kernel/entry_32.S

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ sysenter_do_call:
425425
cmpl $(NR_syscalls), %eax
426426
jae sysenter_badsys
427427
call *sys_call_table(,%eax,4)
428-
movl %eax,PT_EAX(%esp)
429428
sysenter_after_call:
429+
movl %eax,PT_EAX(%esp)
430430
LOCKDEP_SYS_EXIT
431431
DISABLE_INTERRUPTS(CLBR_ANY)
432432
TRACE_IRQS_OFF
@@ -502,6 +502,7 @@ ENTRY(system_call)
502502
jae syscall_badsys
503503
syscall_call:
504504
call *sys_call_table(,%eax,4)
505+
syscall_after_call:
505506
movl %eax,PT_EAX(%esp) # store the return value
506507
syscall_exit:
507508
LOCKDEP_SYS_EXIT
@@ -675,12 +676,12 @@ syscall_fault:
675676
END(syscall_fault)
676677

677678
syscall_badsys:
678-
movl $-ENOSYS,PT_EAX(%esp)
679-
jmp syscall_exit
679+
movl $-ENOSYS,%eax
680+
jmp syscall_after_call
680681
END(syscall_badsys)
681682

682683
sysenter_badsys:
683-
movl $-ENOSYS,PT_EAX(%esp)
684+
movl $-ENOSYS,%eax
684685
jmp sysenter_after_call
685686
END(syscall_badsys)
686687
CFI_ENDPROC

0 commit comments

Comments
 (0)