aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-11-19 10:43:10 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-11-19 12:17:58 -0500
commita7315d2f3c6c4ff37b27c652dba70939d94d436c (patch)
tree24a94f85670a4803ea62993bf34ebebe5731f633 /arch/x86/kvm
parent1c1c35ae4b75d6fc08393a1f73a5a06dc68eebb8 (diff)
KVM: x86: Emulator performs privilege checks on __linearize
When segment is accessed, real hardware does not perform any privilege level checks. In contrast, KVM emulator does. This causes some discrepencies from real hardware. For instance, reading from readable code segment may fail due to incorrect segment checks. In addition, it introduces unnecassary overhead. To reference Intel SDM 5.5 ("Privilege Levels"): "Privilege levels are checked when the segment selector of a segment descriptor is loaded into a segment register." The SDM never mentions privilege level checks during memory access, except for loading far pointers in section 5.10 ("Pointer Validation"). Those are actually segment selector loads and are emulated in the similarily (i.e., regardless to __linearize checks). This behavior was also checked using sysexit. A data-segment whose DPL=0 was loaded, and after sysexit (CPL=3) it is still accessible. Therefore, all the privilege level checks in __linearize are removed. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c15
1 files changed, 0 insertions, 15 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 1317560d0823..d9461e47a65d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -663,7 +663,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
663 ulong la; 663 ulong la;
664 u32 lim; 664 u32 lim;
665 u16 sel; 665 u16 sel;
666 unsigned cpl;
667 666
668 la = seg_base(ctxt, addr.seg) + addr.ea; 667 la = seg_base(ctxt, addr.seg) + addr.ea;
669 *max_size = 0; 668 *max_size = 0;
@@ -705,20 +704,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
705 } 704 }
706 if (size > *max_size) 705 if (size > *max_size)
707 goto bad; 706 goto bad;
708 cpl = ctxt->ops->cpl(ctxt);
709 if (!fetch) {
710 /* data segment or readable code segment */
711 if (cpl > desc.dpl)
712 goto bad;
713 } else if ((desc.type & 8) && !(desc.type & 4)) {
714 /* nonconforming code segment */
715 if (cpl != desc.dpl)
716 goto bad;
717 } else if ((desc.type & 8) && (desc.type & 4)) {
718 /* conforming code segment */
719 if (cpl < desc.dpl)
720 goto bad;
721 }
722 break; 707 break;
723 } 708 }
724 if (ctxt->mode != X86EMUL_MODE_PROT64) 709 if (ctxt->mode != X86EMUL_MODE_PROT64)