When NET-SNMP's snmp_sess_synch_response(sess,*req,**res) receives response 
(and it is correct from snmp_synch_input callback) it ALWAYS free()'s second 
parameter - req.

Looking for (net-snmp-5.7.3...)/snmplib/snmp_api.c:5424 - packet processing
routine.

In case of bad SNMP table response snmp_sess_synch_response returns success 
code, but logic breaks down. It may happen in case of broken SNMP agent 
response. Collectd tries to put into the table and fails on
collectd-5.7.1/src/snmp.c:1423 and breaks out down from (result == 0) while 
loop.

Usually when collectd successfully finished probing all OID from subtree
it creates a fresh new req before using snmp_pdu_create() (snmp.c:1341)
so it safely free()'s it (snmp.c:1496). But in the situation when such
error happens it just drops down with already free()'d req structure.
Double-free happens and heap corrupts. Taking into the account that collectd 
usually runs as root, taking control over heap structures may lead to bad 
consequences for the monitoring server.

ASAN OUTPUT:

=================================================================
==16386==ERROR: AddressSanitizer: heap-use-after-free on address
0x612000017d40 at pc 0x00000044866c bp 0x7fffedcc9e20 sp 0x7fffedcc95d0
WRITE of size 272 at 0x612000017d40 thread T7
    #0 0x44866b in __interceptor_memset.part.43
(/usr/sbin/collectd+0x44866b)
    #1 0x7ffff219c482 in snmp_free_pdu snmplib/snmp_api.c:5153
    #2 0x7ffff2459195 in csnmp_read_table src/snmp.c:1496:5
    #3 0x7ffff2455e2e in csnmp_read_host src/snmp.c:1648:16
    #4 0x5111a6 in plugin_read_thread src/daemon/plugin.c:537:16
    #5 0x7ffff78bf493 in start_thread
(/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
    #6 0x7ffff6bceafe in clone (/lib/x86_64-linux-gnu/libc.so.6+0xe8afe)

0x612000017d40 is located 0 bytes inside of 272-byte region
[0x612000017d40,0x612000017e50)
freed by thread T7 here:
    #0 0x4be120 in __interceptor_cfree.localalias.0
(/usr/sbin/collectd+0x4be120)
    #1 0x7ffff219c48e in snmp_free_pdu snmplib/snmp_api.c:5154
    #2 0x7ffff219d087 in _sess_process_packet snmplib/snmp_api.c:5424
    #3 0x7ffff219e7bc in _sess_read snmplib/snmp_api.c:5876
    #4 0x7ffff219e8b9 in snmp_sess_read2 snmplib/snmp_api.c:5908
    #5 0x7ffff219e865 in snmp_sess_read snmplib/snmp_api.c:5896
    #6 0x7ffff216adac in snmp_sess_synch_response snmplib/snmp_client.c:1157
    #7 0x7ffff2457e20 in csnmp_read_table src/snmp.c:1365:14
    #8 0x7ffff2455e2e in csnmp_read_host src/snmp.c:1648:16
    #9 0x5111a6 in plugin_read_thread src/daemon/plugin.c:537:16
    #10 0x7ffff78bf493 in start_thread
(/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)

previously allocated by thread T7 here:
    #0 0x4be490 in calloc (/usr/sbin/collectd+0x4be490)
    #1 0x7ffff2169239 in snmp_pdu_create snmplib/snmp_client.c:135
    #2 0x7ffff2457bff in csnmp_read_table src/snmp.c:1341:11
    #3 0x7ffff2455e2e in csnmp_read_host src/snmp.c:1648:16
    #4 0x5111a6 in plugin_read_thread src/daemon/plugin.c:537:16
    #5 0x7ffff78bf493 in start_thread
(/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)

Thread T7 created by T0 here:
    #0 0x432b19 in __interceptor_pthread_create
(/usr/sbin/collectd+0x432b19)
    #1 0x5088f3 in start_read_threads src/daemon/plugin.c:645:18
    #2 0x5079d7 in plugin_init_all src/daemon/plugin.c:1658:7
    #3 0x4f181d in do_init src/daemon/collectd.c:297:10
    #4 0x4eff1f in main src/daemon/collectd.c:655:7
    #5 0x7ffff6b062b0 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x202b0)

SUMMARY: AddressSanitizer: heap-use-after-free
(/usr/sbin/collectd+0x44866b) in __interceptor_memset.part.43
Shadow bytes around the buggy address:
  0x0c247fffaf50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c247fffaf60: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
  0x0c247fffaf70: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c247fffaf80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c247fffaf90: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
=>0x0c247fffafa0: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd
  0x0c247fffafb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c247fffafc0: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
  0x0c247fffafd0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c247fffafe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c247fffaff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16386==ABORTING

-- 
Philippe Duke
Network software engineer
System-level developer

NetAssist LLC
Ukraine
Khreshchatyk Street, 10B, office 8
AS29632

http://netassist.ua
Our GitHub Repository:
https://github.com/netassist-ua

Attachment: 0x97A6A441.asc
Description: application/pgp-keys

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to