Bug 2134362

Summary: Memory leak when IPv6 is disabled through ipv6.disable=1
Product: Red Hat Enterprise Linux 8 Reporter: Renaud Métrich <rmetrich>
Component: net-snmpAssignee: Josef Ridky <jridky>
Status: CLOSED DUPLICATE QA Contact: CS System Management SST QE <rhel-cs-system-management-subsystem-qe>
Severity: medium Docs Contact:
Priority: medium    
Version: 8.6CC: sbroz
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-01-16 07:58:25 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Renaud Métrich 2022-10-13 09:06:37 UTC
This bug was initially created as a copy of Bug #2134359

I am copying this bug because: 

Same code applies

Description of problem:

Executing snmpd under valgrind shows a couple of memory leaks when /proc/net/snmp6 doesn't exist:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
==75204== 584 bytes in 1 blocks are definitely lost in loss record 1,238 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x511D3A1: netsnmp_access_systemstats_entry_create (systemstats_common.c:172)
==75204==    by 0x5120476: _systemstats_v6_load_systemstats (systemstats_linux.c:556)
==75204==    by 0x5120476: _systemstats_v6 (systemstats_linux.c:699)
==75204==    by 0x5120476: netsnmp_access_systemstats_container_arch_load (systemstats_linux.c:82)
==75204==    by 0x511D126: netsnmp_access_systemstats_container_load (systemstats_common.c:109)
==75204==    by 0x511D271: netsnmp_access_systemstats_init (systemstats_common.c:52)
==75204==    by 0x50FFAFD: ipIfStatsTable_init_data (ipIfStatsTable_data_access.c:66)
==75204==    by 0x50FE8A4: _ipIfStatsTable_initialize_interface (ipIfStatsTable_interface.c:199)
==75204==    by 0x50FD431: init_ipIfStatsTable (ipIfStatsTable.c:55)
==75204==    by 0x51C42C4: init_mib_modules (mib_module_inits.h:23)
==75204==    by 0x10B744: main (snmpd.c:947)

==75204== 584 bytes in 1 blocks are definitely lost in loss record 1,239 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x511D3A1: netsnmp_access_systemstats_entry_create (systemstats_common.c:172)
==75204==    by 0x5120476: _systemstats_v6_load_systemstats (systemstats_linux.c:556)
==75204==    by 0x5120476: _systemstats_v6 (systemstats_linux.c:699)
==75204==    by 0x5120476: netsnmp_access_systemstats_container_arch_load (systemstats_linux.c:82)
==75204==    by 0x511D126: netsnmp_access_systemstats_container_load (systemstats_common.c:109)
==75204==    by 0x51A62A1: ipSystemStatsTable_container_load (ipSystemStatsTable_data_access.c:304)
==75204==    by 0x51A50F2: _ipSystemStatsTable_container_init (ipSystemStatsTable_interface.c:1332)
==75204==    by 0x51A50F2: _ipSystemStatsTable_initialize_interface (ipSystemStatsTable_interface.c:190)
==75204==    by 0x51C3CE4: init_mib_modules (mib_module_inits.h:117)
==75204==    by 0x10B744: main (snmpd.c:947)

==75204== 82,928 bytes in 142 blocks are definitely lost in loss record 1,444 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x511D3A1: netsnmp_access_systemstats_entry_create (systemstats_common.c:172)
==75204==    by 0x5120476: _systemstats_v6_load_systemstats (systemstats_linux.c:556)
==75204==    by 0x5120476: _systemstats_v6 (systemstats_linux.c:699)
==75204==    by 0x5120476: netsnmp_access_systemstats_container_arch_load (systemstats_linux.c:82)
==75204==    by 0x511D126: netsnmp_access_systemstats_container_load (systemstats_common.c:109)
==75204==    by 0x51A62A1: ipSystemStatsTable_container_load (ipSystemStatsTable_data_access.c:304)
==75204==    by 0x4E4CEFF: _cache_load (cache_handler.c:700)
==75204==    by 0x57D9CDB: run_alarms (snmp_alarm.c:218)
==75204==    by 0x10C0EE: receive (snmpd.c:1376)
==75204==    by 0x10C0EE: main (snmpd.c:1130)

