git: 8a7404b2aeeb - main - tcp: fix leaks in tcp_chg_pacing_rate error paths
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 27 Jan 2022 15:42:54 UTC
The branch main has been updated by gallatin: URL: https://cgit.FreeBSD.org/src/commit/?id=8a7404b2aeeb6345bd82c13c432e56d8cbfba869 commit 8a7404b2aeeb6345bd82c13c432e56d8cbfba869 Author: Andrew Gallatin <gallatin@FreeBSD.org> AuthorDate: 2022-01-27 15:35:03 +0000 Commit: Andrew Gallatin <gallatin@FreeBSD.org> CommitDate: 2022-01-27 15:35:03 +0000 tcp: fix leaks in tcp_chg_pacing_rate error paths tcp_chg_pacing_rate() is expected to release the hw rate limit table, but failed to do so in several error cases, leading to ever increasing counts of flows using the rate. This patch was mostly done by rrs Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D34058 Reviewed by: hselasky, rrs, jhb (inital version, outside of Differential) --- sys/netinet/tcp_ratelimit.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sys/netinet/tcp_ratelimit.c b/sys/netinet/tcp_ratelimit.c index 96a38b6afd54..2f36cea4faed 100644 --- a/sys/netinet/tcp_ratelimit.c +++ b/sys/netinet/tcp_ratelimit.c @@ -1411,6 +1411,7 @@ tcp_chg_pacing_rate(const struct tcp_hwrate_limit_table *crte, * tags if it didn't allocate one when an * existing rate was present, so ignore. */ + tcp_rel_pacing_rate(crte, tp); if (error) *error = EOPNOTSUPP; return (NULL); @@ -1419,6 +1420,7 @@ tcp_chg_pacing_rate(const struct tcp_hwrate_limit_table *crte, #endif if (tp->t_inpcb->inp_snd_tag == NULL) { /* Wrong interface */ + tcp_rel_pacing_rate(crte, tp); if (error) *error = EINVAL; return (NULL); @@ -1457,10 +1459,29 @@ tcp_chg_pacing_rate(const struct tcp_hwrate_limit_table *crte, #endif err = in_pcbmodify_txrtlmt(tp->t_inpcb, nrte->rate); if (err) { + struct tcp_rate_set *lrs; + uint64_t pre; + rl_decrement_using(nrte); + lrs = __DECONST(struct tcp_rate_set *, rs); + pre = atomic_fetchadd_64(&lrs->rs_flows_using, -1); /* Do we still have a snd-tag attached? */ if (tp->t_inpcb->inp_snd_tag) in_pcbdetach_txrtlmt(tp->t_inpcb); + + if (pre == 1) { + struct epoch_tracker et; + + NET_EPOCH_ENTER(et); + mtx_lock(&rs_mtx); + /* + * Is it dead? + */ + if (lrs->rs_flags & RS_IS_DEAD) + rs_defer_destroy(lrs); + mtx_unlock(&rs_mtx); + NET_EPOCH_EXIT(et); + } if (error) *error = err; return (NULL);