Skip to content

Commit 53599b4

Browse files
ChangSeokBaesuryasaimadhu
authored andcommitted
x86/fpu/signal: Prepare for variable sigframe length
The software reserved portion of the fxsave frame in the signal frame is copied from structures which have been set up at boot time. With dynamically enabled features the content of these structures is no longer correct because the xfeatures and size can be different per task. Calculate the software reserved portion at runtime and fill in the xfeatures and size values from the tasks active fpstate. Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 4b7ca60 commit 53599b4

File tree

3 files changed

+26
-40
lines changed

3 files changed

+26
-40
lines changed

arch/x86/kernel/fpu/internal.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ static __always_inline __pure bool use_fxsr(void)
2121
# define WARN_ON_FPU(x) ({ (void)(x); 0; })
2222
#endif
2323

24-
/* Init functions */
25-
extern void fpu__init_prepare_fx_sw_frame(void);
26-
2724
/* Used in init.c */
2825
extern void fpstate_init_user(struct fpstate *fpstate);
2926
extern void fpstate_reset(struct fpu *fpu);

arch/x86/kernel/fpu/signal.c

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
#include "legacy.h"
2121
#include "xstate.h"
2222

23-
static struct _fpx_sw_bytes fx_sw_reserved __ro_after_init;
24-
static struct _fpx_sw_bytes fx_sw_reserved_ia32 __ro_after_init;
25-
2623
/*
2724
* Check for the presence of extended state information in the
2825
* user fpstate pointer in the sigcontext.
@@ -98,23 +95,42 @@ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf)
9895
return true;
9996
}
10097

98+
/*
99+
* Prepare the SW reserved portion of the fxsave memory layout, indicating
100+
* the presence of the extended state information in the memory layout
101+
* pointed to by the fpstate pointer in the sigcontext.
102+
* This is saved when ever the FP and extended state context is
103+
* saved on the user stack during the signal handler delivery to the user.
104+
*/
105+
static inline void save_sw_bytes(struct _fpx_sw_bytes *sw_bytes, bool ia32_frame,
106+
struct fpstate *fpstate)
107+
{
108+
sw_bytes->magic1 = FP_XSTATE_MAGIC1;
109+
sw_bytes->extended_size = fpstate->user_size + FP_XSTATE_MAGIC2_SIZE;
110+
sw_bytes->xfeatures = fpstate->user_xfeatures;
111+
sw_bytes->xstate_size = fpstate->user_size;
112+
113+
if (ia32_frame)
114+
sw_bytes->extended_size += sizeof(struct fregs_state);
115+
}
116+
101117
static inline bool save_xstate_epilog(void __user *buf, int ia32_frame,
102-
unsigned int usize)
118+
struct fpstate *fpstate)
103119
{
104120
struct xregs_state __user *x = buf;
105-
struct _fpx_sw_bytes *sw_bytes;
121+
struct _fpx_sw_bytes sw_bytes;
106122
u32 xfeatures;
107123
int err;
108124

109125
/* Setup the bytes not touched by the [f]xsave and reserved for SW. */
110-
sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved;
111-
err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes));
126+
save_sw_bytes(&sw_bytes, ia32_frame, fpstate);
127+
err = __copy_to_user(&x->i387.sw_reserved, &sw_bytes, sizeof(sw_bytes));
112128

113129
if (!use_xsave())
114130
return !err;
115131

116132
err |= __put_user(FP_XSTATE_MAGIC2,
117-
(__u32 __user *)(buf + usize));
133+
(__u32 __user *)(buf + fpstate->user_size));
118134

119135
/*
120136
* Read the xfeatures which we copied (directly from the cpu or
@@ -173,7 +189,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
173189
{
174190
struct task_struct *tsk = current;
175191
struct fpstate *fpstate = tsk->thread.fpu.fpstate;
176-
int ia32_fxstate = (buf != buf_fx);
192+
bool ia32_fxstate = (buf != buf_fx);
177193
int ret;
178194

179195
ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) ||
@@ -226,8 +242,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
226242
if ((ia32_fxstate || !use_fxsr()) && !save_fsave_header(tsk, buf))
227243
return false;
228244

229-
if (use_fxsr() &&
230-
!save_xstate_epilog(buf_fx, ia32_fxstate, fpstate->user_size))
245+
if (use_fxsr() && !save_xstate_epilog(buf_fx, ia32_fxstate, fpstate))
231246
return false;
232247

233248
return true;
@@ -523,28 +538,3 @@ unsigned long __init fpu__get_fpstate_size(void)
523538
return ret;
524539
}
525540

526-
/*
527-
* Prepare the SW reserved portion of the fxsave memory layout, indicating
528-
* the presence of the extended state information in the memory layout
529-
* pointed by the fpstate pointer in the sigcontext.
530-
* This will be saved when ever the FP and extended state context is
531-
* saved on the user stack during the signal handler delivery to the user.
532-
*/
533-
void __init fpu__init_prepare_fx_sw_frame(void)
534-
{
535-
int size = fpu_user_cfg.default_size + FP_XSTATE_MAGIC2_SIZE;
536-
537-
fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
538-
fx_sw_reserved.extended_size = size;
539-
fx_sw_reserved.xfeatures = fpu_user_cfg.default_features;
540-
fx_sw_reserved.xstate_size = fpu_user_cfg.default_size;
541-
542-
if (IS_ENABLED(CONFIG_IA32_EMULATION) ||
543-
IS_ENABLED(CONFIG_X86_32)) {
544-
int fsave_header_size = sizeof(struct fregs_state);
545-
546-
fx_sw_reserved_ia32 = fx_sw_reserved;
547-
fx_sw_reserved_ia32.extended_size = size + fsave_header_size;
548-
}
549-
}
550-

arch/x86/kernel/fpu/xstate.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,6 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
830830
update_regset_xstate_info(fpu_user_cfg.max_size,
831831
fpu_user_cfg.max_features);
832832

833-
fpu__init_prepare_fx_sw_frame();
834833
setup_init_fpu_buf();
835834
setup_xstate_comp_offsets();
836835
setup_supervisor_only_offsets();

0 commit comments

Comments
 (0)