aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-02-10 07:21:35 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:36:11 -0500
commite92805ac1228626c59c865f2f4e9059b9fb8c97b (patch)
treeeb8d8c960ecd31649b9ae95e14ed7cc65c0d06c8 /arch/x86/kvm
parentd4c6a1549c056f1d817e8f6f2f97d8b44933472f (diff)
KVM: x86 emulator: Check CPL level during privilege instruction emulation
Add CPL checking in case emulator is tricked into emulating privilege instruction from userspace. Signed-off-by: Gleb Natapov <gleb@redhat.com> Cc: stable@kernel.org Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-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 1782387c069e..d63211169ac1 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] =
@@ -1700,12 +1705,6 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt)
1700 return -1; 1705 return -1;
1701 } 1706 }
1702 1707
1703 /* sysexit must be called from CPL 0 */
1704 if (kvm_x86_ops->get_cpl(ctxt->vcpu) != 0) {
1705 kvm_inject_gp(ctxt->vcpu, 0);
1706 return -1;
1707 }
1708
1709 setup_syscalls_segments(ctxt, &cs, &ss); 1708 setup_syscalls_segments(ctxt, &cs, &ss);
1710 1709
1711 if ((c->rex_prefix & 0x8) != 0x0) 1710 if ((c->rex_prefix & 0x8) != 0x0)
@@ -1820,6 +1819,12 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1820 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); 1819 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
1821 saved_eip = c->eip; 1820 saved_eip = c->eip;
1822 1821
1822 /* Privileged instruction can be executed only in CPL=0 */
1823 if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) {
1824 kvm_inject_gp(ctxt->vcpu, 0);
1825 goto done;
1826 }
1827
1823 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs)) 1828 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
1824 memop = c->modrm_ea; 1829 memop = c->modrm_ea;
1825 1830