Skip to content

Commit 4fe4790

Browse files
sean-jcgregkh
authored andcommitted
x86/umip: Check that the instruction opcode is at least two bytes
commit 32278c6 upstream. 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 <ncbray@google.com>. Fixes: 1e5db22 ("x86/umip: Add emulation code for UMIP instructions") Reported-by: Dan Snyder <dansnyder@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 08c70f1 commit 4fe4790

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)