From: Nate Eldredge <nate@xxxxxxxxxxxxxxxxxxxx> Make math_state_restore() save and restore the interrupt flag, rather than always disabling interrupts. If math_state_restore() is called in a task that has not used math, it needs to allocate some memory (via init_fpu()). Since this can sleep, it enables interrupts first. Currently, it always disables them afterwards, regardless of whether or not they were enabled on entry. (See commit aa283f4927 where this was introduced.) This doesn't make sense, so instead have it put interrupts back the way they were. This is the cause of Ubuntu bug #1265841 (https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1265841): if a user process dumps core on an ecrypt fs while aesni-intel is loaded, we get a BUG() in __find_get_block() complaining that it was called with interrupts disabled; then all further accesses to our ecrypt fs hang and we have to reboot. The aesni-intel code (encrypting the core file that we are writing) needs the FPU and quite properly wraps its code in kernel_fpu_{begin,end}(), the latter of which calls math_state_restore(). So after kernel_fpu_end(), interrupts may be disabled, which nobody seems to expect, and they stay that way until we eventually get to __find_get_block() which barfs. With this patch, the testcase works fine and no BUG() is triggered. math_state_restore() may need further review, as it still seems suspicious that it can unilaterally enable interupts for itself. It's not clear to me what are the intended semantics of math_state_restore() and kernel_fpu_{begin,end}() with respect to interrupts. Nevertheless, this patch should be appropriate for now. Signed-off-by: Nate Eldredge <nate@xxxxxxxxxxxxxxxxxxxx> Tested-by: George Spelvin <linux@xxxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> Fixes: aa283f4927 --- Applies to linux-3.13. Previous discussion in linux-kernel thread "math_state_restore and kernel_fpu_end disable interrupts?" diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b857ed8..09df67d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -628,6 +628,9 @@ void math_state_restore(void) struct task_struct *tsk = current; if (!tsk_used_math(tsk)) { + unsigned long flags; + + local_save_flags(flags); local_irq_enable(); /* * does a slab alloc which can sleep @@ -639,7 +642,7 @@ void math_state_restore(void) do_group_exit(SIGKILL); return; } - local_irq_disable(); + local_irq_restore(flags); } __thread_fpu_begin(tsk); -- Nate Eldredge nate@xxxxxxxxxxxxxxxxxxxx -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html