Skip to content

Commit 32278c6

Browse files
sean-jcbp3tk0v
authored andcommitted
x86/umip: Check that the instruction opcode is at least two bytes
When checking for a potential UMIP violation on #GP, verify the decoder found at least two opcode bytes to avoid false positives when the kernel encounters an unknown instruction that starts with 0f. Because the array of opcode.bytes is zero-initialized by insn_init(), peeking at bytes[1] will misinterpret garbage as a potential SLDT or STR instruction, and can incorrectly trigger emulation. E.g. if a VPALIGNR instruction 62 83 c5 05 0f 08 ff vpalignr xmm17{k5},xmm23,XMMWORD PTR [r8],0xff hits a #GP, the kernel emulates it as STR and squashes the #GP (and corrupts the userspace code stream). Arguably the check should look for exactly two bytes, but no three byte opcodes use '0f 00 xx' or '0f 01 xx' as an escape, i.e. it should be impossible to get a false positive if the first two opcode bytes match '0f 00' or '0f 01'. Go with a more conservative check with respect to the existing code to minimize the chances of breaking userspace, e.g. due to decoder weirdness. Analyzed by Nick Bray <[email protected]>. Fixes: 1e5db22 ("x86/umip: Add emulation code for UMIP instructions") Reported-by: Dan Snyder <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected]
1 parent d98b40c commit 32278c6

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

arch/x86/kernel/umip.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ static int identify_insn(struct insn *insn)
156156
if (!insn->modrm.nbytes)
157157
return -EINVAL;
158158

159-
/* All the instructions of interest start with 0x0f. */
160-
if (insn->opcode.bytes[0] != 0xf)
159+
/* The instructions of interest have 2-byte opcodes: 0F 00 or 0F 01. */
160+
if (insn->opcode.nbytes < 2 || insn->opcode.bytes[0] != 0xf)
161161
return -EINVAL;
162162

163163
if (insn->opcode.bytes[1] == 0x1) {

0 commit comments

Comments
 (0)