From 8b5c4dce07e6f8fa7f984945d6121e6999072f3d Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 3 Jan 2020 22:28:53 -0500 Subject: [PATCH] zebra: fix iptable memleak, fix free funcs - Fix iptable freeing code to free malloc'd list - malloc iptable in zapi handler and use those functions to free it when done to fix a linked list memleak Signed-off-by: Quentin Young --- zebra/zapi_msg.c | 48 ++++++++++++++++++++++++----------------------- zebra/zebra_pbr.c | 13 ++++++++----- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 1dbe41f462..ad2f5e3c21 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2459,37 +2459,39 @@ stream_failure: static inline void zread_iptable(ZAPI_HANDLER_ARGS) { - struct zebra_pbr_iptable zpi; + struct zebra_pbr_iptable *zpi = + XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable)); struct stream *s; s = msg; - memset(&zpi, 0, sizeof(zpi)); - - zpi.interface_name_list = list_new(); - zpi.sock = client->sock; - zpi.vrf_id = zvrf->vrf->vrf_id; - STREAM_GETL(s, zpi.unique); - STREAM_GETL(s, zpi.type); - STREAM_GETL(s, zpi.filter_bm); - STREAM_GETL(s, zpi.action); - STREAM_GETL(s, zpi.fwmark); - STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE); - STREAM_GETW(s, zpi.pkt_len_min); - STREAM_GETW(s, zpi.pkt_len_max); - STREAM_GETW(s, zpi.tcp_flags); - STREAM_GETW(s, zpi.tcp_mask_flags); - STREAM_GETC(s, zpi.dscp_value); - STREAM_GETC(s, zpi.fragment); - STREAM_GETC(s, zpi.protocol); - STREAM_GETL(s, zpi.nb_interface); - zebra_pbr_iptable_update_interfacelist(s, &zpi); + zpi->interface_name_list = list_new(); + zpi->sock = client->sock; + zpi->vrf_id = zvrf->vrf->vrf_id; + STREAM_GETL(s, zpi->unique); + STREAM_GETL(s, zpi->type); + STREAM_GETL(s, zpi->filter_bm); + STREAM_GETL(s, zpi->action); + STREAM_GETL(s, zpi->fwmark); + STREAM_GET(&zpi->ipset_name, s, ZEBRA_IPSET_NAME_SIZE); + STREAM_GETW(s, zpi->pkt_len_min); + STREAM_GETW(s, zpi->pkt_len_max); + STREAM_GETW(s, zpi->tcp_flags); + STREAM_GETW(s, zpi->tcp_mask_flags); + STREAM_GETC(s, zpi->dscp_value); + STREAM_GETC(s, zpi->fragment); + STREAM_GETC(s, zpi->protocol); + STREAM_GETL(s, zpi->nb_interface); + zebra_pbr_iptable_update_interfacelist(s, zpi); if (hdr->command == ZEBRA_IPTABLE_ADD) - zebra_pbr_add_iptable(&zpi); + zebra_pbr_add_iptable(zpi); else - zebra_pbr_del_iptable(&zpi); + zebra_pbr_del_iptable(zpi); + stream_failure: + zebra_pbr_iptable_free(zpi); + zpi = NULL; return; } diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index e24d2e2b42..0c3adcdfa1 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -345,11 +345,13 @@ void zebra_pbr_iptable_free(void *arg) iptable = (struct zebra_pbr_iptable *)arg; hook_call(zebra_pbr_iptable_update, 0, iptable); - for (ALL_LIST_ELEMENTS(iptable->interface_name_list, - node, nnode, name)) { - XFREE(MTYPE_PBR_IPTABLE_IFNAME, name); - list_delete_node(iptable->interface_name_list, - node); + if (iptable->interface_name_list) { + for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node, + nnode, name)) { + XFREE(MTYPE_PBR_IPTABLE_IFNAME, name); + list_delete_node(iptable->interface_name_list, node); + } + list_delete(&iptable->interface_name_list); } XFREE(MTYPE_TMP, iptable); } @@ -688,6 +690,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable) list_delete_node(iptable->interface_name_list, node); } + list_delete(&iptable->interface_name_list); XFREE(MTYPE_TMP, lookup); } else zlog_debug("%s: IPTable being deleted we know nothing about",