aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-02-10 07:21:35 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 12:07:11 -0400
commit065bc5cd9917ac5ae2c26c4ac9adecdae437a17a (patch)
treed752004d8e7ecaf0c422471c35d67cae54834b46
parent5832b65a5cbed395d469f77859d9a26e7265254d (diff)
KVM: x86 emulator: Check CPL level during privilege instruction emulation
commit e92805ac1228626c59c865f2f4e9059b9fb8c97b upstream. Add CPL checking in case emulator is tricked into emulating privilege instruction from userspace. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/x86/kvm/emulate.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 59a47ddf05b0..c998d27ceb5f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -76,6 +76,7 @@
76#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */ 76#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
77#define GroupMask 0xff /* Group number stored in bits 0:7 */ 77#define GroupMask 0xff /* Group number stored in bits 0:7 */
78/* Misc flags */ 78/* Misc flags */
79#define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */
79#define No64 (1<<28) 80#define No64 (1<<28)
80/* Source 2 operand type */ 81/* Source 2 operand type */
81#define Src2None (0<<29) 82#define Src2None (0<<29)
@@ -211,7 +212,7 @@ static u32 opcode_table[256] = {
211 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, 212 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
212 /* 0xF0 - 0xF7 */ 213 /* 0xF0 - 0xF7 */
213 0, 0, 0, 0, 214 0, 0, 0, 0,
214 ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3, 215 ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3,
215 /* 0xF8 - 0xFF */ 216 /* 0xF8 - 0xFF */
216 ImplicitOps, 0, ImplicitOps, ImplicitOps, 217 ImplicitOps, 0, ImplicitOps, ImplicitOps,
217 ImplicitOps, ImplicitOps, Group | Group4, Group | Group5, 218 ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
@@ -219,16 +220,20 @@ static u32 opcode_table[256] = {
219 220
220static u32 twobyte_table[256] = { 221static u32 twobyte_table[256] = {
221 /* 0x00 - 0x0F */ 222 /* 0x00 - 0x0F */
222 0, Group | GroupDual | Group7, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 223 0, Group | GroupDual | Group7, 0, 0,
223 ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 224 0, ImplicitOps, ImplicitOps | Priv, 0,
225 ImplicitOps | Priv, ImplicitOps | Priv, 0, 0,
226 0, ImplicitOps | ModRM, 0, 0,
224 /* 0x10 - 0x1F */ 227 /* 0x10 - 0x1F */
225 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 228 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
226 /* 0x20 - 0x2F */ 229 /* 0x20 - 0x2F */
227 ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0, 230 ModRM | ImplicitOps | Priv, ModRM | Priv,
231 ModRM | ImplicitOps | Priv, ModRM | Priv,
232 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 233 0, 0, 0, 0, 0, 0, 0, 0,
229 /* 0x30 - 0x3F */ 234 /* 0x30 - 0x3F */
230 ImplicitOps, 0, ImplicitOps, 0, 235 ImplicitOps | Priv, 0, ImplicitOps | Priv, 0,
231 ImplicitOps, ImplicitOps, 0, 0, 236 ImplicitOps, ImplicitOps | Priv, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 237 0, 0, 0, 0, 0, 0, 0, 0,
233 /* 0x40 - 0x47 */ 238 /* 0x40 - 0x47 */
234 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, 239 DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -322,9 +327,9 @@ static u32 group_table[] = {
322 SrcMem | ModRM | Stack, 0, 327 SrcMem | ModRM | Stack, 0,
323 SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, 0, 328 SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, 0,
324 [Group7*8] = 329 [Group7*8] =
325 0, 0, ModRM | SrcMem, ModRM | SrcMem, 330 0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
326 SrcNone | ModRM | DstMem | Mov, 0, 331 SrcNone | ModRM | DstMem | Mov, 0,
327 SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp, 332 SrcMem16 | ModRM | Mov | Priv, SrcMem | ModRM | ByteOp | Priv,
328 [Group8*8] = 333 [Group8*8] =
329 0, 0, 0, 0, 334 0, 0, 0, 0,
330 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM, 335 DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
@@ -335,7 +340,7 @@ static u32 group_table[] = {
335 340
336static u32 group2_table[] = { 341static u32 group2_table[] = {
337 [Group7*8] = 342 [Group7*8] =
338 SrcNone | ModRM, 0, 0, SrcNone | ModRM, 343 SrcNone | ModRM | Priv, 0, 0, SrcNone | ModRM,
339 SrcNone | ModRM | DstMem | Mov, 0, 344 SrcNone | ModRM | DstMem | Mov, 0,
340 SrcMem16 | ModRM | Mov, 0, 345 SrcMem16 | ModRM | Mov, 0,
341 [Group9*8] = 346 [Group9*8] =
@@ -1650,12 +1655,6 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt)
1650 return -1; 1655 return -1;
1651 } 1656 }
1652 1657
1653 /* sysexit must be called from CPL 0 */
1654 if (kvm_x86_ops->get_cpl(ctxt->vcpu) != 0) {
1655 kvm_inject_gp(ctxt->vcpu, 0);
1656 return -1;
1657 }
1658
1659 setup_syscalls_segments(ctxt, &cs, &ss); 1658 setup_syscalls_segments(ctxt, &cs, &ss);
1660 1659
1661 if ((c->rex_prefix & 0x8) != 0x0) 1660 if ((c->rex_prefix & 0x8) != 0x0)
@@ -1719,6 +1718,12 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1719 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); 1718 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
1720 saved_eip = c->eip; 1719 saved_eip = c->eip;
1721 1720
1721 /* Privileged instruction can be executed only in CPL=0 */
1722 if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) {
1723 kvm_inject_gp(ctxt->vcpu, 0);
1724 goto done;
1725 }
1726
1722 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs)) 1727 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
1723 memop = c->modrm_ea; 1728 memop = c->modrm_ea;
1724 1729