Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1230445pxb; Fri, 21 Jan 2022 12:52:57 -0800 (PST) X-Google-Smtp-Source: ABdhPJzW7aS2wrII1W65H+d6yHYdiAbeYnm7Yrh8gGeanZgkzP0LUBWk8LchsCfWLNXipxr1hymr X-Received: by 2002:a17:902:b78b:b0:14b:1339:58da with SMTP id e11-20020a170902b78b00b0014b133958damr5328978pls.98.1642798377695; Fri, 21 Jan 2022 12:52:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642798377; cv=none; d=google.com; s=arc-20160816; b=dP5ALp9v+SALHwsIiIp2pL+XjqpEhPsU+2lIJcfd4Ne/zDUyM7NMxOGUXJXhvuuFqo n6RuUjydL3MFHoFb1QVxOb++k16Ok9i8VZBsCpD1zB6ObONRnwptararmGXsG5p3ip7q cz1Zx03YJdMWrG9E+UMX918HTVVew4Q3RciXUxx9MhZjyQDloOS950dkx09dUB9VdS16 tz/XgLQ/GUJDR3OYxf3xJ7VJVLqQkpaTqi9icBjS8Qi4nOyoDTm6Iewfnx67p6dlLy1B JPerwoyBibtdRypCXYKU95f6X/ZQPWN2Gkq/0kCxyxxjpoOTRgCcHq0eEj4ZcGDIr781 FyXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:reply-to:dkim-signature; bh=SPmcB01Jw1VeFGKhxeTbS/wTzutTVSBvaADi6jp2W34=; b=w6je9tT0cagc8C7WpT0E2b5A1vzZoIX7QqyU7H3dV/g8Y05ZnaEoRGc1d98B+NaECX 4l50AJLSXmDJ1y5Wdd4AB/TUnf+Pn2ZbldJbJ8kjrD9qEGLAzv2dj2Dq+Kt3gOobXfhq ZCkMbpm/d4vlptHH4GyD1Q+9H/RVQcBMTc6pSw5ZvHoGwXCFRCJDf1y9X2+Rh0FDqinE fcIY1oV3znw8XE2c6EtMLBJly6iiGWYB3VrYFkxxGyb93iCrqmNhIdPtPmmLlhAIXJ9t qFpS5rjq7qYjCErdQEiUZ1aUe6hSV8oEEvJoHJGiFIOn1aAMx4chLEXmIaLrXVI/E8Qi taGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Bf6iFLmM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z17si8259329plg.253.2022.01.21.12.52.45; Fri, 21 Jan 2022 12:52:57 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Bf6iFLmM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358081AbiATBIA (ORCPT + 99 others); Wed, 19 Jan 2022 20:08:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49126 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1358065AbiATBHg (ORCPT ); Wed, 19 Jan 2022 20:07:36 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 86FD4C06173F for ; Wed, 19 Jan 2022 17:07:35 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id t27-20020a63461b000000b00342c204e4f3so2679498pga.11 for ; Wed, 19 Jan 2022 17:07:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=SPmcB01Jw1VeFGKhxeTbS/wTzutTVSBvaADi6jp2W34=; b=Bf6iFLmM0Eql/U38xrScPLNbMLbjXLYmQELg5ayX41BI4Km4eyFs4TB/Rsw2gkiqRI y97hQ2UJ/PZIa3tEWd3IL//sqfXfYIzOmAw/0ibi05slPvOGFHvT9r3hpqCu+AwvNzN8 RZBeeIAvE7Z+qJI1GXD8MkHuUo6cyFBK9kmLgEybj2zdReYvrHUEAYgYqkVKpgHt/NuA VHGCB3s7zv+zvQsqYzJPM/HoXCXKpZKehuedJ2x00uo29ZHA/ZRxxOhxPt5Fe3cwjHWs C35WKWS6Xh3/FOddroYlUxkhOlTFPRTCwvr9oBgmU5VGY7CY7b4zSKMtcPoyovU88X3U lCJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=SPmcB01Jw1VeFGKhxeTbS/wTzutTVSBvaADi6jp2W34=; b=GgY2g+DNIOyBQpHLKiHlFcxLwUzi+PH8fDVspgbkSVUHqW4MIhbSMp4vbg0ga3y4B/ bd1++DqjsSYpf6wrkdDy72M1RC/8iMXFtfYhyQhHfWrcWv4xSjGlHc5nIJUJWyGri1/a fkoXaX1AxnrqSmhegIJtvnXKvzAlnulTs66Vwq1jsA4xeFS8jASLbtw6IgmbQkZo9Dme mdZuY+fKdMwhh+mJnoUIaLWMdkGwfVIROuISqusR6Q0sX2ezFG9tIna9u679hAcg0KZP ypuebHarJfg1qbgm/b1rxll1/hUxpNlXsshf7t8GKXYxXr9LKbyY5I7sDAz0RLAaqSmo sEpw== X-Gm-Message-State: AOAM5312JSt+ZbeyqZ4QYjOnGr7fpweArPqBm6uBYqyADj2OpUyL2twB c83shnN2imHgM+iymLDyKVNqFSXgFxk= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:90b:1651:: with SMTP id il17mr7717476pjb.151.1642640855071; Wed, 19 Jan 2022 17:07:35 -0800 (PST) Reply-To: Sean Christopherson Date: Thu, 20 Jan 2022 01:07:17 +0000 In-Reply-To: <20220120010719.711476-1-seanjc@google.com> Message-Id: <20220120010719.711476-8-seanjc@google.com> Mime-Version: 1.0 References: <20220120010719.711476-1-seanjc@google.com> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog Subject: [PATCH 7/9] KVM: SVM: Inject #UD on attempted emulation for SEV guest w/o insn buffer From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Tom Lendacky , Brijesh Singh , Liam Merwick Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Inject #UD if KVM attempts emulation for an SEV guests without an insn buffer and instruction decoding is required. The previous behavior of allowing emulation if there is no insn buffer is undesirable as doing so means KVM is reading guest private memory and thus decoding cyphertext, i.e. is emulating garbage. The check was previously necessary as the emulation type was not provided, i.e. SVM needed to allow emulation to handle completion of emulation after exiting to userspace to handle I/O. Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 89 ++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ed2ca875b84b..d324183fc596 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4277,49 +4277,70 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type, if (sev_es_guest(vcpu->kvm)) return false; + /* + * Emulation is possible if the instruction is already decoded, e.g. + * when completing I/O after returning from userspace. + */ + if (emul_type & EMULTYPE_NO_DECODE) + return true; + + /* + * Emulation is possible for SEV guests if and only if a prefilled + * buffer containing the bytes of the intercepted instruction is + * available. SEV guest memory is encrypted with a guest specific key + * and cannot be decrypted by KVM, i.e. KVM would read cyphertext and + * decode garbage. + * + * Inject #UD if KVM reached this point without an instruction buffer. + * In practice, this path should never be hit by a well-behaved guest, + * e.g. KVM doesn't intercept #UD or #GP for SEV guests, but this path + * is still theoretically reachable, e.g. via unaccelerated fault-like + * AVIC access, and needs to be handled by KVM to avoid putting the + * guest into an infinite loop. Injecting #UD is somewhat arbitrary, + * but its the least awful option given lack of insight into the guest. + */ + if (unlikely(!insn)) { + kvm_queue_exception(vcpu, UD_VECTOR); + return false; + } + + /* + * Emulate for SEV guests if the insn buffer is not empty. The buffer + * will be empty if the DecodeAssist microcode cannot fetch bytes for + * the faulting instruction because the code fetch itself faulted, e.g. + * the guest attempted to fetch from emulated MMIO or a guest page + * table used to translate CS:RIP resides in emulated MMIO. + */ + if (likely(insn_len)) + return true; + /* * Detect and workaround Errata 1096 Fam_17h_00_0Fh. * * Errata: - * When CPU raise #NPF on guest data access and vCPU CR4.SMAP=1, it is - * possible that CPU microcode implementing DecodeAssist will fail - * to read bytes of instruction which caused #NPF. In this case, - * GuestIntrBytes field of the VMCB on a VMEXIT will incorrectly - * return 0 instead of the correct guest instruction bytes. - * - * This happens because CPU microcode reading instruction bytes - * uses a special opcode which attempts to read data using CPL=0 - * privileges. The microcode reads CS:RIP and if it hits a SMAP - * fault, it gives up and returns no instruction bytes. + * When CPU raises #NPF on guest data access and vCPU CR4.SMAP=1, it is + * possible that CPU microcode implementing DecodeAssist will fail to + * read guest memory at CS:RIP and vmcb.GuestIntrBytes will incorrectly + * be '0'. This happens because microcode reads CS:RIP using a _data_ + * loap uop with CPL=0 privileges. If the load hits a SMAP #PF, ucode + * gives up and does not fill the instruction bytes buffer. * * Detection: - * We reach here in case CPU supports DecodeAssist, raised #NPF and - * returned 0 in GuestIntrBytes field of the VMCB. - * First, errata can only be triggered in case vCPU CR4.SMAP=1. - * Second, if vCPU CR4.SMEP=1, errata could only be triggered - * in case vCPU CPL==3 (Because otherwise guest would have triggered - * a SMEP fault instead of #NPF). - * Otherwise, vCPU CR4.SMEP=0, errata could be triggered by any vCPU CPL. - * As most guests enable SMAP if they have also enabled SMEP, use above - * logic in order to attempt minimize false-positive of detecting errata - * while still preserving all cases semantic correctness. + * KVM reaches this point if the VM is an SEV guest, the CPU supports + * DecodeAssist, a #NPF was raised, KVM's page fault handler triggered + * emulation (e.g. for MMIO), and the CPU returned 0 in GuestIntrBytes + * field of the VMCB. * - * Workaround: - * To determine what instruction the guest was executing, the hypervisor - * will have to decode the instruction at the instruction pointer. + * This does _not_ mean that the erratum has been encountered, as the + * DecodeAssist will also fail if the load for CS:RIP hits a legitimate + * #PF, e.g. if the guest attempt to execute from emulated MMIO and + * encountered a reserved/not-present #PF. * - * In non SEV guest, hypervisor will be able to read the guest - * memory to decode the instruction pointer when insn_len is zero - * so we return true to indicate that decoding is possible. - * - * But in the SEV guest, the guest memory is encrypted with the - * guest specific key and hypervisor will not be able to decode the - * instruction pointer so we will not able to workaround it. Lets - * print the error and request to kill the guest. + * To reduce the likelihood of false positives, take action if and only + * if CR4.SMAP=1 (obviously required to hit the erratum) and CR4.SMEP=0 + * or CPL=3. If SMEP=1 and CPL!=3, the erratum cannot have been hit as + * the guest would have encountered a SMEP violation #PF, not a #NPF. */ - if (likely(!insn || insn_len)) - return true; - cr4 = kvm_read_cr4(vcpu); smep = cr4 & X86_CR4_SMEP; smap = cr4 & X86_CR4_SMAP; -- 2.34.1.703.g22d0c6ccf7-goog