Suresh Siddha 06c38d5e36 x86-64: fix FPU corruption with signals and preemption
In 64bit signal delivery path, clear_used_math() was happening before saving
the current active FPU state on to the user stack for signal handling. Between
clear_used_math() and the state store on to the user stack, potentially we
can get a page fault for the user address and can block. Infact, while testing
we were hitting the might_fault() in __clear_user() which can do a schedule().

At a later point in time, we will schedule back into this process and
resume the save state (using "xsave/fxsave" instruction) which can lead
to DNA fault. And as used_math was cleared before, we will reinit the FP state
in the DNA fault and continue. This reinit will result in loosing the
FPU state of the process.

Move clear_used_math() to a point after the FPU state has been stored
onto the user stack.

This issue is present from a long time (even before the xsave changes
and the x86 merge). But it can easily be exposed in 2.6.28.x and 2.6.29.x
series because of the __clear_user() in this path, which has an explicit
__cond_resched() leading to a context switch with CONFIG_PREEMPT_VOLUNTARY.

[ Impact: fix FPU state corruption ]

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: <stable@kernel.org>			[2.6.28.x, 2.6.29.x]
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2009-04-20 14:33:00 -07:00
..
2009-04-05 02:14:15 -04:00
2009-04-20 18:09:18 +02:00
2009-03-15 07:03:15 +01:00
2008-12-12 11:08:42 +01:00
2009-02-10 13:13:23 +01:00
2009-03-21 16:56:10 +05:30
2009-02-23 00:08:11 +01:00
2008-12-31 18:07:42 -05:00
2009-03-21 16:57:04 +05:30
2009-02-09 12:16:05 +01:00
2009-03-21 16:55:45 +05:30
2009-02-17 17:52:44 +01:00
2009-02-23 00:08:11 +01:00
2009-01-02 17:46:24 +01:00
2009-02-23 00:08:11 +01:00
2009-03-18 13:51:17 +01:00
2009-03-18 13:51:17 +01:00
2009-01-12 11:22:50 +01:00
2009-01-20 17:14:28 +01:00
2009-04-02 19:04:51 -07:00
2009-04-02 19:04:51 -07:00
2009-03-28 22:27:45 +01:00
2009-03-21 16:56:37 +05:30
2009-02-17 17:52:44 +01:00
2009-01-31 04:21:18 +01:00
2008-07-16 12:15:17 -07:00
2008-07-22 14:35:57 +02:00
2008-10-22 22:55:23 -07:00
2009-02-23 00:08:11 +01:00
2008-07-22 14:35:57 +02:00
2009-03-21 16:55:24 +05:30
2009-02-17 17:52:44 +01:00