[v2 1/7] x86/mpx: Do not use SIB index if index points to R/ESP

Ricardo Neri <[email protected]>
Newsgroups org.kernel.vger.linux-msdos,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Section 2.2.1.2 of the Intel 64 and IA-32 Architectures Software
Developer's Manual volume 2A states that when memory addressing is used
(i.e., mod part of ModR/M is not 3), a SIB byte is used and the index of
the SIB byte points to the R/ESP (i.e.,index = 4), the index should not be
used in the computation of the memory address.

An example of such instruction could be

    insn -0x80(%rsp)

This is represented as:

     [opcode] 4c 24 80

      ModR/M: mod: 1, reg: 1: r/m: 4 (R/ESP)
      SIB 24: sc: 0, index: 100 (R/ESP), base(R/ESP): 100
      Displacement -0x80

The correct address is (base) + displacement; no index is used.

Care is taken to allow R12 to be used as index, which is a valid scenario.

Cc: Dave Hansen <[email protected]>
Cc: Adam Buchbinder <[email protected]>
Cc: Colin Ian King <[email protected]>
Cc: Lorenzo Stoakes <[email protected]>
Cc: Qiaowei Ren <[email protected]>
Cc: Ravi V. Shankar <[email protected]>
Cc: [email protected]
Signed-off-by: Ricardo Neri <[email protected]>
---
 arch/x86/mm/mpx.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 324e571..6a75a75 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -109,6 +109,13 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
 		regno = X86_SIB_INDEX(insn->sib.value);
 		if (X86_REX_X(insn->rex_prefix.value))
 			regno += 8;
+		/*
+		 * If mod !=3, SP is not used as index. Check is done after
+		 * looking at REX.X This is because R12 can be used as an
+		 * index.
+		 */
+		if (regno == 4 && X86_MODRM_RM(insn->modrm.value) != 3)
+			return 0;
 		break;
 
 	case REG_TYPE_BASE:
@@ -161,7 +168,10 @@ static void __user *mpx_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 				goto out_err;
 
 			base = regs_get_register(regs, base_offset);
-			indx = regs_get_register(regs, indx_offset);
+			if (indx_offset)
+				indx = regs_get_register(regs, indx_offset);
+			else
+				indx = 0;
 			addr = base + indx * (1 << X86_SIB_SCALE(sib));
 		} else {
 			addr_offset = get_reg_offset(insn, regs, REG_TYPE_RM);
-- 
2.9.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.