bgpd, lib, zebra: Switch to work_queue_free_and_null

The work_queue_free function free'd up the wq pointer but
did not set it too NULL.  This of course causes situations
where we may use the work_queue after it is freed.  Let's
modify the work_queue to set the pointer for you.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2018-02-05 10:40:09 -05:00
parent c67667e74c
commit e208c8f943
6 changed files with 32 additions and 18 deletions

View File

@ -1079,10 +1079,8 @@ static void peer_free(struct peer *peer)
XFREE(MTYPE_TMP, peer->notify.data); XFREE(MTYPE_TMP, peer->notify.data);
memset(&peer->notify, 0, sizeof(struct bgp_notify)); memset(&peer->notify, 0, sizeof(struct bgp_notify));
if (peer->clear_node_queue) { if (peer->clear_node_queue)
work_queue_free(peer->clear_node_queue); work_queue_free_and_null(&peer->clear_node_queue);
peer->clear_node_queue = NULL;
}
bgp_sync_delete(peer); bgp_sync_delete(peer);
@ -7639,10 +7637,8 @@ void bgp_terminate(void)
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG); BGP_NOTIFY_CEASE_PEER_UNCONFIG);
if (bm->process_main_queue) { if (bm->process_main_queue)
work_queue_free(bm->process_main_queue); work_queue_free_and_null(&bm->process_main_queue);
bm->process_main_queue = NULL;
}
if (bm->t_rmap_update) if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update); BGP_TIMER_OFF(bm->t_rmap_update);

View File

@ -4336,7 +4336,7 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
h->import_mac = NULL; h->import_mac = NULL;
} }
work_queue_free(h->deferred_close_q); work_queue_free_and_null(&h->deferred_close_q);
if (h->rfp != NULL) if (h->rfp != NULL)
rfp_stop(h->rfp); rfp_stop(h->rfp);

View File

@ -571,10 +571,8 @@ void rfapiRibClear(struct rfapi_descriptor *rfd)
} }
} }
} }
if (rfd->updated_responses_queue) { if (rfd->updated_responses_queue)
work_queue_free(rfd->updated_responses_queue); work_queue_free_and_null(&rfd->updated_responses_queue);
rfd->updated_responses_queue = NULL;
}
} }
/* /*

View File

@ -101,7 +101,7 @@ struct work_queue *work_queue_new(struct thread_master *m,
return new; return new;
} }
void work_queue_free(struct work_queue *wq) void work_queue_free_original(struct work_queue *wq)
{ {
if (wq->thread != NULL) if (wq->thread != NULL)
thread_cancel(wq->thread); thread_cancel(wq->thread);
@ -119,6 +119,12 @@ void work_queue_free(struct work_queue *wq)
return; return;
} }
void work_queue_free_and_null(struct work_queue **wq)
{
work_queue_free_original(*wq);
*wq = NULL;
}
bool work_queue_is_scheduled(struct work_queue *wq) bool work_queue_is_scheduled(struct work_queue *wq)
{ {
return (wq->thread != NULL); return (wq->thread != NULL);

View File

@ -28,7 +28,7 @@
DECLARE_MTYPE(WORK_QUEUE) DECLARE_MTYPE(WORK_QUEUE)
/* Hold time for the initial schedule of a queue run, in millisec */ /* Hold time for the initial schedule of a queue run, in millisec */
#define WORK_QUEUE_DEFAULT_HOLD 50 #define WORK_QUEUE_DEFAULT_HOLD 50
/* action value, for use by item processor and item error handlers */ /* action value, for use by item processor and item error handlers */
typedef enum { typedef enum {
@ -148,8 +148,22 @@ static inline void work_queue_item_dequeue(struct work_queue *wq,
* anything to it * anything to it
*/ */
extern struct work_queue *work_queue_new(struct thread_master *, const char *); extern struct work_queue *work_queue_new(struct thread_master *, const char *);
/* destroy work queue */ /* destroy work queue */
extern void work_queue_free(struct work_queue *); /*
* The usage of work_queue_free is being transitioned to pass
* in the double pointer to remove use after free's.
*/
#if CONFDATE > 20190205
CPP_NOTICE("work_queue_free without double pointer is deprecated, please fixup")
#endif
extern void work_queue_free_and_null(struct work_queue **);
extern void work_queue_free_original(struct work_queue *);
#define work_queue_free(X) \
do { \
work_queue_free_original((X)); \
CPP_WARN("Please use work_queue_free_and_null"); \
} while (0)
/* Add the supplied data as an item onto the workqueue */ /* Add the supplied data as an item onto the workqueue */
extern void work_queue_add(struct work_queue *, void *); extern void work_queue_add(struct work_queue *, void *);

View File

@ -140,7 +140,7 @@ static void sigint(void)
SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN); SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN);
} }
if (zebrad.lsp_process_q) if (zebrad.lsp_process_q)
work_queue_free(zebrad.lsp_process_q); work_queue_free_and_null(&zebrad.lsp_process_q);
vrf_terminate(); vrf_terminate();
ns_walk_func(zebra_ns_disabled); ns_walk_func(zebra_ns_disabled);
@ -151,7 +151,7 @@ static void sigint(void)
route_map_finish(); route_map_finish();
list_delete_and_null(&zebrad.client_list); list_delete_and_null(&zebrad.client_list);
work_queue_free(zebrad.ribq); work_queue_free_and_null(&zebrad.ribq);
meta_queue_free(zebrad.mq); meta_queue_free(zebrad.mq);
frr_fini(); frr_fini();