[PATCH] Make math_state_restore() save and restore the interruptflag

From: Nate Eldredge
Date: Thu Jan 30 2014 - 17:02:11 EST


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 linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/