]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0226-kvm-x86-fix-RSM-when-PCID-is-non-zero.patch
update ZFS to 0.7.4 + ARC hit rate cherry-pick
[pve-kernel.git] / patches / kernel / 0226-kvm-x86-fix-RSM-when-PCID-is-non-zero.patch
CommitLineData
59d5af67 1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
321d628a
FG
2From: Paolo Bonzini <pbonzini@redhat.com>
3Date: Thu, 21 Dec 2017 00:49:14 +0100
59d5af67 4Subject: [PATCH] kvm: x86: fix RSM when PCID is non-zero
321d628a
FG
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9CVE-2017-5754
10
11rsm_load_state_64() and rsm_enter_protected_mode() load CR3, then
12CR4 & ~PCIDE, then CR0, then CR4.
13
14However, setting CR4.PCIDE fails if CR3[11:0] != 0. It's probably easier
15in the long run to replace rsm_enter_protected_mode() with an emulator
16callback that sets all the special registers (like KVM_SET_SREGS would
17do). For now, set the PCID field of CR3 only after CR4.PCIDE is 1.
18
19Reported-by: Laszlo Ersek <lersek@redhat.com>
20Tested-by: Laszlo Ersek <lersek@redhat.com>
21Fixes: 660a5d517aaab9187f93854425c4c63f4a09195c
22Cc: stable@vger.kernel.org
23Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24(cherry picked from commit fae1a3e775cca8c3a9e0eb34443b310871a15a92)
25Signed-off-by: Andy Whitcroft <apw@canonical.com>
26Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
27(cherry picked from commit dba4ceb9a91ed2d11a47722436b3c0be15e791d4)
28Signed-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
33diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
34index 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--
1232.14.2
124