Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs

Sean Christopherson
2025-09-19T17:58:17Z

On Fri, Sep 19, 2025, Sean Christopherson wrote:
> On Tue, Sep 16, 2025, Xiaoyao Li wrote:
> > On 9/16/2025 6:12 AM, Sean Christopherson wrote:
> > > For 6.18, I think the safe play is to go with the first path (exempt KVM-internal
> > > MSRs), and then try to go for the second approach (exempt all host accesses) for
> > > 6.19. KVM's ABI for ignore_msrs=true is already all kinds of messed up, so I'm
> > > not terribly concerned about temporarily making it marginally worse.
> >
> > Looks OK to me.
>
> Actually, better idea. Just use kvm_msr_{read,write}() for ONE_REG and bypass
> the ignore_msrs crud. It's new uAPI, so we can define the semantics to be anything
> we want. I see zero reason for ignore_msrs to apply to host accesses, and even
> less reason for it to apply to ONE_REG.
>
> Then there's no need to special case GUEST_SSP, and what to do about ignore_msrs
> for host accesses remains an orthogonal discussion.
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 4ed25d33aaee..4adfece25630 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5932,7 +5932,7 @@ static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
> {
> u64 val;
>
> - if (do_get_msr(vcpu, msr, &val))
> + if (kvm_msr_read(vcpu, msr, &val))
> return -EINVAL;
>
> if (put_user(val, user_val))
> @@ -5948,7 +5948,7 @@ static int kvm_set_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
> if (get_user(val, user_val))
> return -EFAULT;
>
> - if (do_set_msr(vcpu, msr, &val))
> + if (kvm_msr_write(vcpu, msr, &val))
> return -EINVAL;
>
> return 0;

Never mind, that would cause problems for using ONE_REG for actual MSRs. Most
importantly, it would let userspace bypass the feature MSR restrictions in
do_set_msr().

I think the best option is to immediately reject translation. That way host
accesses to whatever KVM uses for the internal SSP MSR index are unaffected by
the introduction of ONE_REG support. E.g. modifying kvm_do_msr_access() would
mean that userspace would see different behavior for MSR_KVM_INTERNAL_GUEST_SSP
versus all other MSRs.

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ab7f8c41d93b..720540f102e1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6016,10 +6016,20 @@ struct kvm_x86_reg_id {
__u8 x86;
};

-static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg)
+static int kvm_translate_kvm_reg(struct kvm_vcpu *vcpu,
+ struct kvm_x86_reg_id *reg)
{
switch (reg->index) {
case KVM_REG_GUEST_SSP:
+ /*
+ * FIXME: If host-initiated accesses are ever exempted from
+ * ignore_msrs (in kvm_do_msr_access()), drop this manual check
+ * and rely on KVM's standard checks to reject accesses to regs
+ * that don't exist.
+ */
+ if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
+ return -EINVAL;
+
reg->type = KVM_X86_REG_TYPE_MSR;
reg->index = MSR_KVM_INTERNAL_GUEST_SSP;
break;
@@ -6075,7 +6085,7 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
return -EINVAL;

if (reg->type == KVM_X86_REG_TYPE_KVM) {
- r = kvm_translate_kvm_reg(reg);
+ r = kvm_translate_kvm_reg(vcpu, reg);
if (r)
return r;
}