diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-04-24 02:09:56 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-04-24 02:11:25 +0200 |
commit | d3963e92499f3d71a213975480030e74ea73a774 (patch) | |
tree | 66865c6be1dc4f8a1ce5b359eebca7dfaad0311c /src | |
parent | d0158bf4cab929d4143a78d4c992cf271bf264e0 (diff) | |
download | slirp-d3963e92499f3d71a213975480030e74ea73a774.zip slirp-d3963e92499f3d71a213975480030e74ea73a774.tar.gz slirp-d3963e92499f3d71a213975480030e74ea73a774.tar.bz2 |
m_cleanup_list: Fix missing cleanup packets from the same session
When several packets are queued for emission for the same socket session, we
need to clean them all.
Spotted thanks to ASAN & fuzzing.
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/if.c | 6 | ||||
-rw-r--r-- | src/mbuf.c | 37 | ||||
-rw-r--r-- | src/mbuf.h | 6 |
3 files changed, 33 insertions, 16 deletions
@@ -13,12 +13,6 @@ static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) ifm->ifs_next->ifs_prev = ifm; } -static void ifs_remque(struct mbuf *ifm) -{ - ifm->ifs_prev->ifs_next = ifm->ifs_next; - ifm->ifs_next->ifs_prev = ifm->ifs_prev; -} - void if_init(Slirp *slirp) { slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq; @@ -29,17 +29,34 @@ void m_init(Slirp *slirp) slirp->m_usedlist.qh_link = slirp->m_usedlist.qh_rlink = &slirp->m_usedlist; } -static void m_cleanup_list(struct slirp_quehead *list_head) +static void m_cleanup_list(struct slirp_quehead *list_head, bool pkts) { - struct mbuf *m, *next; + struct mbuf *m, *next, *next2; + bool last; m = (struct mbuf *)list_head->qh_link; while ((struct slirp_quehead *)m != list_head) { next = m->m_next; - if (m->m_flags & M_EXT) { - g_free(m->m_ext); - } - g_free(m); + + last = false; + do { + next2 = m->ifs_next; + + if (pkts) { + ifs_remque(m); + last = next2 == m; + } else { + last = true; + } + + if (m->m_flags & M_EXT) { + g_free(m->m_ext); + } + + g_free(m); + m = next2; + } while (!last); + m = next; } list_head->qh_link = list_head; @@ -48,10 +65,10 @@ static void m_cleanup_list(struct slirp_quehead *list_head) void m_cleanup(Slirp *slirp) { - m_cleanup_list(&slirp->m_usedlist); - m_cleanup_list(&slirp->m_freelist); - m_cleanup_list(&slirp->if_batchq); - m_cleanup_list(&slirp->if_fastq); + m_cleanup_list(&slirp->m_usedlist, false); + m_cleanup_list(&slirp->m_freelist, false); + m_cleanup_list(&slirp->if_batchq, true); + m_cleanup_list(&slirp->if_fastq, true); } /* @@ -109,6 +109,12 @@ struct mbuf { #define ifs_next m_nextpkt #define ifq_so m_so +static inline void ifs_remque(struct mbuf *ifm) +{ + ifm->ifs_prev->ifs_next = ifm->ifs_next; + ifm->ifs_next->ifs_prev = ifm->ifs_prev; +} + #define M_EXT 0x01 /* m_ext points to more (malloced) data */ #define M_FREELIST 0x02 /* mbuf is on free list */ #define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */ |