diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-02-10 07:21:35 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:36:11 -0500 |
commit | e92805ac1228626c59c865f2f4e9059b9fb8c97b (patch) | |
tree | eb8d8c960ecd31649b9ae95e14ed7cc65c0d06c8 /arch/x86/kvm | |
parent | d4c6a1549c056f1d817e8f6f2f97d8b44933472f (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.c | 35 |
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 | ||
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] = |
@@ -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 | ||