1 |
From ec6e4d863258d4bfb36d48d5e3ef68140234d688 Mon Sep 17 00:00:00 2001 |
2 |
From: Sean Christopherson <seanjc@google.com> |
3 |
Date: Mon, 11 Jul 2022 23:27:48 +0000 |
4 |
Subject: KVM: x86: Mark TSS busy during LTR emulation _after_ all fault checks |
5 |
|
6 |
From: Sean Christopherson <seanjc@google.com> |
7 |
|
8 |
commit ec6e4d863258d4bfb36d48d5e3ef68140234d688 upstream. |
9 |
|
10 |
Wait to mark the TSS as busy during LTR emulation until after all fault |
11 |
checks for the LTR have passed. Specifically, don't mark the TSS busy if |
12 |
the new TSS base is non-canonical. |
13 |
|
14 |
Opportunistically drop the one-off !seg_desc.PRESENT check for TR as the |
15 |
only reason for the early check was to avoid marking a !PRESENT TSS as |
16 |
busy, i.e. the common !PRESENT is now done before setting the busy bit. |
17 |
|
18 |
Fixes: e37a75a13cda ("KVM: x86: Emulator ignores LDTR/TR extended base on LLDT/LTR") |
19 |
Reported-by: syzbot+760a73552f47a8cd0fd9@syzkaller.appspotmail.com |
20 |
Cc: stable@vger.kernel.org |
21 |
Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> |
22 |
Cc: Hou Wenlong <houwenlong.hwl@antgroup.com> |
23 |
Signed-off-by: Sean Christopherson <seanjc@google.com> |
24 |
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> |
25 |
Link: https://lore.kernel.org/r/20220711232750.1092012-2-seanjc@google.com |
26 |
Signed-off-by: Sean Christopherson <seanjc@google.com> |
27 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
28 |
--- |
29 |
arch/x86/kvm/emulate.c | 19 +++++++++---------- |
30 |
1 file changed, 9 insertions(+), 10 deletions(-) |
31 |
|
32 |
--- a/arch/x86/kvm/emulate.c |
33 |
+++ b/arch/x86/kvm/emulate.c |
34 |
@@ -1669,16 +1669,6 @@ static int __load_segment_descriptor(str |
35 |
case VCPU_SREG_TR: |
36 |
if (seg_desc.s || (seg_desc.type != 1 && seg_desc.type != 9)) |
37 |
goto exception; |
38 |
- if (!seg_desc.p) { |
39 |
- err_vec = NP_VECTOR; |
40 |
- goto exception; |
41 |
- } |
42 |
- old_desc = seg_desc; |
43 |
- seg_desc.type |= 2; /* busy */ |
44 |
- ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, |
45 |
- sizeof(seg_desc), &ctxt->exception); |
46 |
- if (ret != X86EMUL_CONTINUE) |
47 |
- return ret; |
48 |
break; |
49 |
case VCPU_SREG_LDTR: |
50 |
if (seg_desc.s || seg_desc.type != 2) |
51 |
@@ -1719,6 +1709,15 @@ static int __load_segment_descriptor(str |
52 |
((u64)base3 << 32), ctxt)) |
53 |
return emulate_gp(ctxt, 0); |
54 |
} |
55 |
+ |
56 |
+ if (seg == VCPU_SREG_TR) { |
57 |
+ old_desc = seg_desc; |
58 |
+ seg_desc.type |= 2; /* busy */ |
59 |
+ ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, |
60 |
+ sizeof(seg_desc), &ctxt->exception); |
61 |
+ if (ret != X86EMUL_CONTINUE) |
62 |
+ return ret; |
63 |
+ } |
64 |
load: |
65 |
ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg); |
66 |
if (desc) |