diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-03-05 09:26:11 -0500 |
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-03-06 16:37:17 -0500 |
| commit | b7e40944a26b80be83d44cdac1bed73c71ccc0d8 (patch) | |
| tree | 0d2ad0fa7654351de63143d9bc5c4b9086df343d /pimd/pim_mlag.c | |
| parent | 3c685e64ff0529cf5bf949dca0b63faf8b79ccb6 (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.c | 16 |
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__); } } |
