I have found a memory leak in both inetCidrRouteTable and ipCidrRouteTable:
How to reproduce:
Valgrind reports:
==1034== 32 (16 direct, 16 indirect) bytes in 2 blocks are definitely lost in loss record 42 of 107 ==1034== at 0x401115C: calloc (in /lib.debug/valgrind/vgpreload_memcheck-x86-linux.so) ==1034== by 0x4147A81: _ssll_insert (container_list_ssll.c:147) ==1034== by 0x4145A4B: CONTAINER_INSERT_HELPER (container.c:326) ==1034== by 0x4145A7F: CONTAINER_INSERT (container.c:349) ==1034== by 0x409280B: _load_ipv4 (route_linux.c:185) ==1034== by 0x4092B15: netsnmp_access_route_container_arch_load (route_linux.c:363) ==1034== by 0x40922FE: netsnmp_access_route_container_load (route_common.c:60) ==1034== by 0x40829AD: ipCidrRouteTable_container_load (ipCidrRouteTable_data_access.c:250) ==1034== by 0x4081D1C: _cache_load (ipCidrRouteTable_interface.c:2196) ==1034== by 0x402BBA1: _cache_load (cache_handler.c:700) ==1034== by 0x402C42C: netsnmp_cache_helper_handler (cache_handler.c:638) ==1034== by 0x40364EA: netsnmp_call_handler (agent_handler.c:526) ==1034== 376 (48 direct, 328 indirect) bytes in 6 blocks are definitely lost in loss record 91 of 107 ==1034== at 0x401115C: calloc (in /lib.debug/valgrind/vgpreload_memcheck-x86-linux.so) ==1034== by 0x4147A81: _ssll_insert (container_list_ssll.c:147) ==1034== by 0x4145A4B: CONTAINER_INSERT_HELPER (container.c:326) ==1034== by 0x4145A7F: CONTAINER_INSERT (container.c:349) ==1034== by 0x409280B: _load_ipv4 (route_linux.c:185) ==1034== by 0x4092B15: netsnmp_access_route_container_arch_load (route_linux.c:363) ==1034== by 0x40922FE: netsnmp_access_route_container_load (route_common.c:60) ==1034== by 0x408441B: inetCidrRouteTable_container_load (inetCidrRouteTable_data_access.c:262) ==1034== by 0x40834AB: _cache_load (inetCidrRouteTable_interface.c:2242) ==1034== by 0x402BBA1: _cache_load (cache_handler.c:700) ==1034== by 0x402C42C: netsnmp_cache_helper_handler (cache_handler.c:638) ==1034== by 0x40364EA: netsnmp_call_handler (agent_handler.c:526)
The issue is caused by the unusual handling of the container/cache:
ipCidrRouteTable_data_access.c: ipCidrRouteTable_container_load()
route_common.c: netsnmp_access_route_container_free()
When the actual routing data was added to the container via CONTAINER_INSERT (in route_linux.c), this kind of container which is used for the ip-forward-mib ("access:_route:fifo" / container_list_ssll.c) will actually allocate a helper data structure (sl_node) for each entry.
Since that sl_node is neither freed nor transferred to a new owner in _snarf_route_entry (only the actual data is freed/transferred), these sl_node data structures will never be freed.
A possible solution could be to call CONTAINER_CLEAR even if the DONT_CLEAR flag is set, but don't provide a cleanup function:
That will free the sl_nodes, but won't touch the actual data (which is already taken care of).
--- net-snmp/agent/mibgroup/ip-forward-mib/data_access/route_common.c 2013/10/23 15:37:58 226468 +++ net-snmp/agent/mibgroup/ip-forward-mib/data_access/route_common.c 2013/10/23 15:42:56 226469 @@ -83,6 +83,12 @@ CONTAINER_CLEAR(container, (netsnmp_container_obj_func*)_access_route_entry_release, NULL); + } else { + /* + * free the CONTAINER's sl_nodes, but not their data + */ + CONTAINER_CLEAR(container, NULL, NULL); } if(! (free_flags & NETSNMP_ACCESS_ROUTE_FREE_KEEP_CONTAINER))
Hi Christian,
I can confirm that your suggested patch works. You should submit this as a working patch.
Regards,
Sam Tannous
I put in your patch....
https://sourceforge.net/p/net-snmp/patches/1326/
Thanks for the patch, and sorry for the delay in fixing this :-(
The fix has been applied to all active branches.
Ok, perfect - thanks! Is there a plan for a 5.7.4 release in the near future?