]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0017-KVM-x86-Constrain-guest-supported-xfeatures-only-at-.patch
bump version to 6.2.16-19
[pve-kernel.git] / patches / kernel / 0017-KVM-x86-Constrain-guest-supported-xfeatures-only-at-.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Sean Christopherson <seanjc@google.com>
3 Date: Wed, 27 Sep 2023 17:19:53 -0700
4 Subject: [PATCH] KVM: x86: Constrain guest-supported xfeatures only at
5 KVM_GET_XSAVE{2}
6
7 Mask off xfeatures that aren't exposed to the guest only when saving guest
8 state via KVM_GET_XSAVE{2} instead of modifying user_xfeatures directly.
9 Preserving the maximal set of xfeatures in user_xfeatures restores KVM's
10 ABI for KVM_SET_XSAVE, which prior to commit ad856280ddea ("x86/kvm/fpu:
11 Limit guest user_xfeatures to supported bits of XCR0") allowed userspace
12 to load xfeatures that are supported by the host, irrespective of what
13 xfeatures are exposed to the guest.
14
15 There is no known use case where userspace *intentionally* loads xfeatures
16 that aren't exposed to the guest, but the bug fixed by commit ad856280ddea
17 was specifically that KVM_GET_SAVE{2} would save xfeatures that weren't
18 exposed to the guest, e.g. would lead to userspace unintentionally loading
19 guest-unsupported xfeatures when live migrating a VM.
20
21 Restricting KVM_SET_XSAVE to guest-supported xfeatures is especially
22 problematic for QEMU-based setups, as QEMU has a bug where instead of
23 terminating the VM if KVM_SET_XSAVE fails, QEMU instead simply stops
24 loading guest state, i.e. resumes the guest after live migration with
25 incomplete guest state, and ultimately results in guest data corruption.
26
27 Note, letting userspace restore all host-supported xfeatures does not fix
28 setups where a VM is migrated from a host *without* commit ad856280ddea,
29 to a target with a subset of host-supported xfeatures. However there is
30 no way to safely address that scenario, e.g. KVM could silently drop the
31 unsupported features, but that would be a clear violation of KVM's ABI and
32 so would require userspace to opt-in, at which point userspace could
33 simply be updated to sanitize the to-be-loaded XSAVE state.
34
35 Reported-by: Tyler Stachecki <stachecki.tyler@gmail.com>
36 Closes: https://lore.kernel.org/all/20230914010003.358162-1-tstachecki@bloomberg.net
37 Fixes: ad856280ddea ("x86/kvm/fpu: Limit guest user_xfeatures to supported bits of XCR0")
38 Cc: stable@vger.kernel.org
39 Cc: Leonardo Bras <leobras@redhat.com>
40 Signed-off-by: Sean Christopherson <seanjc@google.com>
41 Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
42 Message-Id: <20230928001956.924301-3-seanjc@google.com>
43 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
44 (cherry picked from commit 8647c52e9504c99752a39f1d44f6268f82c40a5c)
45 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
46 ---
47 arch/x86/kernel/fpu/xstate.c | 5 +----
48 arch/x86/kvm/cpuid.c | 8 --------
49 arch/x86/kvm/x86.c | 18 ++++++++++++++++--
50 3 files changed, 17 insertions(+), 14 deletions(-)
51
52 diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
53 index 463ec0cd0dab..ebe698f8af73 100644
54 --- a/arch/x86/kernel/fpu/xstate.c
55 +++ b/arch/x86/kernel/fpu/xstate.c
56 @@ -1543,10 +1543,7 @@ static int fpstate_realloc(u64 xfeatures, unsigned int ksize,
57 fpregs_restore_userregs();
58
59 newfps->xfeatures = curfps->xfeatures | xfeatures;
60 -
61 - if (!guest_fpu)
62 - newfps->user_xfeatures = curfps->user_xfeatures | xfeatures;
63 -
64 + newfps->user_xfeatures = curfps->user_xfeatures | xfeatures;
65 newfps->xfd = curfps->xfd & ~xfeatures;
66
67 /* Do the final updates within the locked region */
68 diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
69 index 61aefeb3fdbc..e5393ee652ba 100644
70 --- a/arch/x86/kvm/cpuid.c
71 +++ b/arch/x86/kvm/cpuid.c
72 @@ -350,14 +350,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
73 vcpu->arch.guest_supported_xcr0 =
74 cpuid_get_supported_xcr0(vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent);
75
76 - /*
77 - * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
78 - * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
79 - * supported by the host.
80 - */
81 - vcpu->arch.guest_fpu.fpstate->user_xfeatures = vcpu->arch.guest_supported_xcr0 |
82 - XFEATURE_MASK_FPSSE;
83 -
84 kvm_update_pv_runtime(vcpu);
85
86 vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
87 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
88 index a43a950d04cb..a4a44adf7c72 100644
89 --- a/arch/x86/kvm/x86.c
90 +++ b/arch/x86/kvm/x86.c
91 @@ -5318,12 +5318,26 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
92 static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
93 u8 *state, unsigned int size)
94 {
95 + /*
96 + * Only copy state for features that are enabled for the guest. The
97 + * state itself isn't problematic, but setting bits in the header for
98 + * features that are supported in *this* host but not exposed to the
99 + * guest can result in KVM_SET_XSAVE failing when live migrating to a
100 + * compatible host without the features that are NOT exposed to the
101 + * guest.
102 + *
103 + * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
104 + * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
105 + * supported by the host.
106 + */
107 + u64 supported_xcr0 = vcpu->arch.guest_supported_xcr0 |
108 + XFEATURE_MASK_FPSSE;
109 +
110 if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
111 return;
112
113 fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size,
114 - vcpu->arch.guest_fpu.fpstate->user_xfeatures,
115 - vcpu->arch.pkru);
116 + supported_xcr0, vcpu->arch.pkru);
117 }
118
119 static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,