aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Ivanov <aivanov@brocade.com>2015-12-21 06:28:02 -0500
committerRichard Weinberger <richard@nod.at>2016-01-10 15:49:47 -0500
commitd5e3f5cbe5cee7fe6da26566559a978547179b37 (patch)
tree7f40e2da3a070e811a412865ffbf5c317844e257
parent0754fb298f2f2719f0393491d010d46cfb25d043 (diff)
um: Prevent IRQ handler reentrancy
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>
-rw-r--r--arch/um/os-Linux/signal.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c211153ca69a..7801666514ed 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
62 62
63static int signals_enabled; 63static int signals_enabled;
64static unsigned int signals_pending; 64static unsigned int signals_pending;
65static unsigned int signals_active = 0;
65 66
66void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) 67void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
67{ 68{
@@ -101,7 +102,12 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
101 102
102 block_signals(); 103 block_signals();
103 104
105 signals_active |= SIGALRM_MASK;
106
104 timer_real_alarm_handler(mc); 107 timer_real_alarm_handler(mc);
108
109 signals_active &= ~SIGALRM_MASK;
110
105 set_signals(enabled); 111 set_signals(enabled);
106} 112}
107 113
@@ -286,8 +292,16 @@ void unblock_signals(void)
286 if (save_pending & SIGIO_MASK) 292 if (save_pending & SIGIO_MASK)
287 sig_handler_common(SIGIO, NULL, NULL); 293 sig_handler_common(SIGIO, NULL, NULL);
288 294
289 if (save_pending & SIGALRM_MASK) 295 /* Do not reenter the handler */
296
297 if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
290 timer_real_alarm_handler(NULL); 298 timer_real_alarm_handler(NULL);
299
300 /* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
301
302 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
303 return;
304
291 } 305 }
292} 306}
293 307