Blob Blame History Raw
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