]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.9.109/kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.109 / kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch
1 From 3c9fa24ca7c9c47605672916491f79e8ccacb9e6 Mon Sep 17 00:00:00 2001
2 From: Paolo Bonzini <pbonzini@redhat.com>
3 Date: Wed, 6 Jun 2018 17:38:09 +0200
4 Subject: kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access
5
6 From: Paolo Bonzini <pbonzini@redhat.com>
7
8 commit 3c9fa24ca7c9c47605672916491f79e8ccacb9e6 upstream.
9
10 The functions that were used in the emulation of fxrstor, fxsave, sgdt and
11 sidt were originally meant for task switching, and as such they did not
12 check privilege levels. This is very bad when the same functions are used
13 in the emulation of unprivileged instructions. This is CVE-2018-10853.
14
15 The obvious fix is to add a new argument to ops->read_std and ops->write_std,
16 which decides whether the access is a "system" access or should use the
17 processor's CPL.
18
19 Fixes: 129a72a0d3c8 ("KVM: x86: Introduce segmented_write_std", 2017-01-12)
20 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23 ---
24 arch/x86/include/asm/kvm_emulate.h | 6 ++++--
25 arch/x86/kvm/emulate.c | 12 ++++++------
26 arch/x86/kvm/x86.c | 18 ++++++++++++++----
27 3 files changed, 24 insertions(+), 12 deletions(-)
28
29 --- a/arch/x86/include/asm/kvm_emulate.h
30 +++ b/arch/x86/include/asm/kvm_emulate.h
31 @@ -105,11 +105,12 @@ struct x86_emulate_ops {
32 * @addr: [IN ] Linear address from which to read.
33 * @val: [OUT] Value read from memory, zero-extended to 'u_long'.
34 * @bytes: [IN ] Number of bytes to read from memory.
35 + * @system:[IN ] Whether the access is forced to be at CPL0.
36 */
37 int (*read_std)(struct x86_emulate_ctxt *ctxt,
38 unsigned long addr, void *val,
39 unsigned int bytes,
40 - struct x86_exception *fault);
41 + struct x86_exception *fault, bool system);
42
43 /*
44 * read_phys: Read bytes of standard (non-emulated/special) memory.
45 @@ -127,10 +128,11 @@ struct x86_emulate_ops {
46 * @addr: [IN ] Linear address to which to write.
47 * @val: [OUT] Value write to memory, zero-extended to 'u_long'.
48 * @bytes: [IN ] Number of bytes to write to memory.
49 + * @system:[IN ] Whether the access is forced to be at CPL0.
50 */
51 int (*write_std)(struct x86_emulate_ctxt *ctxt,
52 unsigned long addr, void *val, unsigned int bytes,
53 - struct x86_exception *fault);
54 + struct x86_exception *fault, bool system);
55 /*
56 * fetch: Read bytes of standard (non-emulated/special) memory.
57 * Used for instruction fetch.
58 --- a/arch/x86/kvm/emulate.c
59 +++ b/arch/x86/kvm/emulate.c
60 @@ -805,14 +805,14 @@ static inline int jmp_rel(struct x86_emu
61 static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear,
62 void *data, unsigned size)
63 {
64 - return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
65 + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true);
66 }
67
68 static int linear_write_system(struct x86_emulate_ctxt *ctxt,
69 ulong linear, void *data,
70 unsigned int size)
71 {
72 - return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
73 + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true);
74 }
75
76 static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
77 @@ -826,7 +826,7 @@ static int segmented_read_std(struct x86
78 rc = linearize(ctxt, addr, size, false, &linear);
79 if (rc != X86EMUL_CONTINUE)
80 return rc;
81 - return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
82 + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false);
83 }
84
85 static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
86 @@ -840,7 +840,7 @@ static int segmented_write_std(struct x8
87 rc = linearize(ctxt, addr, size, true, &linear);
88 if (rc != X86EMUL_CONTINUE)
89 return rc;
90 - return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
91 + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false);
92 }
93
94 /*
95 @@ -2912,12 +2912,12 @@ static bool emulator_io_port_access_allo
96 #ifdef CONFIG_X86_64
97 base |= ((u64)base3) << 32;
98 #endif
99 - r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL);
100 + r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true);
101 if (r != X86EMUL_CONTINUE)
102 return false;
103 if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
104 return false;
105 - r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL);
106 + r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true);
107 if (r != X86EMUL_CONTINUE)
108 return false;
109 if ((perm >> bit_idx) & mask)
110 --- a/arch/x86/kvm/x86.c
111 +++ b/arch/x86/kvm/x86.c
112 @@ -4408,10 +4408,15 @@ EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
113
114 static int emulator_read_std(struct x86_emulate_ctxt *ctxt,
115 gva_t addr, void *val, unsigned int bytes,
116 - struct x86_exception *exception)
117 + struct x86_exception *exception, bool system)
118 {
119 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
120 - return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
121 + u32 access = 0;
122 +
123 + if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
124 + access |= PFERR_USER_MASK;
125 +
126 + return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception);
127 }
128
129 static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
130 @@ -4455,12 +4460,17 @@ out:
131 }
132
133 static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val,
134 - unsigned int bytes, struct x86_exception *exception)
135 + unsigned int bytes, struct x86_exception *exception,
136 + bool system)
137 {
138 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
139 + u32 access = PFERR_WRITE_MASK;
140 +
141 + if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
142 + access |= PFERR_USER_MASK;
143
144 return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
145 - PFERR_WRITE_MASK, exception);
146 + access, exception);
147 }
148
149 int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,