Prevent underflows in tp->snd_wnd if the remote side ACKs more than
tp->snd_wnd. This can happen, for example, when the remote side responds to a window probe by ACKing the one byte it contains. Differential Revision: https://reviews.freebsd.org/D5625 Reviewed by: hiren Obtained from: Juniper Networks (earlier version) MFC after: 2 weeks Sponsored by: Juniper Networks
This commit is contained in:
parent
b8df8f9a8d
commit
b8c2cd15e9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298408
@ -2754,6 +2754,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
|
||||
INP_WLOCK_ASSERT(tp->t_inpcb);
|
||||
|
||||
acked = BYTES_THIS_ACK(tp, th);
|
||||
KASSERT(acked >= 0, ("%s: acked unexepectedly negative "
|
||||
"(tp->snd_una=%u, th->th_ack=%u, tp=%p, m=%p)", __func__,
|
||||
tp->snd_una, th->th_ack, tp, m));
|
||||
TCPSTAT_INC(tcps_rcvackpack);
|
||||
TCPSTAT_ADD(tcps_rcvackbyte, acked);
|
||||
|
||||
@ -2823,13 +2826,19 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
|
||||
|
||||
SOCKBUF_LOCK(&so->so_snd);
|
||||
if (acked > sbavail(&so->so_snd)) {
|
||||
tp->snd_wnd -= sbavail(&so->so_snd);
|
||||
if (tp->snd_wnd >= sbavail(&so->so_snd))
|
||||
tp->snd_wnd -= sbavail(&so->so_snd);
|
||||
else
|
||||
tp->snd_wnd = 0;
|
||||
mfree = sbcut_locked(&so->so_snd,
|
||||
(int)sbavail(&so->so_snd));
|
||||
ourfinisacked = 1;
|
||||
} else {
|
||||
mfree = sbcut_locked(&so->so_snd, acked);
|
||||
tp->snd_wnd -= acked;
|
||||
if (tp->snd_wnd >= (u_long) acked)
|
||||
tp->snd_wnd -= acked;
|
||||
else
|
||||
tp->snd_wnd = 0;
|
||||
ourfinisacked = 0;
|
||||
}
|
||||
/* NB: sowwakeup_locked() does an implicit unlock. */
|
||||
|
Loading…
Reference in New Issue
Block a user