[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <87v87lebyt.ffs@tglx>
Date: Mon, 22 Jan 2024 14:26:02 +0100
From: Thomas Gleixner <tglx@...utronix.de>
To: Andrei Vagin <avagin@...il.com>
Cc: Dave Hansen <dave.hansen@...el.com>, Andrei Vagin <avagin@...gle.com>,
Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>, Dave
Hansen <dave.hansen@...ux.intel.com>, LKML <linux-kernel@...r.kernel.org>,
x86@...nel.org, "H. Peter Anvin" <hpa@...or.com>
Subject: Re: [PATCH] x86/fpu: verify xstate buffer size according with
requested features
On Sun, Jan 21 2024 at 19:58, Andrei Vagin wrote:
> On Thu, Jan 18, 2024 at 2:11 PM Thomas Gleixner <tglx@...utronix.de> wrote:
>> >> After staring more at it, it's arguable to pass fpstate->user_size to
>> >> fault_in_readable() and ignore fx_sw->xstate_size completely.
>> >>
>> >> That's a guaranteed to be reliable size which prevents endless loops
>> >> because arguably that's the maximum size which can be touched by XRSTOR,
>> >> no?
>
> fpstate->user_size isn't constant. It can be modified from the XFD #NM
> handler. For example, it happens when a process invokes one of amx
> instructions for the first time. It means we have to be able to restore
> an fpu state from signal frames generated with a smaller
> fpstate->user_size. Can it trigger any issues?
I know, but the #NM handler does not run in the signal restore
path. fpstate->user_size is guaranteed to be correct at that point.
The untested below should just work.
Thanks,
tglx
---
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -274,8 +274,7 @@ static int __restore_fpregs_from_user(vo
* Attempt to restore the FPU registers directly from user memory.
* Pagefaults are handled and any errors returned are fatal.
*/
-static bool restore_fpregs_from_user(void __user *buf, u64 xrestore,
- bool fx_only, unsigned int size)
+static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, bool fx_only)
{
struct fpu *fpu = ¤t->thread.fpu;
int ret;
@@ -309,7 +308,7 @@ static bool restore_fpregs_from_user(voi
if (ret != X86_TRAP_PF)
return false;
- if (!fault_in_readable(buf, size))
+ if (!fault_in_readable(buf, fpu->fpstate->user_size))
goto retry;
return false;
}
@@ -339,7 +338,6 @@ static bool __fpu_restore_sig(void __use
struct user_i387_ia32_struct env;
bool success, fx_only = false;
union fpregs_state *fpregs;
- unsigned int state_size;
u64 user_xfeatures = 0;
if (use_xsave()) {
@@ -349,17 +347,14 @@ static bool __fpu_restore_sig(void __use
return false;
fx_only = !fx_sw_user.magic1;
- state_size = fx_sw_user.xstate_size;
user_xfeatures = fx_sw_user.xfeatures;
} else {
user_xfeatures = XFEATURE_MASK_FPSSE;
- state_size = fpu->fpstate->user_size;
}
if (likely(!ia32_fxstate)) {
/* Restore the FPU registers directly from user memory. */
- return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only,
- state_size);
+ return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only);
}
/*
Powered by blists - more mailing lists