aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-08-13 19:19:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-13 19:19:44 -0400
commitcd88ec2317015f9ae94fa55149bc6f61e1a460e9 (patch)
tree6f5e066cfb60b8d6dfb1a9b806e69cdfd7c1a3c2
parent5b3e2e14eaa2a98232a4f292341fb88438685734 (diff)
x86: fix error handling for 32-bit compat out-of-range system call numbers
Commit 3f5159a9221f ("x86/asm/entry/32: Update -ENOSYS handling to match the 64-bit logic") broke the ENOSYS handling for the 32-bit compat case. The proper error return value was never loaded into %rax, except if things just happened to go through the audit paths, which ended up reloading the return value. This moves the loading or %rax into the normal system call path, just to make sure the error case triggers it. It's kind of sad, since it adds a useless instruction to reload the register to the fast path, but it's not like that single load from the stack is going to be noticeable. Reported-by: David Drysdale <drysdale@google.com> Tested-by: Kees Cook <keescook@chromium.org> Acked-by: Andy Lutomirski <luto@amacapital.net> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/entry/entry_64_compat.S3
1 files changed, 2 insertions, 1 deletions
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 5a1844765a7a..a7e257d9cb90 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -140,6 +140,7 @@ sysexit_from_sys_call:
140 */ 140 */
141 andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) 141 andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
142 movl RIP(%rsp), %ecx /* User %eip */ 142 movl RIP(%rsp), %ecx /* User %eip */
143 movq RAX(%rsp), %rax
143 RESTORE_RSI_RDI 144 RESTORE_RSI_RDI
144 xorl %edx, %edx /* Do not leak kernel information */ 145 xorl %edx, %edx /* Do not leak kernel information */
145 xorq %r8, %r8 146 xorq %r8, %r8
@@ -219,7 +220,6 @@ sysexit_from_sys_call:
2191: setbe %al /* 1 if error, 0 if not */ 2201: setbe %al /* 1 if error, 0 if not */
220 movzbl %al, %edi /* zero-extend that into %edi */ 221 movzbl %al, %edi /* zero-extend that into %edi */
221 call __audit_syscall_exit 222 call __audit_syscall_exit
222 movq RAX(%rsp), %rax /* reload syscall return value */
223 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi 223 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi
224 DISABLE_INTERRUPTS(CLBR_NONE) 224 DISABLE_INTERRUPTS(CLBR_NONE)
225 TRACE_IRQS_OFF 225 TRACE_IRQS_OFF
@@ -368,6 +368,7 @@ sysretl_from_sys_call:
368 RESTORE_RSI_RDI_RDX 368 RESTORE_RSI_RDI_RDX
369 movl RIP(%rsp), %ecx 369 movl RIP(%rsp), %ecx
370 movl EFLAGS(%rsp), %r11d 370 movl EFLAGS(%rsp), %r11d
371 movq RAX(%rsp), %rax
371 xorq %r10, %r10 372 xorq %r10, %r10
372 xorq %r9, %r9 373 xorq %r9, %r9
373 xorq %r8, %r8 374 xorq %r8, %r8