]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0224-kvm-x86-fix-RSM-when-PCID-is-non-zero.patch
0e61616bb7d68d2b78b707592e35145a9fde0d4d
[pve-kernel.git] / patches / kernel / 0224-kvm-x86-fix-RSM-when-PCID-is-non-zero.patch
1 From 59b914593681a98524e4f3ba239544f77f03d14a Mon Sep 17 00:00:00 2001
2 From: Paolo Bonzini <pbonzini@redhat.com>
3 Date: Thu, 21 Dec 2017 00:49:14 +0100
4 Subject: [PATCH 224/233] kvm: x86: fix RSM when PCID is non-zero
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 CVE-2017-5754
10
11 rsm_load_state_64() and rsm_enter_protected_mode() load CR3, then
12 CR4 & ~PCIDE, then CR0, then CR4.
13
14 However, setting CR4.PCIDE fails if CR3[11:0] != 0. It's probably easier
15 in the long run to replace rsm_enter_protected_mode() with an emulator
16 callback that sets all the special registers (like KVM_SET_SREGS would
17 do). For now, set the PCID field of CR3 only after CR4.PCIDE is 1.
18
19 Reported-by: Laszlo Ersek <lersek@redhat.com>
20 Tested-by: Laszlo Ersek <lersek@redhat.com>
21 Fixes: 660a5d517aaab9187f93854425c4c63f4a09195c
22 Cc: stable@vger.kernel.org
23 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24 (cherry picked from commit fae1a3e775cca8c3a9e0eb34443b310871a15a92)
25 Signed-off-by: Andy Whitcroft <apw@canonical.com>
26 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
27 (cherry picked from commit dba4ceb9a91ed2d11a47722436b3c0be15e791d4)
28 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
29 ---
30 arch/x86/kvm/emulate.c | 32 +++++++++++++++++++++++++-------
31 1 file changed, 25 insertions(+), 7 deletions(-)
32
33 diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
34 index fb0055953fbc..155f2af2cb39 100644
35 --- a/arch/x86/kvm/emulate.c
36 +++ b/arch/x86/kvm/emulate.c
37 @@ -2399,9 +2399,21 @@ static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n)
38 }
39
40 static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
41 - u64 cr0, u64 cr4)
42 + u64 cr0, u64 cr3, u64 cr4)
43 {
44 int bad;
45 + u64 pcid;
46 +
47 + /* In order to later set CR4.PCIDE, CR3[11:0] must be zero. */
48 + pcid = 0;
49 + if (cr4 & X86_CR4_PCIDE) {
50 + pcid = cr3 & 0xfff;
51 + cr3 &= ~0xfff;
52 + }
53 +
54 + bad = ctxt->ops->set_cr(ctxt, 3, cr3);
55 + if (bad)
56 + return X86EMUL_UNHANDLEABLE;
57
58 /*
59 * First enable PAE, long mode needs it before CR0.PG = 1 is set.
60 @@ -2420,6 +2432,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
61 bad = ctxt->ops->set_cr(ctxt, 4, cr4);
62 if (bad)
63 return X86EMUL_UNHANDLEABLE;
64 + if (pcid) {
65 + bad = ctxt->ops->set_cr(ctxt, 3, cr3 | pcid);
66 + if (bad)
67 + return X86EMUL_UNHANDLEABLE;
68 + }
69 +
70 }
71
72 return X86EMUL_CONTINUE;
73 @@ -2430,11 +2448,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
74 struct desc_struct desc;
75 struct desc_ptr dt;
76 u16 selector;
77 - u32 val, cr0, cr4;
78 + u32 val, cr0, cr3, cr4;
79 int i;
80
81 cr0 = GET_SMSTATE(u32, smbase, 0x7ffc);
82 - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u32, smbase, 0x7ff8));
83 + cr3 = GET_SMSTATE(u32, smbase, 0x7ff8);
84 ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED;
85 ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0);
86
87 @@ -2476,14 +2494,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
88
89 ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8));
90
91 - return rsm_enter_protected_mode(ctxt, cr0, cr4);
92 + return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
93 }
94
95 static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
96 {
97 struct desc_struct desc;
98 struct desc_ptr dt;
99 - u64 val, cr0, cr4;
100 + u64 val, cr0, cr3, cr4;
101 u32 base3;
102 u16 selector;
103 int i, r;
104 @@ -2500,7 +2518,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
105 ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
106
107 cr0 = GET_SMSTATE(u64, smbase, 0x7f58);
108 - ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u64, smbase, 0x7f50));
109 + cr3 = GET_SMSTATE(u64, smbase, 0x7f50);
110 cr4 = GET_SMSTATE(u64, smbase, 0x7f48);
111 ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00));
112 val = GET_SMSTATE(u64, smbase, 0x7ed0);
113 @@ -2528,7 +2546,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
114 dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
115 ctxt->ops->set_gdt(ctxt, &dt);
116
117 - r = rsm_enter_protected_mode(ctxt, cr0, cr4);
118 + r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
119 if (r != X86EMUL_CONTINUE)
120 return r;
121
122 --
123 2.14.2
124