diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-13 19:19:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-13 19:19:44 -0400 |
| commit | cd88ec2317015f9ae94fa55149bc6f61e1a460e9 (patch) | |
| tree | 6f5e066cfb60b8d6dfb1a9b806e69cdfd7c1a3c2 | |
| parent | 5b3e2e14eaa2a98232a4f292341fb88438685734 (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.S | 3 |
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: | |||
| 219 | 1: setbe %al /* 1 if error, 0 if not */ | 220 | 1: 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 |
