From: Donald Sharp Date: Thu, 27 Oct 2016 12:05:57 +0000 (-0400) Subject: pimd: Fix possible double free of upstream X-Git-Tag: frr-3.0-branchpoint~64^2~10^2~165 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e5905a3bc3b33940d01e1b4a62a4eee74f465698;p=mirror%2Ffrr.git pimd: Fix possible double free of upstream Fix possible double free of upstream and in addition add some debug code to help find where the problem is coming from. Signed-off-by: Donald Sharp --- diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index a811742e3e..c2d27f1ec8 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -127,7 +127,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_upstream_update_join_desired(ch->upstream); } - pim_upstream_del(ch->upstream); + pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); ch->upstream = NULL; THREAD_OFF(ch->t_ifjoin_expiry_timer); @@ -365,7 +365,7 @@ pim_ifchannel_add(struct interface *ifp, pim_ifp = ifp->info; zassert(pim_ifp); - up = pim_upstream_add(sg, NULL, flags); + up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); if (!up) { zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", __PRETTY_FUNCTION__, diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 5f8d180742..7935f7290e 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -136,7 +136,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg return 0; } - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); if (!up) { if (PIM_DEBUG_MROUTE) { zlog_debug("%s: Failure to add upstream information for %s", @@ -371,7 +371,7 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) pim_mroute_add (oil); if (pim_if_connected_to_source (ifp, sg.src)) { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR); + up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); if (!up) { if (PIM_DEBUG_MROUTE) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 62973bc9c1..c941388dc4 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -333,7 +333,9 @@ pim_register_recv (struct interface *ifp, */ if (!upstream) { - upstream = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); + upstream = pim_upstream_add (&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); if (!upstream) { zlog_warn ("Failure to create upstream state"); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b103a4fc66..ee26683547 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -156,8 +156,19 @@ static void upstream_channel_oil_detach(struct pim_upstream *up) } } -void pim_upstream_delete(struct pim_upstream *up) +void +pim_upstream_del(struct pim_upstream *up, const char *name) { + if (PIM_DEBUG_PIM_TRACE) + { + zlog_debug ("%s: Delete (%s) ref count: %d", + name, pim_str_sg_dump (&up->sg), up->ref_count); + } + --up->ref_count; + + if (up->ref_count >= 1) + return; + if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: %s is being deleted", __PRETTY_FUNCTION__, @@ -548,29 +559,27 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct interface *incoming, - int flags) + int flags, const char *name) { struct pim_upstream *up = NULL; - + int found = 0; up = pim_upstream_find(sg); if (up) { ++up->ref_count; up->flags |= flags; + found = 1; } else { up = pim_upstream_new(sg, incoming, flags); } - return up; -} - -void pim_upstream_del(struct pim_upstream *up) -{ - --up->ref_count; + if (PIM_DEBUG_TRACE) + zlog_debug("%s(%s): (%s), found: %d: ref_count: %d", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump (&up->sg), found, + up->ref_count); - if (up->ref_count < 1) { - pim_upstream_delete(up); - } + return up; } static int @@ -885,7 +894,10 @@ pim_upstream_keep_alive_timer (struct thread *t) &up->sg, 0); PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags)) - pim_upstream_del (up); + { + PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); + pim_upstream_del (up, __PRETTY_FUNCTION__); + } } else { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 70b5b01062..41fcd28679 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -116,11 +116,11 @@ struct list *pim_upstream_list; struct hash *pim_upstream_hash; void pim_upstream_free(struct pim_upstream *up); -void pim_upstream_delete(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, - struct interface *ifp, int); -void pim_upstream_del(struct pim_upstream *up); + struct interface *ifp, int flags, + const char *name); +void pim_upstream_del(struct pim_upstream *up, const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); void pim_upstream_update_join_desired(struct pim_upstream *up);