Re: [PATCH v10 13/28] x86/fpu/xstate: Use feature disable (XFD) to protect dynamic user state
From: Thomas Gleixner
Date: Fri Oct 01 2021 - 11:10:28 EST
On Fri, Oct 01 2021 at 17:02, Thomas Gleixner wrote:
> On Wed, Aug 25 2021 at 08:53, Chang S. Bae wrote:
>> DEFINE_IDTENTRY(exc_device_not_available)
>> {
>> unsigned long cr0 = read_cr0();
>
>> + if (handle_xfd_event(¤t->thread.fpu, regs))
>> + return;
>
> As I said before, this is wrong because at that point interrupts are disabled.
So you want something like this:
static bool handle_xfd_event(struct pt_regs *regs)
{
u64 xfd_err, xfd_event, xfd, mask;
struct fpu *fpu;
if (!cpu_feature_enabled(X86_FEATURE_XFD))
return false;
rdmsrl_safe(MSR_IA32_XFD_ERR, &xfd_err);
if (!xfd_err)
return false;
wrmsrl_safe(MSR_IA32_XFD_ERR, 0);
xfd_event = xfd_err & xfeatures_mask_user_dynamic;
/* Die if a non-handled feature raised the exception */
if (WARN_ON(!xfd_event))
return true;
/* Die if that happens in kernel space */
if (WARN_ON(!user_mode(regs)))
return false;
local_irq_enable();
/* Make sure that dynamic buffer expansion is permitted. */
if (dynamic_state_permitted(current, xfd_event) &&
!realloc_xstate_buffer(current, xfd_event)) {
mask = xfeatures_mask_user_dynamic;
fpu = ¤t->thread.fpu;
xfd_write((fpu->state_mask & mask) ^ mask);
} else {
force_sig_fault(SIGILL, ILL_ILLOPC, error_get_trap_addr(regs));
}
local_irq_disable();
return true;
}
Along with a correct implementation of realloc_xstate_buffer().
Thanks,
tglx