In all three 32-bit entry points, %eax is zero-extended to %rax. It is safe to do 32-bit compare when checking that syscall# is not too large.
The last instance of "mysterious" SS+8 constant is replaced by SIZEOF_PTREGS. The $AUDIT_ARCH_X86_64 parameter to syscall_trace_enter_phase1/2 is a 32-bit constant, loading it with 64-bit MOV produces 10-byte insn instead of 5-byte one. After TEST insn, JE anctually means "jump of zero", let's use JZ mnemonic instead. At irq_return_via_sysret: * avoid redundant load of %r11 (it is already loaded a few instructions before). * do not needlessly increment %rsp - we are going to return to userspace via SYSRET, this insn doesn't use stack for return. Signed-off-by: Denys Vlasenko <dvlas...@redhat.com> CC: Linus Torvalds <torva...@linux-foundation.org> CC: Steven Rostedt <rost...@goodmis.org> CC: Ingo Molnar <mi...@kernel.org> CC: Borislav Petkov <b...@alien8.de> CC: "H. Peter Anvin" <h...@zytor.com> CC: Andy Lutomirski <l...@amacapital.net> CC: Oleg Nesterov <o...@redhat.com> CC: Frederic Weisbecker <fweis...@gmail.com> CC: Alexei Starovoitov <a...@plumgrid.com> CC: Will Drewry <w...@chromium.org> CC: Kees Cook <keesc...@chromium.org> CC: x...@kernel.org CC: linux-kernel@vger.kernel.org --- arch/x86/ia32/ia32entry.S | 14 +++++++------- arch/x86/include/asm/calling.h | 3 +++ arch/x86/kernel/entry_64.S | 13 ++++++------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 6dcd372..01eca80 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -163,8 +163,8 @@ sysenter_flags_fixed: orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) CFI_REMEMBER_STATE - jnz sysenter_tracesys - cmpq $(IA32_NR_syscalls-1),%rax + jnz sysenter_tracesys + cmpl $(IA32_NR_syscalls-1),%eax ja ia32_badsys sysenter_do_call: /* 32bit syscall -> 64bit C ABI argument conversion */ @@ -350,9 +350,9 @@ ENTRY(ia32_cstar_target) orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) CFI_REMEMBER_STATE - jnz cstar_tracesys - cmpq $IA32_NR_syscalls-1,%rax - ja ia32_badsys + jnz cstar_tracesys + cmpl $(IA32_NR_syscalls-1),%eax + ja ia32_badsys cstar_do_call: /* 32bit syscall -> 64bit C ABI argument conversion */ movl %edi,%r8d /* arg5 */ @@ -473,7 +473,7 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) jnz ia32_tracesys - cmpq $(IA32_NR_syscalls-1),%rax + cmpl $(IA32_NR_syscalls-1),%eax ja ia32_badsys ia32_do_call: /* 32bit syscall -> 64bit C ABI argument conversion */ @@ -536,7 +536,7 @@ ia32_ptregs_common: CFI_ENDPROC CFI_STARTPROC32 simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,SS+8 + CFI_DEF_CFA rsp,SIZEOF_PTREGS CFI_REL_OFFSET rax,RAX CFI_REL_OFFSET rcx,RCX CFI_REL_OFFSET rdx,RDX diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index 3374235..f1a962f 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h @@ -176,6 +176,9 @@ For 32-bit we have the following conventions - kernel is built with .macro RESTORE_C_REGS_EXCEPT_RCX RESTORE_C_REGS_HELPER 1,0,1,1,1 .endm + .macro RESTORE_C_REGS_EXCEPT_R11 + RESTORE_C_REGS_HELPER 1,1,0,1,1 + .endm .macro RESTORE_RSI_RDI RESTORE_C_REGS_HELPER 0,0,0,0,0 .endm diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 64f2fd3..b93f3a2 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -312,7 +312,7 @@ int_ret_from_sys_call_fixup: /* Do syscall tracing */ tracesys: movq %rsp, %rdi - movq $AUDIT_ARCH_X86_64, %rsi + movl $AUDIT_ARCH_X86_64, %esi call syscall_trace_enter_phase1 test %rax, %rax jnz tracesys_phase2 /* if needed, run the slow path */ @@ -323,7 +323,7 @@ tracesys_phase2: SAVE_EXTRA_REGS FIXUP_TOP_OF_STACK %rdi movq %rsp, %rdi - movq $AUDIT_ARCH_X86_64, %rsi + movl $AUDIT_ARCH_X86_64, %esi movq %rax,%rdx call syscall_trace_enter_phase2 @@ -686,7 +686,7 @@ ret_from_intr: exit_intr: GET_THREAD_INFO(%rcx) testl $3,CS(%rsp) - je retint_kernel + jz retint_kernel /* Interrupt came from user space */ /* @@ -742,7 +742,7 @@ retint_swapgs: /* return to user-space */ cmpq %r11,EFLAGS(%rsp) /* R11 == RFLAGS */ jne opportunistic_sysret_failed - testq $X86_EFLAGS_RF,%r11 /* sysret can't restore RF */ + testl $X86_EFLAGS_RF,%r11d /* sysret can't restore RF */ jnz opportunistic_sysret_failed /* nothing to check for RSP */ @@ -756,9 +756,8 @@ retint_swapgs: /* return to user-space */ */ irq_return_via_sysret: CFI_REMEMBER_STATE - RESTORE_C_REGS - REMOVE_PT_GPREGS_FROM_STACK 8 - movq (RSP-RIP)(%rsp),%rsp + RESTORE_C_REGS_EXCEPT_R11 + movq RSP(%rsp),%rsp USERGS_SYSRET64 CFI_RESTORE_STATE -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/