Re: [PATCH 09/10] x86/fpu: Allow restoring signal frames with larger xstate_size
From: Andrei Vagin
Date: Tue Jul 21 2026 - 21:13:57 EST
On Thu, Jul 9, 2026 at 2:15 PM Chang S. Bae <chang.seok.bae@xxxxxxxxx> wrote:
>
> On 7/7/2026 1:27 PM, Andrei Vagin wrote:
> >
> > With this changes, the kernel will correctly reject signals frames with
> > MPX states on APX machines and vise versa. If a signal frame contains an
> > MPX state, it will be rejected on an APX machine because XCR0 will lack
> > the MPX bits, causing XRSTOR to trigger a #GP. The exact same thing
> > happens if a signal frame containing an APX state is brought to an older
> > machine. XRSTOR explicitly triggers a #GP exception if a bit in XCR0 is
> > 0 but the corresponding bit in the xstate_bv field of the XSAVE header
> > is 1. This hardware enforcement occurs regardless of whether the target
> > bit is present in the requested-feature bitmap.
>
> Okay, in this regard, the interaction with XRSTOR in ring0 is ultimately
> what enforces the consistency check. Rather than trying to interpret the
> frame, let the kernel XRSTOR validate whether the image is migratable to
> the target or not. Perhaps, that's your perspective here all.
Yes, exactly. Regardless of this change, the kernel already relies on
XRSTOR to validate the actual state. check_xstate_in_sigframe() only
verifies that the extended state is present in the signal frame and
performs consistency checks on the fx_sw metadata, without validating
the xstate buffer contents itself.
>
> > Dynamic XSTATE components (like Intel AMX) require a process to
> > explicitly request permission via arch_prctl(ARCH_REQ_XCOMP_PERM, ...).
> > During the checkpoint, CRIU detects which dynamic features have been
> > enabled for each thread and saves this configuration as part of the
> > process image. During the restore, CRIU invokes arch_prctl() on threads
> > to request the identical dynamic XSTATE permissions. If the target
> > machine doesn't support a specific dynamic state, the restore will fail.
>
> The permission request itself does not expand a task's fpstate -- it
> does not reallocate a larger XSAVE buffer or update its size/xfeatures
> attributes.
>
> Assuming the target task has never touched the dynamic state, if
> fx_sw->xstate_size > fpstate->user_size is permitted, while
> fx_sw->xfeatures is still used directly as the XRSTOR RFBM, I think it
> may be possible to trigger an ugly #NM in the kernel along the way when
> CONFIG_X86_DEBUG_FPU=n. If CONFIG_X86_DEBUG_FPU=y, xfd_validate_state()
> could guard this by clearing the bit as part of its consistency check.
We never pass fx_sw->xfeatures directly to XRSTOR as the RFBM. In
__restore_fpregs_from_user(), the restore mask is explicitly restricted:
xrestore_mask &= fpu->fpstate->user_xfeatures;
>
> If the restore path manages the destination fpstate before XRSTOR
> somehow, then this dynamic satate example isn't the case of migrating
> from larger to smaller frames. But I guess what you wanted here was
> stretching the "try-and-see" migration model to cover learger-to-smaller
> xstate-size transitions as well.
>
> But again, from the kernel perspective, I feel this relaxation needs
> very careful review and auditing.
The kernel doesn't validate user xstate buffer contents. If there is a
concern that an unprivileged user could trigger in-kernel exceptions or
restore unexpected feature states, this change doesn't alter anything in
that regard.
ps: Sorry for the delay, I was on vacation.
Thanks,
Andrei