548 static int
549 _systemstats_v6_load_systemstats(netsnmp_container* container, u_int load_flags)
550 {
 :
556     entry = netsnmp_access_systemstats_entry_create(2, 0,
557             "ipSystemStatsTable.ipv6");
 :
565     if (!(devin = fopen(filename, "r"))) {
566         DEBUGMSGTL(("access:systemstats",
567                 "Failed to load Systemstats Table (linux1), cannot open %s\n",
568                 filename));
569         return 0;
570     }
 :
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

In case opening `/proc/net/snmp6` fails, which is the case due to not having IPv6 enabled, the memory allocated on line 445 is not de-allocated, this is causing a leak to occur every minute.

Version-Release number of selected component (if applicable):

net-snmp-5.8-25.el8

How reproducible:

Always

Steps to Reproduce:
1. Boot with "ipv6.disable=1"
2. Wait and check VmRSS

Actual results:

Growing slowly

Expected results:

Mostly stable

Additional info:

Valgrind reports some some other leaks and an issue with "memcpy", which should be fixed as well:

-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
==75204== Source and destination overlap in memcpy(0x5a35560, 0x5a35560, 5)
==75204==    at 0x4C2E81D: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1035)
==75204==    by 0x580367E: UnknownInlinedFun (string3.h:51)
==75204==    by 0x580367E: strlcpy (strlcpy.c:40)
==75204==    by 0x57C7BEC: snmp_log_syslogname (snmp_logging.c:538)
==75204==    by 0x57C8587: snmp_enable_syslog_ident (snmp_logging.c:791)
==75204==    by 0x57C8E0E: snmp_log_options (snmp_logging.c:498)
==75204==    by 0x10B305: main (snmpd.c:665)

 766 void    
 767 snmp_enable_syslog_ident(const char *ident, const int facility)
 768 {
 :
 791     openlog(snmp_log_syslogname(ident), LOG_CONS | LOG_PID, facility);
 :

 534 char *
 535 snmp_log_syslogname(const char *pstr)
 536 {   
 537   if (pstr)
 538     strlcpy (syslogname, pstr, sizeof(syslogname));
 539 
 540   return syslogname;
 541 }   
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Here above we can see a copy from "pstr" to itself (same addresses), this should be avoided but is likely harmless.

and

-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
==75204== 1,168 (32 direct, 1,136 indirect) bytes in 1 blocks are definitely lost in loss record 1,367 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x50E9852: initialize_lmSensorsTable (lmsensorsMib.c:87)
==75204==    by 0x50E9997: init_lmsensorsMib (lmsensorsMib.c:37)
==75204==    by 0x51C43D4: init_mib_modules (mib_module_inits.h:6)
==75204==    by 0x10B744: main (snmpd.c:947)
==75204==
==75204== 1,168 (32 direct, 1,136 indirect) bytes in 1 blocks are definitely lost in loss record 1,368 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x50E9852: initialize_lmSensorsTable (lmsensorsMib.c:87)
==75204==    by 0x50E99B6: init_lmsensorsMib (lmsensorsMib.c:39)
==75204==    by 0x51C43D4: init_mib_modules (mib_module_inits.h:6)
==75204==    by 0x10B744: main (snmpd.c:947)
==75204==
==75204== 1,168 (32 direct, 1,136 indirect) bytes in 1 blocks are definitely lost in loss record 1,369 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x50E9852: initialize_lmSensorsTable (lmsensorsMib.c:87)
==75204==    by 0x50E99D5: init_lmsensorsMib (lmsensorsMib.c:41)
==75204==    by 0x51C43D4: init_mib_modules (mib_module_inits.h:6)
==75204==    by 0x10B744: main (snmpd.c:947)
==75204==
==75204== 1,168 (32 direct, 1,136 indirect) bytes in 1 blocks are definitely lost in loss record 1,370 of 1,444
==75204==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==75204==    by 0x50E9852: initialize_lmSensorsTable (lmsensorsMib.c:87)
==75204==    by 0x51C43D4: init_mib_modules (mib_module_inits.h:6)
==75204==    by 0x10B744: main (snmpd.c:947)

 50 void
 51 initialize_lmSensorsTable(const char *tableName, const oid *tableOID,
 52                           netsnmp_container_op *filter, int mult )
 53 {
 :
 69     container = netsnmp_container_find("sensorTable:table_container");
 :
 87     table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
 :
 91     netsnmp_container_table_register( reg, table_info, container, 0 );
 :
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Here above, there should be no leak happening, unless `netsnmp_container_table_register()` returns an error (line 91), which is not handled by this code.
I have however no evidence an error occurred, because errors are all logged at *debug* level, but such level was not enabled when starting the process.

Comment 1 Josef Ridky 2023-01-16 07:58:25 UTC

*** This bug has been marked as a duplicate of bug 2151537 ***