diff options
author | np <np@FreeBSD.org> | 2015-06-30 17:19:58 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2015-06-30 17:19:58 +0000 |
commit | a503d4a154104ab423b21d9677afa7923122f4f5 (patch) | |
tree | 6f19faa9ca7b7f1a889c4544f7be487af0765fc7 | |
parent | 8b5b408c2c62fe7ff51161d7e59c3d1798f71834 (diff) | |
download | FreeBSD-src-a503d4a154104ab423b21d9677afa7923122f4f5.zip FreeBSD-src-a503d4a154104ab423b21d9677afa7923122f4f5.tar.gz |
Fix leak in tcp_lro_rx. Simply clearing M_PKTHDR isn't enough, any tags
hanging off the header need to be freed too.
Differential Revision: https://reviews.freebsd.org/D2708
Reviewed by: ae@, hiren@
-rw-r--r-- | sys/kern/uipc_mbuf.c | 18 | ||||
-rw-r--r-- | sys/netinet/tcp_lro.c | 2 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 1 |
3 files changed, 15 insertions, 6 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index b77d476..c0c467c 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -420,6 +420,17 @@ mb_dupcl(struct mbuf *n, struct mbuf *m) n->m_flags |= m->m_flags & M_RDONLY; } +void +m_demote_pkthdr(struct mbuf *m) +{ + + M_ASSERTPKTHDR(m); + + m_tag_delete_chain(m, NULL); + m->m_flags &= ~M_PKTHDR; + bzero(&m->m_pkthdr, sizeof(struct pkthdr)); +} + /* * Clean up mbuf (chain) from any tags and packet headers. * If "all" is set then the first mbuf in the chain will be @@ -433,11 +444,8 @@ m_demote(struct mbuf *m0, int all, int flags) for (m = all ? m0 : m0->m_next; m != NULL; m = m->m_next) { KASSERT(m->m_nextpkt == NULL, ("%s: m_nextpkt in m %p, m0 %p", __func__, m, m0)); - if (m->m_flags & M_PKTHDR) { - m_tag_delete_chain(m, NULL); - m->m_flags &= ~M_PKTHDR; - bzero(&m->m_pkthdr, sizeof(struct pkthdr)); - } + if (m->m_flags & M_PKTHDR) + m_demote_pkthdr(m); m->m_flags = m->m_flags & (M_EXT | M_RDONLY | M_NOFREE | flags); } } diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index 63a6bba..83ab2e2 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -550,7 +550,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) * append new segment to existing mbuf chain. */ m_adj(m, m->m_pkthdr.len - tcp_data_len); - m->m_flags &= ~M_PKTHDR; + m_demote_pkthdr(m); le->m_tail->m_next = m; le->m_tail = m_last(m); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index ab06547..3d5a7c1 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -959,6 +959,7 @@ struct mbuf *m_copypacket(struct mbuf *, int); void m_copy_pkthdr(struct mbuf *, struct mbuf *); struct mbuf *m_copyup(struct mbuf *, int, int); struct mbuf *m_defrag(struct mbuf *, int); +void m_demote_pkthdr(struct mbuf *); void m_demote(struct mbuf *, int, int); struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)(char *, caddr_t, u_int)); |