diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-02-10 07:21:35 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-15 12:07:11 -0400 |
commit | 065bc5cd9917ac5ae2c26c4ac9adecdae437a17a (patch) | |
tree | d752004d8e7ecaf0c422471c35d67cae54834b46 | |
parent | 5832b65a5cbed395d469f77859d9a26e7265254d (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.c | 35 |
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 | ||
220 | static u32 twobyte_table[256] = { | 221 | static 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 | ||
336 | static u32 group2_table[] = { | 341 | static 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 | ||