Fix a memory leak when ip_output_send() returns EAGAIN due to send tag issues
When ip_output_send() returns EAGAIN due to issues with send tags (route change, lagg failover, etc), it must free the mbuf. This is because ip_output_send() was written as a wrapper/replacement for a direct call to if_output(), and the contract with if_output() has historically been that it owns the mbufs once called. When ip_output_send() failed to free mbufs, it violated this assumption and lead to leaked mbufs. This was noticed when using NIC TLS in combination with hardware rate-limited connections. When seeing lots of NIC output drops triggered ratelimit send tag changes, we noticed we were leaking ktls_sessions, send tags and mbufs. This was due ip_output_send() leaking mbufs which held references to ktls_sessions, which in turn held references to send tags. Many thanks to jbh, rrs, hselasky and markj for their help in debugging this. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D34054 Reviewed by: hselasky, jhb, rrs MFC after: 2 weeks
This commit is contained in:
parent
38da0c96dc
commit
9ba117960e
@ -239,6 +239,7 @@ ip_output_send(struct inpcb *inp, struct ifnet *ifp, struct mbuf *m,
|
||||
* packet.
|
||||
*/
|
||||
if (mst == NULL) {
|
||||
m_freem(m);
|
||||
error = EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
@ -263,6 +264,7 @@ ip_output_send(struct inpcb *inp, struct ifnet *ifp, struct mbuf *m,
|
||||
KASSERT(m->m_pkthdr.rcvif == NULL,
|
||||
("trying to add a send tag to a forwarded packet"));
|
||||
if (mst->ifp != ifp) {
|
||||
m_freem(m);
|
||||
error = EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
|
@ -336,6 +336,7 @@ ip6_output_send(struct inpcb *inp, struct ifnet *ifp, struct ifnet *origifp,
|
||||
* packet.
|
||||
*/
|
||||
if (mst == NULL) {
|
||||
m_freem(m);
|
||||
error = EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
@ -360,6 +361,7 @@ ip6_output_send(struct inpcb *inp, struct ifnet *ifp, struct ifnet *origifp,
|
||||
KASSERT(m->m_pkthdr.rcvif == NULL,
|
||||
("trying to add a send tag to a forwarded packet"));
|
||||
if (mst->ifp != ifp) {
|
||||
m_freem(m);
|
||||
error = EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user