mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-13 01:08:50 +00:00
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>
This commit is contained in:
parent
0754fb298f
commit
d5e3f5cbe5
@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
|
|||||||
|
|
||||||
static int signals_enabled;
|
static int signals_enabled;
|
||||||
static unsigned int signals_pending;
|
static unsigned int signals_pending;
|
||||||
|
static unsigned int signals_active = 0;
|
||||||
|
|
||||||
void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
|
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();
|
block_signals();
|
||||||
|
|
||||||
|
signals_active |= SIGALRM_MASK;
|
||||||
|
|
||||||
timer_real_alarm_handler(mc);
|
timer_real_alarm_handler(mc);
|
||||||
|
|
||||||
|
signals_active &= ~SIGALRM_MASK;
|
||||||
|
|
||||||
set_signals(enabled);
|
set_signals(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,8 +292,16 @@ void unblock_signals(void)
|
|||||||
if (save_pending & SIGIO_MASK)
|
if (save_pending & SIGIO_MASK)
|
||||||
sig_handler_common(SIGIO, NULL, NULL);
|
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);
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user