From: Joerg Roedel <jroedel@suse.de>
Date: Fri, 10 Aug 2018 15:27:01 +0200
Subject: [PATCH] x86/kvm: kABI workaround for CVE-2018-10853 fix
References: CVE-2018-10853 bsc#1097104
Patch-mainline: Never, kabi
Signed-off-by: Joerg Roedel <jroedel@suse.de>
---
arch/x86/include/asm/kvm_emulate.h | 8 ++++----
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/emulate.c | 18 ++++++++++++------
arch/x86/kvm/x86.c | 26 +++++++++++++++++++++++---
4 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 96125be..c245481 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -106,12 +106,11 @@ struct x86_emulate_ops {
* @addr: [IN ] Linear address from which to read.
* @val: [OUT] Value read from memory, zero-extended to 'u_long'.
* @bytes: [IN ] Number of bytes to read from memory.
- * @system:[IN ] Whether the access is forced to be at CPL0.
*/
int (*read_std)(struct x86_emulate_ctxt *ctxt,
unsigned long addr, void *val,
unsigned int bytes,
- struct x86_exception *fault, bool system);
+ struct x86_exception *fault);
/*
* read_phys: Read bytes of standard (non-emulated/special) memory.
@@ -129,11 +128,10 @@ struct x86_emulate_ops {
* @addr: [IN ] Linear address to which to write.
* @val: [OUT] Value write to memory, zero-extended to 'u_long'.
* @bytes: [IN ] Number of bytes to write to memory.
- * @system:[IN ] Whether the access is forced to be at CPL0.
*/
int (*write_std)(struct x86_emulate_ctxt *ctxt,
unsigned long addr, void *val, unsigned int bytes,
- struct x86_exception *fault, bool system);
+ struct x86_exception *fault);
/*
* fetch: Read bytes of standard (non-emulated/special) memory.
* Used for instruction fetch.
@@ -229,6 +227,8 @@ struct x86_emulate_ops {
};
+void emulator_force_system(struct x86_emulate_ctxt *ctxt);
+
typedef u32 __attribute__((vector_size(16))) sse128_t;
/* Type, address-of, and value of an instruction's operand. */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a426243..d6982eb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1362,6 +1362,8 @@ enum {
#define HF_SMM_MASK (1 << 6)
#define HF_SMM_INSIDE_NMI_MASK (1 << 7)
+#define HF_FORCE_SYSTEM (1 << 31) /* kABI helper for ctxt->read_std */
+
#define __KVM_VCPU_MULTIPLE_ADDRESS_SPACE
#define KVM_ADDRESS_SPACE_NUM 2
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 98b1071..c1c94d6 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -814,14 +814,18 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear,
void *data, unsigned size)
{
- return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true);
+ emulator_force_system(ctxt);
+
+ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
}
static int linear_write_system(struct x86_emulate_ctxt *ctxt,
ulong linear, void *data,
unsigned int size)
{
- return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true);
+ emulator_force_system(ctxt);
+
+ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
}
static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
@@ -835,7 +839,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
rc = linearize(ctxt, addr, size, false, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false);
+ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
}
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
@@ -849,7 +853,7 @@ static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
rc = linearize(ctxt, addr, size, true, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false);
+ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
}
/*
@@ -2916,12 +2920,14 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
#ifdef CONFIG_X86_64
base |= ((u64)base3) << 32;
#endif
- r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true);
+ emulator_force_system(ctxt);
+ r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL);
if (r != X86EMUL_CONTINUE)
return false;
if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
return false;
- r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true);
+ emulator_force_system(ctxt);
+ r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL);
if (r != X86EMUL_CONTINUE)
return false;
if ((perm >> bit_idx) & mask)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2146603..2405922 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4545,12 +4545,32 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
}
EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
+void emulator_force_system(struct x86_emulate_ctxt *ctxt)
+{
+ u32 hflags = ctxt->ops->get_hflags(ctxt);
+
+ ctxt->ops->set_hflags(ctxt, hflags | HF_FORCE_SYSTEM);
+}
+
+static bool rw_std_force_system(struct x86_emulate_ctxt *ctxt)
+{
+ u32 hflags = ctxt->ops->get_hflags(ctxt);
+
+ if (hflags & HF_FORCE_SYSTEM) {
+ ctxt->ops->set_hflags(ctxt, hflags & ~HF_FORCE_SYSTEM);
+ return true;
+ }
+
+ return false;
+}
+
static int emulator_read_std(struct x86_emulate_ctxt *ctxt,
gva_t addr, void *val, unsigned int bytes,
- struct x86_exception *exception, bool system)
+ struct x86_exception *exception)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
u32 access = 0;
+ bool system = rw_std_force_system(ctxt);
if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
access |= PFERR_USER_MASK;
@@ -4599,11 +4619,11 @@ static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes
}
static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val,
- unsigned int bytes, struct x86_exception *exception,
- bool system)
+ unsigned int bytes, struct x86_exception *exception)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
u32 access = PFERR_WRITE_MASK;
+ bool system = rw_std_force_system(ctxt);
if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
access |= PFERR_USER_MASK;
--
2.12.3