Re: [PATCH 09/10] x86/fpu: Allow restoring signal frames with larger xstate_size
From: Chang S. Bae
Date: Mon Jul 06 2026 - 13:22:59 EST
On 6/30/2026 5:48 PM, Andrei Vagin wrote:
In our previous discussion, I explained why the state translation
approach doesn't solve the problem: in-flight signal frames on user
stacks cannot be translated. When a process is checkpointed while
handling a signal, there is an in-flight signal frame residing directly
on the thread's user stack. There is no way for userspace tools to
reliably discover arbitrary in-flight signal frames embedded in stack
memory.
We want to support cases where processes using only cluster-wide
available features can be migrated from newer to older CPUs. If we
migrate from a newer CPU (larger default `user_size`) to an older CPU
(smaller `user_size`), enforcing `xstate_size <= fpstate->user_size` in
the kernel unconditionally rejects valid signal frames.
An fpu translation mechanism already exists in CRIU to restore current
per-thread FPU states, making it possible to migrate workloads between
different CPUs even today. But there is always a risk that a process is
migrated at the wrong moment (while running inside a signal handler).
Without this change, failing the size check on that in-flight stack
frame can trigger a state corruption. This patch eliminates that risk.
So if I understand correctly, the intended usage model is a cluster of machines exposing a compatible set of xfeatures. Migration may occur in either direction (old -> new or new -> old), and the process image, including any inflight signal frames, is copied verbatim because interpreting or translating arbitrary signal frame is either impossible or at least not reliable.
With APX, userspace can no longer assume that a higher XSTATE component
number implies a higher offset within the XSAVE image. Going forward,
migration software will likely need a more robust approach that
interprets the layout and transforms the image when moving between
machines with different layouts. With such translation, maybe further
relaxing the kernel-side checker isn't that needed.
I think APX was designed to preserve backward compatibility cleanly. And
I don't think that we rely on the assumption that a higher XSTATE component
number implies a higher offset within the XSAVE image.
`xstate_calculate_size()` already finds the topmost feature by offset. The
only reason the kernel needs to know the required xstate size is to
correctly pre-fault the user memory buffer.
While APX reuses the MPX space in the xsave state, it introduces a new
feature bit to indicate the presence of its state, which is really what
matters. The actual register state that gets restored depends on
`task_xfeatures` and the header's `xstate_bv`. Any attempt by XRSTOR to
restore a header containing unsupported feature bits in xstate_bv
generates a GP fault. This cleanly traps in restore_fpregs_from_user()
and fails out, triggering a SIGSEGV.
IIUC, this works because the migration pool is already constrained to architecturally compatible machines. In particular, APX systems would not be mixed with older MPX systems. Otherwise, while with a distinguishing feature bit though, the layout is still ambiguous without interpreting signal frames.
I completely understand that some features may be deprecated in the
future, but I still believe that for non-deprecated features, component
offsets should be fixed across all CPUs within a vendor's family. If
this assumption is ever broken, even standard KVM live migration of
guest vCPUs would break.
Sorry if I missed something. Maybe you can give an example of when
this change would work against us?
With dynamic XSTATE, suppose a take has opted into a dynamic state and therefore carries a larger xstate_size, but it is migrated to another machine where the corresponding dynamic permission has not been requested. Since, according to the usage model, reliable interpretation of arbitrary signal frames is not possible, I assume the migration framework does not inspect each individual state to determine whether this is still in its init state or not.
If that's the case, is there a possibility that meaningful dynamic state could be lost during migration?
More generally, if ever reconsidering the kernel's sanity checking, one concern I still have with this change is validation in the presence of unknown future feature bits. This series does not run into that problem in practice though.
Thanks,
Chang