xsave: fix error condition in save_i387_xstate()
PATCH 1/2 xsave: fix error condition in save_i387_xstate()
---
arch/x86/kernel/xsave.c +2 -0
@@ -121,6 +121,8 @@ err |=__put_user (FP_XSTATE_MAGIC2 , (__u32 __user *) (buf + sig_xstate_size -FP_XSTATE_MAGIC2_SIZE )); +if (err) +return err; }return 1 ;
PATCH 2/2 xsave: set FP, SSE bits in the xsave header in the user sigcontext
If a processor implementation discern that a processor state component is in its initialized state, it may modify the corresponding bit in the xsave header.xstate_bv as '0'. State in the memory layout setup by 'xsave' will be consistent with the bit values in the header.
During signal handling, legacy applications may change the FP/SSE bits in the sigcontext memory layout without touching the FP/SSE header bits in the xsave header. So always set FP/SSE bits in the xsave header while saving the sigcontext state to the user space. During signal return, this will enable the kernel to capture any changes to the FP/SSE bits by the legacy applications which don't touch xsave headers.
xsave aware apps can change the xstate_bv in the xsave header aswell as change any contents in the memory layout. xrestor as part of sigreturn will capture all the changes.
---
arch/x86/kernel/xsave.c +25 -0
@@ -114,6 +114,8 @@if (task_thread_info (tsk)->status &TS_XSAVE ) {struct _fpstate __user *fx = buf; +struct _xstate __user *x = buf; +u64 xstate_bv; err =__copy_to_user (&fx->sw_reserved, &fx_sw_reserved,sizeof (struct _fpx_sw_bytes ));
@@ -121,6 +123,29 @@ err |=__put_user (FP_XSTATE_MAGIC2 , (__u32 __user *) (buf + sig_xstate_size -FP_XSTATE_MAGIC2_SIZE )); + +/* +* Read the xstate_bv which we copied (directly from the cpu or +* from the state in task struct) to the user buffers and +* set the FP/SSE bits. +*/ + err |=__get_user (xstate_bv, &x->xstate_hdr.xstate_bv); + +/* +* For legacy compatible, we always set FP/SSE bits in the bit +* vector while saving the state to the user context. This will +* enable us capturing any changes(during sigreturn) to +* the FP/SSE bits by the legacy applications which don't touch +* xstate_bv in the xsave header. +* +* xsave aware apps can change the xstate_bv in the xsave +* header as well as change any contents in the memory layout. +* xrestore as part of sigreturn will capture all the changes. +*/ + xstate_bv |=XSTATE_FPSSE ; + + err |=__put_user (xstate_bv, &x->xstate_hdr.xstate_bv); +if (err)return err; }
arch/x86/kernel/i387.c +14 -0
@@ -468,9 +468,23 @@static int save_i387_xsave (void __user *buf) { +struct task_struct *tsk = current;struct _fpstate_ia32 __user *fx = buf;int err =0 ; +/* +* For legacy compatible, we always set FP/SSE bits in the bit +* vector while saving the state to the user context. +* This will enable us capturing any changes(during sigreturn) to +* the FP/SSE bits by the legacy applications which don't touch +* xstate_bv in the xsave header. +* +* xsave aware applications can change the xstate_bv in the xsave +* header as well as change any contents in the memory layout. +* xrestore as part of sigreturn will capture all the changes. +*/ + tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |=XSTATE_FPSSE ; +if (save_i387_fxsave (fx) <0 )return -1 ;
H. Peter Anvin
reviewerSeries applied to tip:x86/xsave, thanks!
-hpa