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 <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2016-10-27 08:05:57 -04:00
parent 3506072736
commit e5905a3bc3
5 changed files with 35 additions and 21 deletions

View File

@ -127,7 +127,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
pim_upstream_update_join_desired(ch->upstream); pim_upstream_update_join_desired(ch->upstream);
} }
pim_upstream_del(ch->upstream); pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__);
ch->upstream = NULL; ch->upstream = NULL;
THREAD_OFF(ch->t_ifjoin_expiry_timer); THREAD_OFF(ch->t_ifjoin_expiry_timer);
@ -365,7 +365,7 @@ pim_ifchannel_add(struct interface *ifp,
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
up = pim_upstream_add(sg, NULL, flags); up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__);
if (!up) { if (!up) {
zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", zlog_err("%s: could not attach upstream (S,G)=%s on interface %s",
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__,

View File

@ -136,7 +136,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg
return 0; 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 (!up) {
if (PIM_DEBUG_MROUTE) { if (PIM_DEBUG_MROUTE) {
zlog_debug("%s: Failure to add upstream information for %s", 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); pim_mroute_add (oil);
if (pim_if_connected_to_source (ifp, sg.src)) 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 (!up)
{ {
if (PIM_DEBUG_MROUTE) if (PIM_DEBUG_MROUTE)

View File

@ -333,7 +333,9 @@ pim_register_recv (struct interface *ifp,
*/ */
if (!upstream) 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) if (!upstream)
{ {
zlog_warn ("Failure to create upstream state"); zlog_warn ("Failure to create upstream state");

View File

@ -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) if (PIM_DEBUG_PIM_TRACE)
zlog_debug ("%s: %s is being deleted", zlog_debug ("%s: %s is being deleted",
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__,
@ -548,31 +559,29 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg)
struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
struct interface *incoming, struct interface *incoming,
int flags) int flags, const char *name)
{ {
struct pim_upstream *up = NULL; struct pim_upstream *up = NULL;
int found = 0;
up = pim_upstream_find(sg); up = pim_upstream_find(sg);
if (up) { if (up) {
++up->ref_count; ++up->ref_count;
up->flags |= flags; up->flags |= flags;
found = 1;
} }
else { else {
up = pim_upstream_new(sg, incoming, flags); up = pim_upstream_new(sg, incoming, flags);
} }
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);
return up; return up;
} }
void pim_upstream_del(struct pim_upstream *up)
{
--up->ref_count;
if (up->ref_count < 1) {
pim_upstream_delete(up);
}
}
static int static int
pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
struct pim_ifchannel *ch) struct pim_ifchannel *ch)
@ -885,7 +894,10 @@ pim_upstream_keep_alive_timer (struct thread *t)
&up->sg, 0); &up->sg, 0);
PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags); PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags);
if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(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 else
{ {

View File

@ -116,11 +116,11 @@ struct list *pim_upstream_list;
struct hash *pim_upstream_hash; struct hash *pim_upstream_hash;
void pim_upstream_free(struct pim_upstream *up); 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_find (struct prefix_sg *sg);
struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct pim_upstream *pim_upstream_add (struct prefix_sg *sg,
struct interface *ifp, int); struct interface *ifp, int flags,
void pim_upstream_del(struct pim_upstream *up); const char *name);
void pim_upstream_del(struct pim_upstream *up, const char *name);
int pim_upstream_evaluate_join_desired(struct pim_upstream *up); int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
void pim_upstream_update_join_desired(struct pim_upstream *up); void pim_upstream_update_join_desired(struct pim_upstream *up);