uml: fix irqstack crash

This patch fixes a crash caused by an interrupt coming in when an IRQ stack
is being torn down. When this happens, handle_signal will loop, setting up
the IRQ stack again because the tearing down had finished, and handling
whatever signals had come in.

However, to_irq_stack returns a mask of pending signals to be handled, plus
bit zero is set if the IRQ stack was already active, and thus shouldn't be
torn down. This causes a problem because when handle_signal goes around
the loop, sig will be zero, and to_irq_stack will duly set bit zero in the
returned mask, faking handle_signal into believing that it shouldn't tear
down the IRQ stack and return thread_info pointers back to their original
values.

This will eventually cause a crash, as the IRQ stack thread_info will
continue pointing to the original task_struct and an interrupt will look
into it after it has been freed.

The fix is to stop passing a signal number into to_irq_stack. Rather, the
pending signals mask is initialized beforehand with the bit for sig already
set. References to sig in to_irq_stack can be replaced with references to
the mask.

[akpm@linux-foundation.org: use UL]
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Jeff Dike and committed by Linus Torvalds 508a9274 480eccf9

+7 -6
+1 -1
arch/um/include/kern_util.h
··· 117 117 118 118 extern void copy_sc(union uml_pt_regs *regs, void *from); 119 119 120 - unsigned long to_irq_stack(int sig, unsigned long *mask_out); 120 + extern unsigned long to_irq_stack(unsigned long *mask_out); 121 121 unsigned long from_irq_stack(int nested); 122 122 123 123 #endif
+4 -3
arch/um/kernel/irq.c
··· 518 518 519 519 static unsigned long pending_mask; 520 520 521 - unsigned long to_irq_stack(int sig, unsigned long *mask_out) 521 + unsigned long to_irq_stack(unsigned long *mask_out) 522 522 { 523 523 struct thread_info *ti; 524 524 unsigned long mask, old; 525 525 int nested; 526 526 527 - mask = xchg(&pending_mask, 1 << sig); 527 + mask = xchg(&pending_mask, *mask_out); 528 528 if(mask != 0){ 529 529 /* If any interrupts come in at this point, we want to 530 530 * make sure that their bits aren't lost by our ··· 534 534 * and pending_mask contains a bit for each interrupt 535 535 * that came in. 536 536 */ 537 - old = 1 << sig; 537 + old = *mask_out; 538 538 do { 539 539 old |= mask; 540 540 mask = xchg(&pending_mask, old); ··· 550 550 551 551 task = cpu_tasks[ti->cpu].task; 552 552 tti = task_thread_info(task); 553 + 553 554 *ti = *tti; 554 555 ti->real_thread = tti; 555 556 task->stack = ti;
+2 -2
arch/um/os-Linux/signal.c
··· 119 119 120 120 void handle_signal(int sig, struct sigcontext *sc) 121 121 { 122 - unsigned long pending = 0; 122 + unsigned long pending = 1UL << sig; 123 123 124 124 do { 125 125 int nested, bail; ··· 134 134 * have to return, and the upper handler will deal 135 135 * with this interrupt. 136 136 */ 137 - bail = to_irq_stack(sig, &pending); 137 + bail = to_irq_stack(&pending); 138 138 if(bail) 139 139 return; 140 140