From: Greg Kroah-Hartman Date: Tue, 10 Oct 2017 18:48:00 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v3.18.75~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f5f2a5ef291515dd19792d024c5fcdb125b79765;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: kvm-x86-fix-singlestepping-over-syscall.patch --- diff --git a/queue-4.9/kvm-x86-fix-singlestepping-over-syscall.patch b/queue-4.9/kvm-x86-fix-singlestepping-over-syscall.patch new file mode 100644 index 00000000000..4ba51c7d17a --- /dev/null +++ b/queue-4.9/kvm-x86-fix-singlestepping-over-syscall.patch @@ -0,0 +1,140 @@ +From c8401dda2f0a00cd25c0af6a95ed50e478d25de4 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 7 Jun 2017 15:13:14 +0200 +Subject: KVM: x86: fix singlestepping over syscall +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paolo Bonzini + +commit c8401dda2f0a00cd25c0af6a95ed50e478d25de4 upstream. + +TF is handled a bit differently for syscall and sysret, compared +to the other instructions: TF is checked after the instruction completes, +so that the OS can disable #DB at a syscall by adding TF to FMASK. +When the sysret is executed the #DB is taken "as if" the syscall insn +just completed. + +KVM emulates syscall so that it can trap 32-bit syscall on Intel processors. +Fix the behavior, otherwise you could get #DB on a user stack which is not +nice. This does not affect Linux guests, as they use an IST or task gate +for #DB. + +This fixes CVE-2017-7518. + +Cc: stable@vger.kernel.org +Reported-by: Andy Lutomirski +Signed-off-by: Paolo Bonzini +Signed-off-by: Radim Krčmář +[bwh: Backported to 4.9: + - kvm_vcpu_check_singlestep() sets some flags differently + - Drop changes to kvm_skip_emulated_instruction()] +Cc: Ben Hutchings +Cc: Salvatore Bonaccorso +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/kvm_emulate.h | 1 + arch/x86/kvm/emulate.c | 1 + arch/x86/kvm/x86.c | 52 +++++++++++++++---------------------- + 3 files changed, 24 insertions(+), 30 deletions(-) + +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -296,6 +296,7 @@ struct x86_emulate_ctxt { + + bool perm_ok; /* do not check permissions if true */ + bool ud; /* inject an #UD if host doesn't support insn */ ++ bool tf; /* TF value before instruction (after for syscall/sysret) */ + + bool have_exception; + struct x86_exception exception; +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2738,6 +2738,7 @@ static int em_syscall(struct x86_emulate + ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF); + } + ++ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; + return X86EMUL_CONTINUE; + } + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5250,6 +5250,8 @@ static void init_emulate_ctxt(struct kvm + kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); + + ctxt->eflags = kvm_get_rflags(vcpu); ++ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; ++ + ctxt->eip = kvm_rip_read(vcpu); + ctxt->mode = (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL : + (ctxt->eflags & X86_EFLAGS_VM) ? X86EMUL_MODE_VM86 : +@@ -5465,37 +5467,26 @@ static int kvm_vcpu_check_hw_bp(unsigned + return dr6; + } + +-static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r) ++static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r) + { + struct kvm_run *kvm_run = vcpu->run; + +- /* +- * rflags is the old, "raw" value of the flags. The new value has +- * not been saved yet. +- * +- * This is correct even for TF set by the guest, because "the +- * processor will not generate this exception after the instruction +- * that sets the TF flag". +- */ +- if (unlikely(rflags & X86_EFLAGS_TF)) { +- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { +- kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | +- DR6_RTM; +- kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; +- kvm_run->debug.arch.exception = DB_VECTOR; +- kvm_run->exit_reason = KVM_EXIT_DEBUG; +- *r = EMULATE_USER_EXIT; +- } else { +- vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; +- /* +- * "Certain debug exceptions may clear bit 0-3. The +- * remaining contents of the DR6 register are never +- * cleared by the processor". +- */ +- vcpu->arch.dr6 &= ~15; +- vcpu->arch.dr6 |= DR6_BS | DR6_RTM; +- kvm_queue_exception(vcpu, DB_VECTOR); +- } ++ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { ++ kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | DR6_RTM; ++ kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; ++ kvm_run->debug.arch.exception = DB_VECTOR; ++ kvm_run->exit_reason = KVM_EXIT_DEBUG; ++ *r = EMULATE_USER_EXIT; ++ } else { ++ vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; ++ /* ++ * "Certain debug exceptions may clear bit 0-3. The ++ * remaining contents of the DR6 register are never ++ * cleared by the processor". ++ */ ++ vcpu->arch.dr6 &= ~15; ++ vcpu->arch.dr6 |= DR6_BS | DR6_RTM; ++ kvm_queue_exception(vcpu, DB_VECTOR); + } + } + +@@ -5650,8 +5641,9 @@ restart: + toggle_interruptibility(vcpu, ctxt->interruptibility); + vcpu->arch.emulate_regs_need_sync_to_vcpu = false; + kvm_rip_write(vcpu, ctxt->eip); +- if (r == EMULATE_DONE) +- kvm_vcpu_check_singlestep(vcpu, rflags, &r); ++ if (r == EMULATE_DONE && ++ (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP))) ++ kvm_vcpu_do_singlestep(vcpu, &r); + if (!ctxt->have_exception || + exception_type(ctxt->exception.vector) == EXCPT_TRAP) + __kvm_set_rflags(vcpu, ctxt->eflags); diff --git a/queue-4.9/series b/queue-4.9/series index 301c4b01797..0f2926f7159 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -102,3 +102,4 @@ ext4-fix-data-corruption-for-mmap-writes.patch ext4-don-t-clear-sgid-when-inheriting-acls.patch ext4-don-t-allow-encrypted-operations-without-keys.patch f2fs-don-t-allow-encrypted-operations-without-keys.patch +kvm-x86-fix-singlestepping-over-syscall.patch