From patchwork Sat Mar 16 03:43:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chengen Du X-Patchwork-Id: 1912775 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TxRnF5JXQz1yWy for ; Sat, 16 Mar 2024 14:44:16 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1rlKxi-0004nA-Ui; Sat, 16 Mar 2024 03:43:58 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1rlKxd-0004mf-7g for kernel-team@lists.ubuntu.com; Sat, 16 Mar 2024 03:43:53 +0000 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id E18B23F628 for ; Sat, 16 Mar 2024 03:43:52 +0000 (UTC) Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-29c751d57ddso2202079a91.1 for ; Fri, 15 Mar 2024 20:43:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710560631; x=1711165431; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R9rOiU53TX0fIkIoM5SUbzCspxboaVglKVeDsv2Zeg0=; b=adXFG/FqC5KsyLMqBS3vpsUNKLjiOa2t5FLltfGNFDtsEUJ/2rEL65Xhlld86WBNqW cklYyU1SL1vFqXZvqqbZTMOWXAjfd9DxozEGhLIw72OdGLFCbj+KZ4v17NXdspngFOPr sEyAxbKgahpg+J+HcMr0KO5CZG8jo0dMb7BRiS4OWJ46GsiinkP4Uhswsiq/lPw5NJ5m eEzk8aVVONkUQLjcdUzVok67s2UfU64nwVp0XCppP3cUMelL+4p1Zi3DAPsuAgUqL9WO Qv53mPg75JZ4pI7mBEkL0TZasirEh8Cn9RNYPgrt0pfKWbO/UIBy/YrosZPJmBxFyEGy xEPw== X-Gm-Message-State: AOJu0YzKB1HxvghWZ3TpROj7AK+NUdIoew8ePJS/ef02zouvuf0+zgHv bohHuac/YW+6KXp4LG7g7KPpLfiIix4oKc1W2a/fJ2E918gl3tTRvGXH0DgJ/LhbybF8WYKSEgR eTJalchx/MgRpz5n2hYhsWhhPRfqas36dHleGiIUaUbVPvXPqJHpJZv+59iAU+imt8+KXAS46bQ NZMdeoIBIdpA== X-Received: by 2002:a17:903:40d1:b0:1df:fa37:4975 with SMTP id t17-20020a17090340d100b001dffa374975mr477952pld.3.1710560630714; Fri, 15 Mar 2024 20:43:50 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHlVVcTUGHvu4QhaNktJmZnM/qIE40rOVyeMLWrfTZww1pUCiM8mfSpOT/kSbh5xzkrGdwmGQ== X-Received: by 2002:a17:903:40d1:b0:1df:fa37:4975 with SMTP id t17-20020a17090340d100b001dffa374975mr477940pld.3.1710560630302; Fri, 15 Mar 2024 20:43:50 -0700 (PDT) Received: from chengendu.. (111-248-145-30.dynamic-ip.hinet.net. [111.248.145.30]) by smtp.gmail.com with ESMTPSA id ki3-20020a170903068300b001dd02f4c2casm4695740plb.164.2024.03.15.20.43.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 20:43:50 -0700 (PDT) From: Chengen Du To: kernel-team@lists.ubuntu.com Subject: [SRU][J][PATCH 1/2] x86/fpu: Allow caller to constrain xfeatures when copying to uabi buffer Date: Sat, 16 Mar 2024 11:43:43 +0800 Message-Id: <20240316034344.17515-2-chengen.du@canonical.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240316034344.17515-1-chengen.du@canonical.com> References: <20240316034344.17515-1-chengen.du@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Sean Christopherson BugLink: https://bugs.launchpad.net/bugs/2032164 Plumb an xfeatures mask into __copy_xstate_to_uabi_buf() so that KVM can constrain which xfeatures are saved into the userspace buffer without having to modify the user_xfeatures field in KVM's guest_fpu state. KVM's ABI for KVM_GET_XSAVE{2} is that features that are not exposed to guest must not show up in the effective xstate_bv field of the buffer. Saving only the guest-supported xfeatures allows userspace to load the saved state on a different host with a fewer xfeatures, so long as the target host supports the xfeatures that are exposed to the guest. KVM currently sets user_xfeatures directly to restrict KVM_GET_XSAVE{2} to the set of guest-supported xfeatures, but doing so broke KVM's historical ABI for KVM_SET_XSAVE, which allows userspace to load any xfeatures that are supported by the *host*. Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-Id: <20230928001956.924301-2-seanjc@google.com> Signed-off-by: Paolo Bonzini (backported from commit 18164f66e6c59fda15c198b371fa008431efdb22) [chengen - modify kvm_vcpu_ioctl_x86_get_xsave's context] Signed-off-by: Chengen Du --- arch/x86/include/asm/fpu/api.h | 3 ++- arch/x86/kernel/fpu/core.c | 5 +++-- arch/x86/kernel/fpu/xstate.c | 7 +++++-- arch/x86/kernel/fpu/xstate.h | 3 ++- arch/x86/kvm/x86.c | 17 ++++++++++++----- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 1bec7a723003..73eb299f158b 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -145,7 +145,8 @@ extern bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu); extern void fpu_free_guest_fpstate(struct fpu_guest *gfpu); extern int fpu_swap_kvm_fpstate(struct fpu_guest *gfpu, bool enter_guest); -extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, unsigned int size, u32 pkru); +extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, + unsigned int size, u64 xfeatures, u32 pkru); extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru); static inline void fpstate_set_confidential(struct fpu_guest *gfpu) diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index a615eb2afbed..9f977dd53c8e 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -262,14 +262,15 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest) EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpstate); void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, - unsigned int size, u32 pkru) + unsigned int size, u64 xfeatures, u32 pkru) { struct fpstate *kstate = gfpu->fpstate; union fpregs_state *ustate = buf; struct membuf mb = { .p = buf, .left = size }; if (cpu_feature_enabled(X86_FEATURE_XSAVE)) { - __copy_xstate_to_uabi_buf(mb, kstate, pkru, XSTATE_COPY_XSAVE); + __copy_xstate_to_uabi_buf(mb, kstate, xfeatures, pkru, + XSTATE_COPY_XSAVE); } else { memcpy(&ustate->fxsave, &kstate->regs.fxsave, sizeof(ustate->fxsave)); diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 358c97d203bc..77cd7048302a 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -1127,6 +1127,7 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, * __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer * @to: membuf descriptor * @fpstate: The fpstate buffer from which to copy + * @xfeatures: The mask of xfeatures to save (XSAVE mode only) * @pkru_val: The PKRU value to store in the PKRU component * @copy_mode: The requested copy mode * @@ -1137,7 +1138,8 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, * It supports partial copy but @to.pos always starts from zero. */ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate, - u32 pkru_val, enum xstate_copy_mode copy_mode) + u64 xfeatures, u32 pkru_val, + enum xstate_copy_mode copy_mode) { const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr); struct xregs_state *xinit = &init_fpstate.regs.xsave; @@ -1161,7 +1163,7 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate, break; case XSTATE_COPY_XSAVE: - header.xfeatures &= fpstate->user_xfeatures; + header.xfeatures &= fpstate->user_xfeatures & xfeatures; break; } @@ -1256,6 +1258,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk, enum xstate_copy_mode copy_mode) { __copy_xstate_to_uabi_buf(to, tsk->thread.fpu.fpstate, + tsk->thread.fpu.fpstate->user_xfeatures, tsk->thread.pkru, copy_mode); } diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h index e18210dff88c..8aceb17e7fd8 100644 --- a/arch/x86/kernel/fpu/xstate.h +++ b/arch/x86/kernel/fpu/xstate.h @@ -33,7 +33,8 @@ enum xstate_copy_mode { struct membuf; extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate, - u32 pkru_val, enum xstate_copy_mode copy_mode); + u64 xfeatures, u32 pkru_val, + enum xstate_copy_mode copy_mode); extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk, enum xstate_copy_mode mode); extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8480300c6b0a..efa794d5436f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4862,18 +4862,25 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, return 0; } -static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, - struct kvm_xsave *guest_xsave) + +static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu, + u8 *state, unsigned int size) { if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return; - fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, - guest_xsave->region, - sizeof(guest_xsave->region), + fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size, + vcpu->arch.guest_fpu.fpstate->user_xfeatures, vcpu->arch.pkru); } +static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, + struct kvm_xsave *guest_xsave) +{ + return kvm_vcpu_ioctl_x86_get_xsave2(vcpu, (void *)guest_xsave->region, + sizeof(guest_xsave->region)); +} + static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, struct kvm_xsave *guest_xsave) { From patchwork Sat Mar 16 03:43:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chengen Du X-Patchwork-Id: 1912777 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TxRnF5Szsz23s6 for ; Sat, 16 Mar 2024 14:44:17 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1rlKxq-0004oy-B4; Sat, 16 Mar 2024 03:44:06 +0000 Received: from smtp-relay-internal-1.internal ([10.131.114.114] helo=smtp-relay-internal-1.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1rlKxe-0004mn-01 for kernel-team@lists.ubuntu.com; Sat, 16 Mar 2024 03:43:54 +0000 Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id D51AE3F628 for ; Sat, 16 Mar 2024 03:43:53 +0000 (UTC) Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-1dd96aefa68so26882235ad.3 for ; Fri, 15 Mar 2024 20:43:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710560632; x=1711165432; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HirGJy2rKe7zCYoDDRcqrcjlXBghB/kGGTisaRq1bOE=; b=ro5yxqlWU6NWFgccnJpb0lbhCGHDjgPLX40zwNCA0srqRZo+3OBHGOysVs2jE9j64p zmYkXPyQhPpbeMm0TSc30I4R4INppmZl0/0tc7G/aNH3MTmVTRm8l2glairjfY7IDOhE g8wfCJ/XA6lcZphjWgDVszaPKhmw7QY00hK/pwD9DOSbmXQYPf7Xbdiw/TbIfTc9FXlI AAZJThsIo4IlduuBidPR8NDsmVrLoiOypFAoQ3V3bpztZKqlyDM8C/+KJmU7xNU3Og2M Gy2E2CLj5GOGIpgYEzbdahCPCmb7HYXDn83ViIOu9bmii3v4yPQQA837jXj5REa/8Bt/ sNcw== X-Gm-Message-State: AOJu0YxhN+czLnItyRml1cnQrdhbcVlp6cYQV45GPkirp0nc2jZvmBUw 12UGVK3V5i1FziqSwUg9lW4m+M1MhPe8LbgiQRfBAaeT6A8ubK3/FzFe87Uxu0DHFOqqKj8CdUl Ceg4rNGnQZFDV+D2Hir+7QT9JRv2Pc5744tGdymoHjSTqZE3LF5dZjh3Olp6OT7AH9HNYbn96+6 XIqSqJDqjYPw== X-Received: by 2002:a17:902:c401:b0:1dd:dac3:297e with SMTP id k1-20020a170902c40100b001dddac3297emr9079272plk.13.1710560632205; Fri, 15 Mar 2024 20:43:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG7GL4eZifEaHTtVxDGBWALYrhajwJgQEly5PHAsP48THlSOZXQiOzm8FtYft5CbYOkIKyd4w== X-Received: by 2002:a17:902:c401:b0:1dd:dac3:297e with SMTP id k1-20020a170902c40100b001dddac3297emr9079258plk.13.1710560631899; Fri, 15 Mar 2024 20:43:51 -0700 (PDT) Received: from chengendu.. (111-248-145-30.dynamic-ip.hinet.net. [111.248.145.30]) by smtp.gmail.com with ESMTPSA id ki3-20020a170903068300b001dd02f4c2casm4695740plb.164.2024.03.15.20.43.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 20:43:51 -0700 (PDT) From: Chengen Du To: kernel-team@lists.ubuntu.com Subject: [SRU][J][PATCH 2/2] KVM: x86: Constrain guest-supported xfeatures only at KVM_GET_XSAVE{2} Date: Sat, 16 Mar 2024 11:43:44 +0800 Message-Id: <20240316034344.17515-3-chengen.du@canonical.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240316034344.17515-1-chengen.du@canonical.com> References: <20240316034344.17515-1-chengen.du@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Sean Christopherson BugLink: https://bugs.launchpad.net/bugs/2032164 Mask off xfeatures that aren't exposed to the guest only when saving guest state via KVM_GET_XSAVE{2} instead of modifying user_xfeatures directly. Preserving the maximal set of xfeatures in user_xfeatures restores KVM's ABI for KVM_SET_XSAVE, which prior to commit ad856280ddea ("x86/kvm/fpu: Limit guest user_xfeatures to supported bits of XCR0") allowed userspace to load xfeatures that are supported by the host, irrespective of what xfeatures are exposed to the guest. There is no known use case where userspace *intentionally* loads xfeatures that aren't exposed to the guest, but the bug fixed by commit ad856280ddea was specifically that KVM_GET_SAVE{2} would save xfeatures that weren't exposed to the guest, e.g. would lead to userspace unintentionally loading guest-unsupported xfeatures when live migrating a VM. Restricting KVM_SET_XSAVE to guest-supported xfeatures is especially problematic for QEMU-based setups, as QEMU has a bug where instead of terminating the VM if KVM_SET_XSAVE fails, QEMU instead simply stops loading guest state, i.e. resumes the guest after live migration with incomplete guest state, and ultimately results in guest data corruption. Note, letting userspace restore all host-supported xfeatures does not fix setups where a VM is migrated from a host *without* commit ad856280ddea, to a target with a subset of host-supported xfeatures. However there is no way to safely address that scenario, e.g. KVM could silently drop the unsupported features, but that would be a clear violation of KVM's ABI and so would require userspace to opt-in, at which point userspace could simply be updated to sanitize the to-be-loaded XSAVE state. Reported-by: Tyler Stachecki Closes: https://lore.kernel.org/all/20230914010003.358162-1-tstachecki@bloomberg.net Fixes: ad856280ddea ("x86/kvm/fpu: Limit guest user_xfeatures to supported bits of XCR0") Cc: stable@vger.kernel.org Cc: Leonardo Bras Signed-off-by: Sean Christopherson Acked-by: Dave Hansen Message-Id: <20230928001956.924301-3-seanjc@google.com> Signed-off-by: Paolo Bonzini (backported from commit 8647c52e9504c99752a39f1d44f6268f82c40a5c) [chengen - ignore changes related to fpstate_realloc and kvm_vcpu_after_set_cpuid because the commits associated with them are not included] Signed-off-by: Chengen Du --- arch/x86/kvm/x86.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index efa794d5436f..07c71892d5ae 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4866,12 +4866,26 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu, u8 *state, unsigned int size) { + /* + * Only copy state for features that are enabled for the guest. The + * state itself isn't problematic, but setting bits in the header for + * features that are supported in *this* host but not exposed to the + * guest can result in KVM_SET_XSAVE failing when live migrating to a + * compatible host without the features that are NOT exposed to the + * guest. + * + * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if + * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't + * supported by the host. + */ + u64 supported_xcr0 = vcpu->arch.guest_supported_xcr0 | + XFEATURE_MASK_FPSSE; + if (fpstate_is_confidential(&vcpu->arch.guest_fpu)) return; fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size, - vcpu->arch.guest_fpu.fpstate->user_xfeatures, - vcpu->arch.pkru); + supported_xcr0, vcpu->arch.pkru); } static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,