Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Fri, 31 Oct 2014, Dave Hansen wrote: > On 10/27/2014 01:36 PM, Thomas Gleixner wrote: > > You're repeating yourself. Care to read the discussion about this from > > the last round of review again? > > OK, so here's a rewritten decoder. I think it's a lot more robust and > probably fixes a bug or two. This ends up saving ~70 lines of code out > of ~300 or so for the old patch. > > I'll include this in the next series, but I'm posting it early and often > to make sure I'm on the right track. Had a short glance. This looks really very well done! Thanks, tglx -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/27/2014 01:36 PM, Thomas Gleixner wrote: > You're repeating yourself. Care to read the discussion about this from > the last round of review again? OK, so here's a rewritten decoder. I think it's a lot more robust and probably fixes a bug or two. This ends up saving ~70 lines of code out of ~300 or so for the old patch. I'll include this in the next series, but I'm posting it early and often to make sure I'm on the right track. There is also a preparatory patch or two, but they're small. This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. We have to be very careful when decoding these instructions. They are completely controlled by userspace and may be changed at any time up to and including the point where we try to copy them in to the kernel. They may or may not be MPX instructions and could be completely invalid for all we know. Note: This code is based on Qiaowei Ren's specialized MPX decoder, but uses the generic decoder whenever possible. It was tested for robustness by generating a completely random data stream and trying to decode that stream. I also unmapped random pages inside the stream to test the "partial instruction" short read code. We kzalloc() the siginfo instead of stack allocating it because we need to memset() it anyway, and doing this makes it much more clear when it got initialized by the MPX instruction decoder. Changes from the old decoder: * Use the generic decoder instead of custom functions. Saved ~70 lines of code overall. * Remove insn->addr_bytes code (never used??) * Make sure never to possibly overflow the regoff[] array, plus check the register range correctly in 32 and 64-bit modes. * Allow get_reg() to return an error and have mpx_get_addr_ref() handle when it sees errors. * Only call insn_get_*() near where we actually use the values instead if trying to call them all at once. * Handle short reads from copy_from_user() and check the actual number of read bytes against what we expect from insn_get_length(). If a read stops in the middle of an instruction, we error out. * Actually check the opcodes intead of ignoring them. * Dynamically kzalloc() siginfo_t so we don't leak any stack data. * Detect and handle decoder failures instead of ignoring them. Signed-off-by: Qiaowei Ren Signed-off-by: Dave Hansen --- b/arch/x86/include/asm/mpx.h |8 + b/arch/x86/kernel/mpx.c | 229 +++ b/arch/x86/kernel/traps.c| 19 +++ 3 files changed, 255 insertions(+), 1 deletion(-) diff -puN arch/x86/include/asm/mpx.h~mpx-new-decoder arch/x86/include/asm/mpx.h --- a/arch/x86/include/asm/mpx.h~mpx-new-decoder 2014-10-31 11:36:17.130106540 -0700 +++ b/arch/x86/include/asm/mpx.h 2014-10-31 12:51:19.518584587 -0700 @@ -3,6 +3,7 @@ #include #include +#include /* * NULL is theoretically a valid place to put the bounds @@ -59,11 +60,18 @@ unsigned long mpx_mmap(unsigned long len #ifdef CONFIG_X86_INTEL_MPX int do_mpx_bt_fault(struct xsave_struct *xsave_buf); +siginfo_t *mpx_generate_signifo(struct pt_regs *regs, +struct xsave_struct *xsave_buf); #else static inline int do_mpx_bt_fault(struct xsave_struct *xsave_buf) { return -EINVAL; } +siginfo_t *mpx_generate_signifo(struct pt_regs *regs, +struct xsave_struct *xsave_buf); +{ + return NULL; +} #endif /* CONFIG_X86_INTEL_MPX */ #endif /* _ASM_X86_MPX_H */ diff -puN arch/x86/kernel/mpx.c~mpx-new-decoder arch/x86/kernel/mpx.c --- a/arch/x86/kernel/mpx.c~mpx-new-decoder 2014-10-31 11:36:17.131106585 -0700 +++ b/arch/x86/kernel/mpx.c 2014-10-31 13:12:22.644915144 -0700 @@ -81,6 +81,163 @@ int mpx_disable_management(struct task_s return 0; } +enum reg_type { + REG_TYPE_RM = 0, + REG_TYPE_INDEX, + REG_TYPE_BASE, +}; + +static unsigned long get_reg_offset(struct insn *insn, struct pt_regs *regs, +enum reg_type type) +{ + int regno = 0; + + static const int regoff[] = { + offsetof(struct pt_regs, ax), + offsetof(struct pt_regs, cx), + offsetof(struct pt_regs, dx), + offsetof(struct pt_regs, bx), + offsetof(struct pt_regs, sp), + offsetof(struct pt_regs, bp), + offsetof(struct pt_regs, si), + offsetof(struct pt_regs, di), +#ifdef CONFIG_X86_64 + offsetof(struct pt_regs, r8), + offsetof(struct pt_regs, r9), + offsetof(struct pt_regs, r10), + offsetof(struct pt_regs, r11), + offsetof(struct pt_regs, r12), + offsetof(struct pt_regs, r13), + offsetof(struct pt_regs, r14), + offsetof(struct pt_regs, r15), +#endif + }; + int nr_registers = ARRAY_SIZE(regoff); + /* + * Don't possibly decode a 32-bit instructions as + * reading a 64-bit-only register. + */ + if (IS_ENABLED(CONFIG_X86_64) && !insn->x86_64) + nr_registers -= 8; + + switch (type) { + case REG_TYPE_RM: + regno = X86_MODRM_RM(insn->modrm.value); + if (X86_REX_B(insn->rex_prefix.value) == 1) + regno += 8; + break; + +
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Fri, 31 Oct 2014, Ren Qiaowei wrote: > On 10/31/2014 06:38 AM, Dave Hansen wrote: > > > @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, > > > long error_code) > > > break; > > > > > > case 1: /* Bound violation. */ > > > + do_mpx_bounds(regs, , xsave_buf); > > > + do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, > > > + error_code, ); > > > + break; > > > + > > > case 0: /* No exception caused by Intel MPX operations. */ > > > do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, > > > error_code, > > > NULL); > > > break; > > > > > > > So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if > > it sees an invalid bndregno. We still send the signal with the > > whether or not we filled the 'info' in do_mpx_bounds(). > > > > Can't this leak some kernel stack out in the 'info'? > > > > This should check the return value of do_mpx_bounds and should be fixed. And how's that answering Dave's question about leaking stack information? Thanks, tglx -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Fri, 31 Oct 2014, Ren Qiaowei wrote: On 10/31/2014 06:38 AM, Dave Hansen wrote: @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) break; case 1: /* Bound violation. */ + do_mpx_bounds(regs, info, xsave_buf); + do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, + error_code, info); + break; + case 0: /* No exception caused by Intel MPX operations. */ do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, error_code, NULL); break; So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if it sees an invalid bndregno. We still send the signal with the info whether or not we filled the 'info' in do_mpx_bounds(). Can't this leak some kernel stack out in the 'info'? This should check the return value of do_mpx_bounds and should be fixed. And how's that answering Dave's question about leaking stack information? Thanks, tglx -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/27/2014 01:36 PM, Thomas Gleixner wrote: You're repeating yourself. Care to read the discussion about this from the last round of review again? OK, so here's a rewritten decoder. I think it's a lot more robust and probably fixes a bug or two. This ends up saving ~70 lines of code out of ~300 or so for the old patch. I'll include this in the next series, but I'm posting it early and often to make sure I'm on the right track. There is also a preparatory patch or two, but they're small. This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. We have to be very careful when decoding these instructions. They are completely controlled by userspace and may be changed at any time up to and including the point where we try to copy them in to the kernel. They may or may not be MPX instructions and could be completely invalid for all we know. Note: This code is based on Qiaowei Ren's specialized MPX decoder, but uses the generic decoder whenever possible. It was tested for robustness by generating a completely random data stream and trying to decode that stream. I also unmapped random pages inside the stream to test the partial instruction short read code. We kzalloc() the siginfo instead of stack allocating it because we need to memset() it anyway, and doing this makes it much more clear when it got initialized by the MPX instruction decoder. Changes from the old decoder: * Use the generic decoder instead of custom functions. Saved ~70 lines of code overall. * Remove insn-addr_bytes code (never used??) * Make sure never to possibly overflow the regoff[] array, plus check the register range correctly in 32 and 64-bit modes. * Allow get_reg() to return an error and have mpx_get_addr_ref() handle when it sees errors. * Only call insn_get_*() near where we actually use the values instead if trying to call them all at once. * Handle short reads from copy_from_user() and check the actual number of read bytes against what we expect from insn_get_length(). If a read stops in the middle of an instruction, we error out. * Actually check the opcodes intead of ignoring them. * Dynamically kzalloc() siginfo_t so we don't leak any stack data. * Detect and handle decoder failures instead of ignoring them. Signed-off-by: Qiaowei Ren qiaowei@intel.com Signed-off-by: Dave Hansen dave.han...@intel.com --- b/arch/x86/include/asm/mpx.h |8 + b/arch/x86/kernel/mpx.c | 229 +++ b/arch/x86/kernel/traps.c| 19 +++ 3 files changed, 255 insertions(+), 1 deletion(-) diff -puN arch/x86/include/asm/mpx.h~mpx-new-decoder arch/x86/include/asm/mpx.h --- a/arch/x86/include/asm/mpx.h~mpx-new-decoder 2014-10-31 11:36:17.130106540 -0700 +++ b/arch/x86/include/asm/mpx.h 2014-10-31 12:51:19.518584587 -0700 @@ -3,6 +3,7 @@ #include linux/types.h #include asm/ptrace.h +#include asm/insn.h /* * NULL is theoretically a valid place to put the bounds @@ -59,11 +60,18 @@ unsigned long mpx_mmap(unsigned long len #ifdef CONFIG_X86_INTEL_MPX int do_mpx_bt_fault(struct xsave_struct *xsave_buf); +siginfo_t *mpx_generate_signifo(struct pt_regs *regs, +struct xsave_struct *xsave_buf); #else static inline int do_mpx_bt_fault(struct xsave_struct *xsave_buf) { return -EINVAL; } +siginfo_t *mpx_generate_signifo(struct pt_regs *regs, +struct xsave_struct *xsave_buf); +{ + return NULL; +} #endif /* CONFIG_X86_INTEL_MPX */ #endif /* _ASM_X86_MPX_H */ diff -puN arch/x86/kernel/mpx.c~mpx-new-decoder arch/x86/kernel/mpx.c --- a/arch/x86/kernel/mpx.c~mpx-new-decoder 2014-10-31 11:36:17.131106585 -0700 +++ b/arch/x86/kernel/mpx.c 2014-10-31 13:12:22.644915144 -0700 @@ -81,6 +81,163 @@ int mpx_disable_management(struct task_s return 0; } +enum reg_type { + REG_TYPE_RM = 0, + REG_TYPE_INDEX, + REG_TYPE_BASE, +}; + +static unsigned long get_reg_offset(struct insn *insn, struct pt_regs *regs, +enum reg_type type) +{ + int regno = 0; + + static const int regoff[] = { + offsetof(struct pt_regs, ax), + offsetof(struct pt_regs, cx), + offsetof(struct pt_regs, dx), + offsetof(struct pt_regs, bx), + offsetof(struct pt_regs, sp), + offsetof(struct pt_regs, bp), + offsetof(struct pt_regs, si), + offsetof(struct pt_regs, di), +#ifdef CONFIG_X86_64 + offsetof(struct pt_regs, r8), + offsetof(struct pt_regs, r9), + offsetof(struct pt_regs, r10), + offsetof(struct pt_regs, r11), + offsetof(struct pt_regs, r12), + offsetof(struct pt_regs, r13), + offsetof(struct pt_regs, r14), + offsetof(struct pt_regs, r15), +#endif + }; + int nr_registers = ARRAY_SIZE(regoff); + /* + * Don't possibly decode a 32-bit instructions as + * reading a 64-bit-only register. + */ + if (IS_ENABLED(CONFIG_X86_64) !insn-x86_64) + nr_registers -= 8; + + switch (type) { + case REG_TYPE_RM: + regno = X86_MODRM_RM(insn-modrm.value); + if
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Fri, 31 Oct 2014, Dave Hansen wrote: On 10/27/2014 01:36 PM, Thomas Gleixner wrote: You're repeating yourself. Care to read the discussion about this from the last round of review again? OK, so here's a rewritten decoder. I think it's a lot more robust and probably fixes a bug or two. This ends up saving ~70 lines of code out of ~300 or so for the old patch. I'll include this in the next series, but I'm posting it early and often to make sure I'm on the right track. Had a short glance. This looks really very well done! Thanks, tglx -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/31/2014 06:38 AM, Dave Hansen wrote: +void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf) +{ + struct mpx_insn insn; + uint8_t bndregno; + unsigned long addr_vio; + + addr_vio = mpx_insn_decode(, regs); + + bndregno = X86_MODRM_REG(insn.modrm.value); + if (bndregno > 3) + return; + + /* Note: the upper 32 bits are ignored in 32-bit mode. */ + info->si_lower = (void __user *)(unsigned long) + (xsave_buf->bndregs.bndregs[2*bndregno]); + info->si_upper = (void __user *)(unsigned long) + (~xsave_buf->bndregs.bndregs[2*bndregno+1]); + info->si_addr_lsb = 0; + info->si_signo = SIGSEGV; + info->si_errno = 0; + info->si_code = SEGV_BNDERR; + info->si_addr = (void __user *)addr_vio; +} diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 611b6ec..b2a916b 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -284,6 +284,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) unsigned long status; struct xsave_struct *xsave_buf; struct task_struct *tsk = current; + siginfo_t info; prev_state = exception_enter(); if (notify_die(DIE_TRAP, "bounds", regs, error_code, @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) break; case 1: /* Bound violation. */ + do_mpx_bounds(regs, , xsave_buf); + do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, + error_code, ); + break; + case 0: /* No exception caused by Intel MPX operations. */ do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, NULL); break; So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if it sees an invalid bndregno. We still send the signal with the whether or not we filled the 'info' in do_mpx_bounds(). Can't this leak some kernel stack out in the 'info'? This should check the return value of do_mpx_bounds and should be fixed. Thanks, Qiaowei -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
> +void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, > + struct xsave_struct *xsave_buf) > +{ > + struct mpx_insn insn; > + uint8_t bndregno; > + unsigned long addr_vio; > + > + addr_vio = mpx_insn_decode(, regs); > + > + bndregno = X86_MODRM_REG(insn.modrm.value); > + if (bndregno > 3) > + return; > + > + /* Note: the upper 32 bits are ignored in 32-bit mode. */ > + info->si_lower = (void __user *)(unsigned long) > + (xsave_buf->bndregs.bndregs[2*bndregno]); > + info->si_upper = (void __user *)(unsigned long) > + (~xsave_buf->bndregs.bndregs[2*bndregno+1]); > + info->si_addr_lsb = 0; > + info->si_signo = SIGSEGV; > + info->si_errno = 0; > + info->si_code = SEGV_BNDERR; > + info->si_addr = (void __user *)addr_vio; > +} > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c > index 611b6ec..b2a916b 100644 > --- a/arch/x86/kernel/traps.c > +++ b/arch/x86/kernel/traps.c > @@ -284,6 +284,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long > error_code) > unsigned long status; > struct xsave_struct *xsave_buf; > struct task_struct *tsk = current; > + siginfo_t info; > > prev_state = exception_enter(); > if (notify_die(DIE_TRAP, "bounds", regs, error_code, > @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long > error_code) > break; > > case 1: /* Bound violation. */ > + do_mpx_bounds(regs, , xsave_buf); > + do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, > + error_code, ); > + break; > + > case 0: /* No exception caused by Intel MPX operations. */ > do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, NULL); > break; > So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if it sees an invalid bndregno. We still send the signal with the whether or not we filled the 'info' in do_mpx_bounds(). Can't this leak some kernel stack out in the 'info'? -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
+void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf) +{ + struct mpx_insn insn; + uint8_t bndregno; + unsigned long addr_vio; + + addr_vio = mpx_insn_decode(insn, regs); + + bndregno = X86_MODRM_REG(insn.modrm.value); + if (bndregno 3) + return; + + /* Note: the upper 32 bits are ignored in 32-bit mode. */ + info-si_lower = (void __user *)(unsigned long) + (xsave_buf-bndregs.bndregs[2*bndregno]); + info-si_upper = (void __user *)(unsigned long) + (~xsave_buf-bndregs.bndregs[2*bndregno+1]); + info-si_addr_lsb = 0; + info-si_signo = SIGSEGV; + info-si_errno = 0; + info-si_code = SEGV_BNDERR; + info-si_addr = (void __user *)addr_vio; +} diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 611b6ec..b2a916b 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -284,6 +284,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) unsigned long status; struct xsave_struct *xsave_buf; struct task_struct *tsk = current; + siginfo_t info; prev_state = exception_enter(); if (notify_die(DIE_TRAP, bounds, regs, error_code, @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) break; case 1: /* Bound violation. */ + do_mpx_bounds(regs, info, xsave_buf); + do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, + error_code, info); + break; + case 0: /* No exception caused by Intel MPX operations. */ do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, error_code, NULL); break; So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if it sees an invalid bndregno. We still send the signal with the info whether or not we filled the 'info' in do_mpx_bounds(). Can't this leak some kernel stack out in the 'info'? -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/31/2014 06:38 AM, Dave Hansen wrote: +void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf) +{ + struct mpx_insn insn; + uint8_t bndregno; + unsigned long addr_vio; + + addr_vio = mpx_insn_decode(insn, regs); + + bndregno = X86_MODRM_REG(insn.modrm.value); + if (bndregno 3) + return; + + /* Note: the upper 32 bits are ignored in 32-bit mode. */ + info-si_lower = (void __user *)(unsigned long) + (xsave_buf-bndregs.bndregs[2*bndregno]); + info-si_upper = (void __user *)(unsigned long) + (~xsave_buf-bndregs.bndregs[2*bndregno+1]); + info-si_addr_lsb = 0; + info-si_signo = SIGSEGV; + info-si_errno = 0; + info-si_code = SEGV_BNDERR; + info-si_addr = (void __user *)addr_vio; +} diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 611b6ec..b2a916b 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -284,6 +284,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) unsigned long status; struct xsave_struct *xsave_buf; struct task_struct *tsk = current; + siginfo_t info; prev_state = exception_enter(); if (notify_die(DIE_TRAP, bounds, regs, error_code, @@ -316,6 +317,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) break; case 1: /* Bound violation. */ + do_mpx_bounds(regs, info, xsave_buf); + do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, + error_code, info); + break; + case 0: /* No exception caused by Intel MPX operations. */ do_trap(X86_TRAP_BR, SIGSEGV, bounds, regs, error_code, NULL); break; So, siginfo is stack-allocarted here. do_mpx_bounds() can error out if it sees an invalid bndregno. We still send the signal with the info whether or not we filled the 'info' in do_mpx_bounds(). Can't this leak some kernel stack out in the 'info'? This should check the return value of do_mpx_bounds and should be fixed. Thanks, Qiaowei -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/28/2014 04:36 AM, Thomas Gleixner wrote: On Mon, 27 Oct 2014, Ren, Qiaowei wrote: On 2014-10-24, Thomas Gleixner wrote: On Sun, 12 Oct 2014, Qiaowei Ren wrote: This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. As hpa said, we only need to decode several mpx instructions including BNDCL/BNDCU, and general decoder looks like a little heavy. Peter, what do you think about it? You're repeating yourself. Care to read the discussion about this from the last round of review again? Ok. I will go through it again. Thanks. - Qiaowei -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 10/28/2014 04:36 AM, Thomas Gleixner wrote: On Mon, 27 Oct 2014, Ren, Qiaowei wrote: On 2014-10-24, Thomas Gleixner wrote: On Sun, 12 Oct 2014, Qiaowei Ren wrote: This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. As hpa said, we only need to decode several mpx instructions including BNDCL/BNDCU, and general decoder looks like a little heavy. Peter, what do you think about it? You're repeating yourself. Care to read the discussion about this from the last round of review again? Ok. I will go through it again. Thanks. - Qiaowei -- 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/
RE: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Mon, 27 Oct 2014, Ren, Qiaowei wrote: > On 2014-10-24, Thomas Gleixner wrote: > > On Sun, 12 Oct 2014, Qiaowei Ren wrote: > > > >> This patch sets bound violation fields of siginfo struct in #BR > >> exception handler by decoding the user instruction and constructing > >> the faulting pointer. > >> > >> This patch does't use the generic decoder, and implements a limited > >> special-purpose decoder to decode MPX instructions, simply because > >> the generic decoder is very heavyweight not just in terms of > >> performance but in terms of interface -- because it has to. > > > > My question still stands why using the existing decoder is an issue. > > Performance is a complete non issue in case of a bounds violation and > > the interface argument is just silly, really. > > > > As hpa said, we only need to decode several mpx instructions > including BNDCL/BNDCU, and general decoder looks like a little > heavy. Peter, what do you think about it? You're repeating yourself. Care to read the discussion about this from the last round of review again? Thanks, tglx -- 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/
RE: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Mon, 27 Oct 2014, Ren, Qiaowei wrote: On 2014-10-24, Thomas Gleixner wrote: On Sun, 12 Oct 2014, Qiaowei Ren wrote: This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. As hpa said, we only need to decode several mpx instructions including BNDCL/BNDCU, and general decoder looks like a little heavy. Peter, what do you think about it? You're repeating yourself. Care to read the discussion about this from the last round of review again? Thanks, tglx -- 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/
RE: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 2014-10-24, Thomas Gleixner wrote: > On Sun, 12 Oct 2014, Qiaowei Ren wrote: > >> This patch sets bound violation fields of siginfo struct in #BR >> exception handler by decoding the user instruction and constructing >> the faulting pointer. >> >> This patch does't use the generic decoder, and implements a limited >> special-purpose decoder to decode MPX instructions, simply because >> the generic decoder is very heavyweight not just in terms of >> performance but in terms of interface -- because it has to. > > My question still stands why using the existing decoder is an issue. > Performance is a complete non issue in case of a bounds violation and > the interface argument is just silly, really. > As hpa said, we only need to decode several mpx instructions including BNDCL/BNDCU, and general decoder looks like a little heavy. Peter, what do you think about it? Thanks, Qiaowei -- 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/
RE: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On 2014-10-24, Thomas Gleixner wrote: On Sun, 12 Oct 2014, Qiaowei Ren wrote: This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. As hpa said, we only need to decode several mpx instructions including BNDCL/BNDCU, and general decoder looks like a little heavy. Peter, what do you think about it? Thanks, Qiaowei -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Sun, 12 Oct 2014, Qiaowei Ren wrote: > This patch sets bound violation fields of siginfo struct in #BR > exception handler by decoding the user instruction and constructing > the faulting pointer. > > This patch does't use the generic decoder, and implements a limited > special-purpose decoder to decode MPX instructions, simply because the > generic decoder is very heavyweight not just in terms of performance > but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. Thanks, tglx -- 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/
Re: [PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
On Sun, 12 Oct 2014, Qiaowei Ren wrote: This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. My question still stands why using the existing decoder is an issue. Performance is a complete non issue in case of a bounds violation and the interface argument is just silly, really. Thanks, tglx -- 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/
[PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. Signed-off-by: Qiaowei Ren --- arch/x86/include/asm/mpx.h | 23 arch/x86/kernel/mpx.c | 299 arch/x86/kernel/traps.c|6 + 3 files changed, 328 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h index b7598ac..780af63 100644 --- a/arch/x86/include/asm/mpx.h +++ b/arch/x86/include/asm/mpx.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef CONFIG_X86_64 @@ -44,15 +45,37 @@ #define MPX_BNDSTA_ERROR_CODE 0x3 #define MPX_BD_ENTRY_VALID_FLAG0x1 +struct mpx_insn { + struct insn_field rex_prefix; /* REX prefix */ + struct insn_field modrm; + struct insn_field sib; + struct insn_field displacement; + + unsigned char addr_bytes; /* effective address size */ + unsigned char limit; + unsigned char x86_64; + + const unsigned char *kaddr; /* kernel address of insn to analyze */ + const unsigned char *next_byte; +}; + +#define MAX_MPX_INSN_SIZE 15 + unsigned long mpx_mmap(unsigned long len); #ifdef CONFIG_X86_INTEL_MPX int do_mpx_bt_fault(struct xsave_struct *xsave_buf); +void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf); #else static inline int do_mpx_bt_fault(struct xsave_struct *xsave_buf) { return -EINVAL; } +static inline void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf) +{ +} #endif /* CONFIG_X86_INTEL_MPX */ #endif /* _ASM_X86_MPX_H */ diff --git a/arch/x86/kernel/mpx.c b/arch/x86/kernel/mpx.c index 2103b5e..b7e4c0e 100644 --- a/arch/x86/kernel/mpx.c +++ b/arch/x86/kernel/mpx.c @@ -10,6 +10,275 @@ #include #include +enum reg_type { + REG_TYPE_RM = 0, + REG_TYPE_INDEX, + REG_TYPE_BASE, +}; + +static unsigned long get_reg(struct mpx_insn *insn, struct pt_regs *regs, +enum reg_type type) +{ + int regno = 0; + unsigned char modrm = (unsigned char)insn->modrm.value; + unsigned char sib = (unsigned char)insn->sib.value; + + static const int regoff[] = { + offsetof(struct pt_regs, ax), + offsetof(struct pt_regs, cx), + offsetof(struct pt_regs, dx), + offsetof(struct pt_regs, bx), + offsetof(struct pt_regs, sp), + offsetof(struct pt_regs, bp), + offsetof(struct pt_regs, si), + offsetof(struct pt_regs, di), +#ifdef CONFIG_X86_64 + offsetof(struct pt_regs, r8), + offsetof(struct pt_regs, r9), + offsetof(struct pt_regs, r10), + offsetof(struct pt_regs, r11), + offsetof(struct pt_regs, r12), + offsetof(struct pt_regs, r13), + offsetof(struct pt_regs, r14), + offsetof(struct pt_regs, r15), +#endif + }; + + switch (type) { + case REG_TYPE_RM: + regno = X86_MODRM_RM(modrm); + if (X86_REX_B(insn->rex_prefix.value) == 1) + regno += 8; + break; + + case REG_TYPE_INDEX: + regno = X86_SIB_INDEX(sib); + if (X86_REX_X(insn->rex_prefix.value) == 1) + regno += 8; + break; + + case REG_TYPE_BASE: + regno = X86_SIB_BASE(sib); + if (X86_REX_B(insn->rex_prefix.value) == 1) + regno += 8; + break; + + default: + break; + } + + return regs_get_register(regs, regoff[regno]); +} + +/* + * return the address being referenced be instruction + * for rm=3 returning the content of the rm reg + * for rm!=3 calculates the address using SIB and Disp + */ +static unsigned long get_addr_ref(struct mpx_insn *insn, struct pt_regs *regs) +{ + unsigned long addr; + unsigned long base; + unsigned long indx; + unsigned char modrm = (unsigned char)insn->modrm.value; + unsigned char sib = (unsigned char)insn->sib.value; + + if (X86_MODRM_MOD(modrm) == 3) { + addr = get_reg(insn, regs, REG_TYPE_RM); + } else { + if (insn->sib.nbytes) { + base = get_reg(insn, regs, REG_TYPE_BASE); + indx = get_reg(insn, regs, REG_TYPE_INDEX); + addr = base + indx * (1 << X86_SIB_SCALE(sib)); + } else { + addr = get_reg(insn,
[PATCH v9 09/12] x86, mpx: decode MPX instruction to get bound violation information
This patch sets bound violation fields of siginfo struct in #BR exception handler by decoding the user instruction and constructing the faulting pointer. This patch does't use the generic decoder, and implements a limited special-purpose decoder to decode MPX instructions, simply because the generic decoder is very heavyweight not just in terms of performance but in terms of interface -- because it has to. Signed-off-by: Qiaowei Ren qiaowei@intel.com --- arch/x86/include/asm/mpx.h | 23 arch/x86/kernel/mpx.c | 299 arch/x86/kernel/traps.c|6 + 3 files changed, 328 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h index b7598ac..780af63 100644 --- a/arch/x86/include/asm/mpx.h +++ b/arch/x86/include/asm/mpx.h @@ -3,6 +3,7 @@ #include linux/types.h #include asm/ptrace.h +#include asm/insn.h #ifdef CONFIG_X86_64 @@ -44,15 +45,37 @@ #define MPX_BNDSTA_ERROR_CODE 0x3 #define MPX_BD_ENTRY_VALID_FLAG0x1 +struct mpx_insn { + struct insn_field rex_prefix; /* REX prefix */ + struct insn_field modrm; + struct insn_field sib; + struct insn_field displacement; + + unsigned char addr_bytes; /* effective address size */ + unsigned char limit; + unsigned char x86_64; + + const unsigned char *kaddr; /* kernel address of insn to analyze */ + const unsigned char *next_byte; +}; + +#define MAX_MPX_INSN_SIZE 15 + unsigned long mpx_mmap(unsigned long len); #ifdef CONFIG_X86_INTEL_MPX int do_mpx_bt_fault(struct xsave_struct *xsave_buf); +void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf); #else static inline int do_mpx_bt_fault(struct xsave_struct *xsave_buf) { return -EINVAL; } +static inline void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info, + struct xsave_struct *xsave_buf) +{ +} #endif /* CONFIG_X86_INTEL_MPX */ #endif /* _ASM_X86_MPX_H */ diff --git a/arch/x86/kernel/mpx.c b/arch/x86/kernel/mpx.c index 2103b5e..b7e4c0e 100644 --- a/arch/x86/kernel/mpx.c +++ b/arch/x86/kernel/mpx.c @@ -10,6 +10,275 @@ #include linux/syscalls.h #include asm/mpx.h +enum reg_type { + REG_TYPE_RM = 0, + REG_TYPE_INDEX, + REG_TYPE_BASE, +}; + +static unsigned long get_reg(struct mpx_insn *insn, struct pt_regs *regs, +enum reg_type type) +{ + int regno = 0; + unsigned char modrm = (unsigned char)insn-modrm.value; + unsigned char sib = (unsigned char)insn-sib.value; + + static const int regoff[] = { + offsetof(struct pt_regs, ax), + offsetof(struct pt_regs, cx), + offsetof(struct pt_regs, dx), + offsetof(struct pt_regs, bx), + offsetof(struct pt_regs, sp), + offsetof(struct pt_regs, bp), + offsetof(struct pt_regs, si), + offsetof(struct pt_regs, di), +#ifdef CONFIG_X86_64 + offsetof(struct pt_regs, r8), + offsetof(struct pt_regs, r9), + offsetof(struct pt_regs, r10), + offsetof(struct pt_regs, r11), + offsetof(struct pt_regs, r12), + offsetof(struct pt_regs, r13), + offsetof(struct pt_regs, r14), + offsetof(struct pt_regs, r15), +#endif + }; + + switch (type) { + case REG_TYPE_RM: + regno = X86_MODRM_RM(modrm); + if (X86_REX_B(insn-rex_prefix.value) == 1) + regno += 8; + break; + + case REG_TYPE_INDEX: + regno = X86_SIB_INDEX(sib); + if (X86_REX_X(insn-rex_prefix.value) == 1) + regno += 8; + break; + + case REG_TYPE_BASE: + regno = X86_SIB_BASE(sib); + if (X86_REX_B(insn-rex_prefix.value) == 1) + regno += 8; + break; + + default: + break; + } + + return regs_get_register(regs, regoff[regno]); +} + +/* + * return the address being referenced be instruction + * for rm=3 returning the content of the rm reg + * for rm!=3 calculates the address using SIB and Disp + */ +static unsigned long get_addr_ref(struct mpx_insn *insn, struct pt_regs *regs) +{ + unsigned long addr; + unsigned long base; + unsigned long indx; + unsigned char modrm = (unsigned char)insn-modrm.value; + unsigned char sib = (unsigned char)insn-sib.value; + + if (X86_MODRM_MOD(modrm) == 3) { + addr = get_reg(insn, regs, REG_TYPE_RM); + } else { + if (insn-sib.nbytes) { + base = get_reg(insn, regs, REG_TYPE_BASE); + indx = get_reg(insn, regs, REG_TYPE_INDEX); + addr = base + indx * (1 X86_SIB_SCALE(sib));