Re: [RFC PATCH v2] x86/arch_prctl: Add ARCH_SET_XCR0 to set XCR0 per-thread

From: Andy Lutomirski
Date: Tue Apr 07 2020 - 17:42:50 EST




> On Apr 7, 2020, at 1:21 PM, Dave Hansen <dave.hansen@xxxxxxxxx> wrote:
>
> ïOn 4/7/20 10:55 AM, Keno Fischer wrote:
>>> On Tue, Apr 7, 2020 at 12:27 PM Dave Hansen <dave.hansen@xxxxxxxxx> wrote:
>>>
>>>>> How does this work with things like xstateregs_[gs]et() where the format
>>>>> of the kernel buffer and thus the kernel XCR0 is exposed as part of our
>>>>> ABI? With this patch, wouldn't a debugger app see a state buffer that
>>>>> looks invalid?
>>>>
>>>> Since those operate on the in-kernel buffer of these, which
>>>> in this patch always uses the unmodified XCR0, ptracers
>>>> should not observe a difference.
>>>
>>> Those operate on *BOTH* kernel and userspace buffers. They copy between
>>> them. That's kinda the point. :)
>>
>> Right, what I meant was that in this patch the kernel level
>> xsaves that populates the struct fpu always runs with
>> an unmodified XCR0, so the contents of the xsave area
>> in struct fpu does not change layout (this is the major
>> change in this patch over v1).
>
> The userspace buffer is... a userspace buffer. It is not and should not
> be tied to the format of the kernel buffer.
>
>> Are you referring to a ptracer which runs with a modified XCR0, and
>> assumes that the value it gets back from ptrace will have an
>> XSTATE_BV equal to its own observed XCR0 and thus get confused about
>> the layout of the buffer (or potentially have not copied all of the
>> relevant xstate because it calculated a wrong buffer size)?
>
> I don't think it's insane for a process to assume that it can XRSTOR a
> buffer that it gets back from ptrace. That seems like something that
> could clearly be an ABI that apps depend on.
>
> Also, let's look at the comment about where XCR0 shows up in the ABI
> (arch/x86/include/asm/user.h):
>
>> * For now, only the first 8 bytes of the software usable bytes[464..471] will
>> * be used and will be set to OS enabled xstate mask (which is same as the
>> * 64bit mask returned by the xgetbv's xCR0).
>
> That also makes it sound like we expect there to be a *SINGLE* value
> across the entire system. It also makes me wonder *which* xgetbv is
> expected to match USER_XSTATE_XCR0_WORD. It can't be the ptracee since
> we expect them to change XCR0. It can't be the ptracer because they can
> use this new prctl too. So does it refer to the kernel? Or, should the
> new prctl() *disable* future ptrace()s?
>
>> If so, I think that's just a buggy ptracer. The kernel's xfeature
>> mask is available via ptrace and a well-behaved ptracer should use
>> that (e.g. gdb does, though it looks like it then also assumes that
>> the xstate has no holes, so it potentially gets the layout wrong
>> anyway).
>
> I'm trying to figure out what the semantics are of this whole thing. It
> can't be "don't let userspace observe the real XCR0" because ptrace
> exposes that. Is it, "make memory images portable, unless it's a memory
> image from ptrace"?
>
>> In general, I don't really want the modified XCR0 to affect
>> anything other than the particular instructions that depend
>> on it and maybe the signal frame (though as I said before,
>> I'm open to either here).
>
> Just remember that, in the end, we don't get to say what a good ptracer
> or bad ptracer is. If they're expecting semantics that we've kept
> constant for 10 years, we change the semantics, and the app breaks, the
> kernel is in the wrong.
>
> I also don't feel like I have a good handle on what ptracers *do* with
> their XSAVE buffers that they get/set. How many apps in a distro do
> something with this interface?

Most of them treat it as bytes to be blindly stuck back into the tracee. Some of them will display some registers for the userâs benefit. Maybe a couple that I donât know about do something odd.