mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 21:54:06 +08:00
x86/asm/entry/32: Update -ENOSYS handling to match the 64-bit logic
Recently Andy changed the 64-bit syscall logic so that pt_regs->ax is initially set to -ENOSYS, and on syscall exit, it is updated with the actual return value. This simplified the logic there. This patch does the same for 32-bit syscall entry points. The check for %rax being too big is moved to be just before the call instruction which dispatches execution through the syscall table. There is no way to accidentally skip this check now by jumping to a label after it. This allows us to remove redundant checks after ptrace et al. If %rax is too big, we just skip over the (call, write %rax to pt_regs->ax) instruction pair. pt_regs->ax remains set to -ENOSYS, and it gets returned to userspace. Similar to 64-bit code, this eliminates the "ia32_badsys" code path. Run-tested. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> Cc: Alexei Starovoitov <ast@plumgrid.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Will Drewry <wad@chromium.org> Link: http://lkml.kernel.org/r/1429632194-13445-2-git-send-email-dvlasenk@redhat.com [ Changelog massage. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
ac7f5dfb03
commit
3f5159a922
@ -136,7 +136,7 @@ ENTRY(ia32_sysenter_target)
|
||||
pushq_cfi_reg rsi /* pt_regs->si */
|
||||
pushq_cfi_reg rdx /* pt_regs->dx */
|
||||
pushq_cfi_reg rcx /* pt_regs->cx */
|
||||
pushq_cfi_reg rax /* pt_regs->ax */
|
||||
pushq_cfi $-ENOSYS /* pt_regs->ax */
|
||||
cld
|
||||
sub $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
|
||||
CFI_ADJUST_CFA_OFFSET 10*8
|
||||
@ -163,8 +163,6 @@ sysenter_flags_fixed:
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
/* 32bit syscall -> 64bit C ABI argument conversion */
|
||||
movl %edi,%r8d /* arg5 */
|
||||
@ -173,8 +171,11 @@ sysenter_do_call:
|
||||
movl %ebx,%edi /* arg1 */
|
||||
movl %edx,%edx /* arg3 (zero extension) */
|
||||
sysenter_dispatch:
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja 1f
|
||||
call *ia32_sys_call_table(,%rax,8)
|
||||
movq %rax,RAX(%rsp)
|
||||
1:
|
||||
DISABLE_INTERRUPTS(CLBR_NONE)
|
||||
TRACE_IRQS_OFF
|
||||
testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
|
||||
@ -241,9 +242,7 @@ sysexit_from_sys_call:
|
||||
movl %ebx,%esi /* 2nd arg: 1st syscall arg */
|
||||
movl %eax,%edi /* 1st arg: syscall number */
|
||||
call __audit_syscall_entry
|
||||
movl RAX(%rsp),%eax /* reload syscall number */
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl ORIG_RAX(%rsp),%eax /* reload syscall number */
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX(%rsp),%esi /* reload 2nd syscall arg */
|
||||
movl RDX(%rsp),%edx /* reload 3rd syscall arg */
|
||||
@ -294,13 +293,10 @@ sysenter_tracesys:
|
||||
#endif
|
||||
SAVE_EXTRA_REGS
|
||||
CLEAR_RREGS
|
||||
movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
|
||||
movq %rsp,%rdi /* &pt_regs -> arg1 */
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_EXTRA_REGS
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
ENDPROC(ia32_sysenter_target)
|
||||
@ -370,7 +366,7 @@ ENTRY(ia32_cstar_target)
|
||||
pushq_cfi_reg rdx /* pt_regs->dx */
|
||||
pushq_cfi_reg rbp /* pt_regs->cx */
|
||||
movl %ebp,%ecx
|
||||
pushq_cfi_reg rax /* pt_regs->ax */
|
||||
pushq_cfi $-ENOSYS /* pt_regs->ax */
|
||||
sub $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
|
||||
CFI_ADJUST_CFA_OFFSET 10*8
|
||||
|
||||
@ -386,8 +382,6 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
/* 32bit syscall -> 64bit C ABI argument conversion */
|
||||
movl %edi,%r8d /* arg5 */
|
||||
@ -396,8 +390,11 @@ cstar_do_call:
|
||||
movl %ebx,%edi /* arg1 */
|
||||
movl %edx,%edx /* arg3 (zero extension) */
|
||||
cstar_dispatch:
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja 1f
|
||||
call *ia32_sys_call_table(,%rax,8)
|
||||
movq %rax,RAX(%rsp)
|
||||
1:
|
||||
DISABLE_INTERRUPTS(CLBR_NONE)
|
||||
TRACE_IRQS_OFF
|
||||
testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
|
||||
@ -444,14 +441,11 @@ cstar_tracesys:
|
||||
xchgl %r9d,%ebp
|
||||
SAVE_EXTRA_REGS
|
||||
CLEAR_RREGS r9
|
||||
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
|
||||
movq %rsp,%rdi /* &pt_regs -> arg1 */
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_EXTRA_REGS
|
||||
xchgl %ebp,%r9d
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
|
||||
@ -510,7 +504,7 @@ ENTRY(ia32_syscall)
|
||||
pushq_cfi_reg rsi /* pt_regs->si */
|
||||
pushq_cfi_reg rdx /* pt_regs->dx */
|
||||
pushq_cfi_reg rcx /* pt_regs->cx */
|
||||
pushq_cfi_reg rax /* pt_regs->ax */
|
||||
pushq_cfi $-ENOSYS /* pt_regs->ax */
|
||||
cld
|
||||
sub $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
|
||||
CFI_ADJUST_CFA_OFFSET 10*8
|
||||
@ -518,8 +512,6 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
|
||||
jnz ia32_tracesys
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
/* 32bit syscall -> 64bit C ABI argument conversion */
|
||||
movl %edi,%r8d /* arg5 */
|
||||
@ -527,9 +519,12 @@ ia32_do_call:
|
||||
xchg %ecx,%esi /* rsi:arg2, rcx:arg4 */
|
||||
movl %ebx,%edi /* arg1 */
|
||||
movl %edx,%edx /* arg3 (zero extension) */
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja 1f
|
||||
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
|
||||
ia32_sysret:
|
||||
movq %rax,RAX(%rsp)
|
||||
1:
|
||||
ia32_ret_from_sys_call:
|
||||
CLEAR_RREGS
|
||||
jmp int_ret_from_sys_call
|
||||
@ -537,23 +532,14 @@ ia32_ret_from_sys_call:
|
||||
ia32_tracesys:
|
||||
SAVE_EXTRA_REGS
|
||||
CLEAR_RREGS
|
||||
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
|
||||
movq %rsp,%rdi /* &pt_regs -> arg1 */
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_EXTRA_REGS
|
||||
cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
CFI_ENDPROC
|
||||
END(ia32_syscall)
|
||||
|
||||
ia32_badsys:
|
||||
movq $0,ORIG_RAX(%rsp)
|
||||
movq $-ENOSYS,%rax
|
||||
jmp ia32_sysret
|
||||
|
||||
CFI_ENDPROC
|
||||
|
||||
.macro PTREGSCALL label, func
|
||||
ALIGN
|
||||
GLOBAL(\label)
|
||||
|
Loading…
Reference in New Issue
Block a user