summaryrefslogtreecommitdiff
path: root/pimd/pim_mlag.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2020-03-05 09:26:11 -0500
committerDonald Sharp <sharpd@cumulusnetworks.com>2020-03-06 16:37:17 -0500
commitb7e40944a26b80be83d44cdac1bed73c71ccc0d8 (patch)
tree0d2ad0fa7654351de63143d9bc5c4b9086df343d /pimd/pim_mlag.c
parent3c685e64ff0529cf5bf949dca0b63faf8b79ccb6 (diff)
pimd: Prevent use after free from pim_mlag_up_peer_deref
There exists a chain of events where calling pim_mlag_up_peer_deref can free the up pointer. Prevent a use after free by returning the up pointer as needed and checking to make sure we are ok. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'pimd/pim_mlag.c')
-rw-r--r--pimd/pim_mlag.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index cbde45abb8..f476cb5981 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -210,17 +210,20 @@ static void pim_mlag_up_peer_add(struct mlag_mroute_add *msg)
* - if a local entry continues to exisy and has a MLAG OIF DF election
* is re-run (at the end of which the local entry will be the DF).
*/
-static void pim_mlag_up_peer_deref(struct pim_instance *pim,
- struct pim_upstream *up)
+static struct pim_upstream *pim_mlag_up_peer_deref(struct pim_instance *pim,
+ struct pim_upstream *up)
{
if (!PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))
- return;
+ return up;
PIM_UPSTREAM_FLAG_UNSET_MLAG_PEER(up->flags);
up = pim_upstream_del(pim, up, __func__);
if (up)
pim_mlag_up_df_role_elect(pim, up);
+
+ return up;
}
+
static void pim_mlag_up_peer_del(struct mlag_mroute_del *msg)
{
struct pim_upstream *up;
@@ -256,7 +259,7 @@ static void pim_mlag_up_peer_del(struct mlag_mroute_del *msg)
return;
}
- pim_mlag_up_peer_deref(pim, up);
+ (void)pim_mlag_up_peer_deref(pim, up);
}
/* When we lose connection to the local MLAG daemon we can drop all peer
@@ -300,12 +303,13 @@ static void pim_mlag_up_peer_del_all(void)
up = listnode_head(temp);
listnode_delete(temp, up);
- pim_mlag_up_peer_deref(pim, up);
+ up = pim_mlag_up_peer_deref(pim, up);
/*
* This is the deletion of the reference added
* above
*/
- pim_upstream_del(pim, up, __func__);
+ if (up)
+ pim_upstream_del(pim, up, __func__);
}
}