Commit-ID:  4578f06fc93fb73c9c644ed838f4cdabbfdc4df1
Gitweb:     https://git.kernel.org/tip/4578f06fc93fb73c9c644ed838f4cdabbfdc4df1
Author:     Ricardo Neri <[email protected]>
AuthorDate: Fri, 27 Oct 2017 13:25:35 -0700
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 1 Nov 2017 21:50:10 +0100

x86/mpx: Do not use SIB.base if its value is 101b and ModRM.mod = 0

Section 2.2.1.2 of the Intel 64 and IA-32 Architectures Software
Developer's Manual volume 2A states that if a SIB byte is used and
SIB.base is 101b and ModRM.mod is zero, then the base part of the base
part of the effective address computation is null. To signal this
situation, a -EDOM error is returned to indicate callers to ignore the
base value present in the register operand.

In this scenario, a 32-bit displacement follows the SIB byte. Displacement
is obtained when the instruction decoder parses the operands.

Signed-off-by: Ricardo Neri <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Reviewed-by: Borislav Petkov <[email protected]>
Cc: Adan Hawthorn <[email protected]>
Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: [email protected]
Cc: Paul Gortmaker <[email protected]>
Cc: Huang Rui <[email protected]>
Cc: Qiaowei Ren <[email protected]>
Cc: Shuah Khan <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Jiri Slaby <[email protected]>
Cc: Nathan Howard <[email protected]>
Cc: "Ravi V. Shankar" <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Colin Ian King <[email protected]>
Cc: Chen Yucong <[email protected]>
Cc: Adam Buchbinder <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Lorenzo Stoakes <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Joe Perches <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Andrew Morton <[email protected]>
Link: 
https://lkml.kernel.org/r/1509135945-13762-9-git-send-email-ricardo.neri-calde...@linux.intel.com

---
 arch/x86/mm/mpx.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 2ad1d4a..581a960 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -123,6 +123,14 @@ static int get_reg_offset(struct insn *insn, struct 
pt_regs *regs,
 
        case REG_TYPE_BASE:
                regno = X86_SIB_BASE(insn->sib.value);
+               /*
+                * If ModRM.mod is 0 and SIB.base == 5, the base of the
+                * register-indirect addressing is 0. In this case, a
+                * 32-bit displacement follows the SIB byte.
+                */
+               if (!X86_MODRM_MOD(insn->modrm.value) && regno == 5)
+                       return -EDOM;
+
                if (X86_REX_B(insn->rex_prefix.value))
                        regno += 8;
                break;
@@ -164,16 +172,22 @@ static void __user *mpx_get_addr_ref(struct insn *insn, 
struct pt_regs *regs)
                eff_addr = regs_get_register(regs, addr_offset);
        } else {
                if (insn->sib.nbytes) {
+                       /*
+                        * Negative values in the base and index offset means
+                        * an error when decoding the SIB byte. Except -EDOM,
+                        * which means that the registers should not be used
+                        * in the address computation.
+                        */
                        base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
-                       if (base_offset < 0)
+                       if (base_offset == -EDOM)
+                               base = 0;
+                       else if (base_offset < 0)
                                goto out;
+                       else
+                               base = regs_get_register(regs, base_offset);
 
                        indx_offset = get_reg_offset(insn, regs, 
REG_TYPE_INDEX);
-                       /*
-                        * A negative offset generally means a error, except
-                        * -EDOM, which means that the contents of the register
-                        * should not be used as index.
-                        */
+
                        if (indx_offset == -EDOM)
                                indx = 0;
                        else if (indx_offset < 0)
@@ -181,8 +195,6 @@ static void __user *mpx_get_addr_ref(struct insn *insn, 
struct pt_regs *regs)
                        else
                                indx = regs_get_register(regs, indx_offset);
 
-                       base = regs_get_register(regs, base_offset);
-
                        eff_addr = base + indx * (1 << X86_SIB_SCALE(sib));
                } else {
                        addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);

Reply via email to