Fix kern/39769: race condition in TCP timers
When a TCP timer is disarmed (with callout_stop()) in the general case callout_invoking() isn't checked, so the timer handler could be called run when the current interrupt handler exits, athough the timer is disarmed. This case cause bad things like TCPT_REXMT and TCPT_PERSIST being both pending, causing a panic (see the PR for details). Close the issue by aborting the handler if the timer is not callout_expired(). (the EXPIRED flag being cleared by callout_stop()).
This commit is contained in:
parent
3ab32a0a5e
commit
71d4948e50
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: tcp_timer.c,v 1.82 2008/10/10 10:21:05 ad Exp $ */
|
/* $NetBSD: tcp_timer.c,v 1.83 2008/11/09 17:32:38 bouyer Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.82 2008/10/10 10:21:05 ad Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: tcp_timer.c,v 1.83 2008/11/09 17:32:38 bouyer Exp $");
|
||||||
|
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
#include "opt_tcp_debug.h"
|
#include "opt_tcp_debug.h"
|
||||||
|
@ -212,6 +212,10 @@ tcp_delack(void *arg)
|
||||||
mutex_exit(softnet_lock);
|
mutex_exit(softnet_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!callout_expired(&tp->t_delack_ch)) {
|
||||||
|
mutex_exit(softnet_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tp->t_flags |= TF_ACKNOW;
|
tp->t_flags |= TF_ACKNOW;
|
||||||
KERNEL_LOCK(1, NULL);
|
KERNEL_LOCK(1, NULL);
|
||||||
|
@ -271,6 +275,10 @@ tcp_timer_rexmt(void *arg)
|
||||||
mutex_exit(softnet_lock);
|
mutex_exit(softnet_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!callout_expired(&tp->t_timer[TCPT_REXMT])) {
|
||||||
|
mutex_exit(softnet_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KERNEL_LOCK(1, NULL);
|
KERNEL_LOCK(1, NULL);
|
||||||
if ((tp->t_flags & TF_PMTUD_PEND) && tp->t_inpcb &&
|
if ((tp->t_flags & TF_PMTUD_PEND) && tp->t_inpcb &&
|
||||||
|
@ -428,6 +436,10 @@ tcp_timer_persist(void *arg)
|
||||||
mutex_exit(softnet_lock);
|
mutex_exit(softnet_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!callout_expired(&tp->t_timer[TCPT_PERSIST])) {
|
||||||
|
mutex_exit(softnet_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KERNEL_LOCK(1, NULL);
|
KERNEL_LOCK(1, NULL);
|
||||||
#ifdef TCP_DEBUG
|
#ifdef TCP_DEBUG
|
||||||
|
@ -495,6 +507,10 @@ tcp_timer_keep(void *arg)
|
||||||
mutex_exit(softnet_lock);
|
mutex_exit(softnet_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!callout_expired(&tp->t_timer[TCPT_KEEP])) {
|
||||||
|
mutex_exit(softnet_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KERNEL_LOCK(1, NULL);
|
KERNEL_LOCK(1, NULL);
|
||||||
|
|
||||||
|
@ -585,6 +601,10 @@ tcp_timer_2msl(void *arg)
|
||||||
mutex_exit(softnet_lock);
|
mutex_exit(softnet_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!callout_expired(&tp->t_timer[TCPT_2MSL])) {
|
||||||
|
mutex_exit(softnet_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2 MSL timeout went off, clear the SACK scoreboard, reset
|
* 2 MSL timeout went off, clear the SACK scoreboard, reset
|
||||||
|
|
Loading…
Reference in New Issue