From 8159eff8a56c0970df60f73efb5636494df02e28 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Jun 2018 14:15:56 +0200 Subject: [PATCH] 4.16-stable patches added patches: kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch --- ...-for-sgdt-sidt-fxsave-fxrstor-access.patch | 149 ++++++++++++++++++ queue-4.16/series | 1 + 2 files changed, 150 insertions(+) create mode 100644 queue-4.16/kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch diff --git a/queue-4.16/kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch b/queue-4.16/kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch new file mode 100644 index 00000000000..6a0638c5125 --- /dev/null +++ b/queue-4.16/kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch @@ -0,0 +1,149 @@ +From 3c9fa24ca7c9c47605672916491f79e8ccacb9e6 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 6 Jun 2018 17:38:09 +0200 +Subject: kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access + +From: Paolo Bonzini + +commit 3c9fa24ca7c9c47605672916491f79e8ccacb9e6 upstream. + +The functions that were used in the emulation of fxrstor, fxsave, sgdt and +sidt were originally meant for task switching, and as such they did not +check privilege levels. This is very bad when the same functions are used +in the emulation of unprivileged instructions. This is CVE-2018-10853. + +The obvious fix is to add a new argument to ops->read_std and ops->write_std, +which decides whether the access is a "system" access or should use the +processor's CPL. + +Fixes: 129a72a0d3c8 ("KVM: x86: Introduce segmented_write_std", 2017-01-12) +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/kvm_emulate.h | 6 ++++-- + arch/x86/kvm/emulate.c | 12 ++++++------ + arch/x86/kvm/x86.c | 18 ++++++++++++++---- + 3 files changed, 24 insertions(+), 12 deletions(-) + +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -107,11 +107,12 @@ 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); ++ struct x86_exception *fault, bool system); + + /* + * read_phys: Read bytes of standard (non-emulated/special) memory. +@@ -129,10 +130,11 @@ 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); ++ struct x86_exception *fault, bool system); + /* + * fetch: Read bytes of standard (non-emulated/special) memory. + * Used for instruction fetch. +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -814,14 +814,14 @@ static inline int jmp_rel(struct x86_emu + 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); ++ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true); + } + + 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); ++ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true); + } + + static int segmented_read_std(struct x86_emulate_ctxt *ctxt, +@@ -835,7 +835,7 @@ static int segmented_read_std(struct x86 + rc = linearize(ctxt, addr, size, false, &linear); + if (rc != X86EMUL_CONTINUE) + return rc; +- return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception); ++ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false); + } + + static int segmented_write_std(struct x86_emulate_ctxt *ctxt, +@@ -849,7 +849,7 @@ static int segmented_write_std(struct x8 + rc = linearize(ctxt, addr, size, true, &linear); + if (rc != X86EMUL_CONTINUE) + return rc; +- return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception); ++ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false); + } + + /* +@@ -2916,12 +2916,12 @@ static bool emulator_io_port_access_allo + #ifdef CONFIG_X86_64 + base |= ((u64)base3) << 32; + #endif +- r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL); ++ r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true); + 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); ++ r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true); + if (r != X86EMUL_CONTINUE) + return false; + if ((perm >> bit_idx) & mask) +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4716,10 +4716,15 @@ EXPORT_SYMBOL_GPL(kvm_read_guest_virt); + + static int emulator_read_std(struct x86_emulate_ctxt *ctxt, + gva_t addr, void *val, unsigned int bytes, +- struct x86_exception *exception) ++ struct x86_exception *exception, bool system) + { + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); +- return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception); ++ u32 access = 0; ++ ++ if (!system && kvm_x86_ops->get_cpl(vcpu) == 3) ++ access |= PFERR_USER_MASK; ++ ++ return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception); + } + + static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt, +@@ -4763,12 +4768,17 @@ out: + } + + static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val, +- unsigned int bytes, struct x86_exception *exception) ++ unsigned int bytes, struct x86_exception *exception, ++ bool system) + { + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); ++ u32 access = PFERR_WRITE_MASK; ++ ++ if (!system && kvm_x86_ops->get_cpl(vcpu) == 3) ++ access |= PFERR_USER_MASK; + + return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, +- PFERR_WRITE_MASK, exception); ++ access, exception); + } + + int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, diff --git a/queue-4.16/series b/queue-4.16/series index 10aceb789d0..2a17f8cdc63 100644 --- a/queue-4.16/series +++ b/queue-4.16/series @@ -28,3 +28,4 @@ serial-samsung-fix-maxburst-parameter-for-dma-transactions.patch serial-8250-omap-fix-idling-of-clocks-for-unused-uarts.patch vmw_balloon-fixing-double-free-when-batching-mode-is-off.patch tty-pl011-avoid-spuriously-stuck-off-interrupts.patch +kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch -- 2.47.3