Re: [RESEND PATCH v6 1/2] x86/fpu: Allow PKRU to be (once again) written by ptrace.

From: Dave Hansen
Date: Thu Nov 10 2022 - 20:38:04 EST


On 11/10/22 16:03, Kyle Huey wrote:
> On Tue, Nov 8, 2022 at 10:23 AM Dave Hansen <dave.hansen@xxxxxxxxx> wrote:
...
>> At a high level, this patch does a *LOT*. Generally, it's nice when
>> bugfixes can be encapsulted in one patch, but I think there's too much
>> going on here for one patch.
>
> Ok. How about I break the first part into two pieces, one that changes the
> signatures of copy_uabi_from_kernel_to_xstate() and
> copy_sigframe_from_user_to_xstate(), and one that moves the relevant
> KVM code from fpu_copy_uabi_to_guest_fpstate() to copy_uabi_to_xstate()
> and deals with the edge case behavior of the mask?

Sounds like a good start. My gut says there's another patch or two that
could be broken out, but that sounds like a reasonable next step.

>>> diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
>>> index 3b28c5b25e12..c273669e8a00 100644
>>> --- a/arch/x86/kernel/fpu/core.c
>>> +++ b/arch/x86/kernel/fpu/core.c
>>> @@ -391,8 +391,6 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
>>> {
>>> struct fpstate *kstate = gfpu->fpstate;
>>> const union fpregs_state *ustate = buf;
>>> - struct pkru_state *xpkru;
>>> - int ret;
>>>
>>> if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) {
>>> if (ustate->xsave.header.xfeatures & ~XFEATURE_MASK_FPSSE)
>>> @@ -406,16 +404,16 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
>>> if (ustate->xsave.header.xfeatures & ~xcr0)
>>> return -EINVAL;
>>>
>>> - ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
>>> - if (ret)
>>> - return ret;
>>> + /*
>>> + * Nullify @vpkru to preserve its current value if PKRU's bit isn't set
>>> + * in the header. KVM's odd ABI is to leave PKRU untouched in this
>>> + * case (all other components are eventually re-initialized).
>>> + * (Not clear that this is actually necessary for compat).
>>> + */
>>> + if (!(ustate->xsave.header.xfeatures & XFEATURE_MASK_PKRU))
>>> + vpkru = NULL;
>>
>> I'm not a big fan of hunks that are part of bugfixes where it is not
>> clear that the hunk is necessary.
>
> This is necessary to avoid changing KVM's behavior at the same time
> that we change
> ptrace, since KVM doesn't want the same behavior as ptrace.

Your "This is necessary" doesn't really match with "Not clear that this
is actually necessary" from the comment, right?

Rather than claim whether it is necessary or not, maybe just say why
it's there: it's there to preserve wonky KVM behavior.

BTW, I'd love to know if KVM *REALLY* depends on this. It'd be nice to
kill if not.
>> Would something like this be more clear?
>>
>> if (hdr.xfeatures & XFEATURE_MASK_PKRU) {
>> struct pkru_state *xpkru;
>>
>> xpkru = __raw_xsave_addr(xsave, XFEATURE_PKRU);
>> *pkru = xpkru->pkru;
>> } else {
>> /*
>> * KVM may pass a NULL 'pkru' to indicate
>> * that it does not need PKRU updated.
>> */
>> if (pkru)
>> *pkru = 0;
>> }
>
> Yeah, Sean Christopherson suggested this (with the else and if
> collapsed into a single level) when I submitted this previously.

I generally agree with Sean, but he's also been guilty of an atrocity or
two over the years. :) While I generally like low levels of
indentation I also think my version is much more clear in this case.