Plug a TCP reassembly UMA zone leak introduced in r226113 by only using the

backup stack queue entry when the zone is exhausted, otherwise we leak a zone
allocation each time we plug a hole in the reassembly queue.

Reported by:	many on freebsd-stable@ (thread: "TCP Reassembly Issues")
Tested by:	many on freebsd-stable@ (thread: "TCP Reassembly Issues")
Reviewed by:	bz (very brief sanity check)
MFC after:	3 days
This commit is contained in:
Lawrence Stewart 2011-11-27 02:32:08 +00:00
parent 03f33e912d
commit a26fef3a21

View File

@ -233,23 +233,28 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* when the zone is exhausted. Otherwise we may get stuck. * when the zone is exhausted. Otherwise we may get stuck.
*/ */
te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT); te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT);
if (te == NULL && th->th_seq != tp->rcv_nxt) { if (te == NULL) {
TCPSTAT_INC(tcps_rcvmemdrop); if (th->th_seq != tp->rcv_nxt) {
m_freem(m); TCPSTAT_INC(tcps_rcvmemdrop);
*tlenp = 0; m_freem(m);
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { *tlenp = 0;
log(LOG_DEBUG, "%s; %s: global zone limit reached, " if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
"segment dropped\n", s, __func__); NULL))) {
free(s, M_TCPLOG); log(LOG_DEBUG, "%s; %s: global zone limit "
} "reached, segment dropped\n", s, __func__);
return (0); free(s, M_TCPLOG);
} else if (th->th_seq == tp->rcv_nxt) { }
bzero(&tqs, sizeof(struct tseg_qent)); return (0);
te = &tqs; } else {
if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { bzero(&tqs, sizeof(struct tseg_qent));
log(LOG_DEBUG, "%s; %s: global zone limit reached, " te = &tqs;
"using stack for missing segment\n", s, __func__); if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
free(s, M_TCPLOG); NULL))) {
log(LOG_DEBUG,
"%s; %s: global zone limit reached, using "
"stack for missing segment\n", s, __func__);
free(s, M_TCPLOG);
}
} }
} }
tp->t_segqlen++; tp->t_segqlen++;