um: Prevent IRQ handler reentrancy
authorAnton Ivanov <aivanov@brocade.com>
Mon, 21 Dec 2015 11:28:02 +0000 (11:28 +0000)
committerRichard Weinberger <richard@nod.at>
Sun, 10 Jan 2016 20:49:47 +0000 (21:49 +0100)
The existing IRQ handler design in UML does not prevent reentrancy

This is mitigated by fd-enable/fd-disable semantics for the IO
portion of the UML subsystem. The timer, however, can and is
re-entered resulting in very deep stack usage and occasional
stack exhaustion.

This patch prevents this by checking if there is a timer
interrupt in-flight before processing any pending timer interrupts.

Signed-off-by: Anton Ivanov <aivanov@brocade.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
arch/um/os-Linux/signal.c

index c211153ca69a18f95d74cd6661ecffcb91e270bb..7801666514ed60a83fd28618f6886981b0e77167 100644 (file)
@@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
 
 static int signals_enabled;
 static unsigned int signals_pending;
+static unsigned int signals_active = 0;
 
 void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
 {
@@ -101,7 +102,12 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
 
        block_signals();
 
+       signals_active |= SIGALRM_MASK;
+
        timer_real_alarm_handler(mc);
+
+       signals_active &= ~SIGALRM_MASK;
+
        set_signals(enabled);
 }
 
@@ -286,8 +292,16 @@ void unblock_signals(void)
                if (save_pending & SIGIO_MASK)
                        sig_handler_common(SIGIO, NULL, NULL);
 
-               if (save_pending & SIGALRM_MASK)
+               /* Do not reenter the handler */
+
+               if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
                        timer_real_alarm_handler(NULL);
+
+               /* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
+
+               if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
+                       return;
+
        }
 }