Package: snmpd
Version: 5.2.1.2-2
Tags: patch
Followup-For: Bug #321713

Hi,

After investigation, I found the cause of this problem. But WAIT! There's more!
snmpd won't survive an snmpwalk (looking at this problem right now)


The segfault happens in snmplib/tools.c:401, netsnmp_hex_to_binary(),
called from agent/mibgroup/ip-mib/data_access/ipaddress_linux.c:_load_v6()

   370  int
   371  netsnmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * out_len,
   372                        int allow_realloc, const char *hex, const char 
*delim)
   373  {
   374      int             subid = 0;
   375      const char     *cp = hex;

   ...

   397          if ((*out_len >= *buf_len) &&
   398              !(allow_realloc && snmp_realloc(buf, buf_len))) {
   399              return 0;
   400          }
   401          *(*buf + *out_len) = (u_char) subid;

   ...

Printing out the value of *buf and (*buf + *out_len) after line 400 gives:

  *buf = 0x5eaa8c, (*buf + *out_len) = 0x10005eaa8c

Printing the values of *buf_len and *out_len reveals that they're WAY to high
to be OK. As both buf_len and out_len are affected, the realloc check doesn't
trigger, unfortunately.

Investigating the caller reveals this:

   144  int
   145  _load_v6(netsnmp_container *container, int idx_offset)
   146  {
   147      FILE           *in;
   148      char            line[80], addr[33], if_name[IFNAMSIZ];
   149      u_char          *buf;
   150      int             if_index, pfx_len, scope, flags, rc = 0, in_len, 
out_len;
   151      netsnmp_ipaddress_entry *entry;
   152      _ioctl_extras           *extras;
   153      static int      log_open_err = 1;

   ...

   201          in_len = entry->ia_address_len = sizeof(entry->ia_address);
   202          netsnmp_assert(16 == in_len);
   203          out_len = 0;
   204          buf = entry->ia_address;
   205          if(1 != snmp_hex_to_binary(&buf,
   206                                     &in_len, &out_len, 0, addr)) {
   207              snmp_log(LOG_ERR,"error parsing '%s', skipping\n",
   208                       entry->ia_address);
   209              netsnmp_access_ipaddress_entry_free(entry);
   210              continue;
   211          }
   212          netsnmp_assert(16 == out_len);
   213          entry->ia_address_len = out_len;

   ...

See line 206 ? See line 150 ? See line 371 above ?

The types for in_len (buf_len) and out_len (out_len) ARE FUCKING WRONG.


int is signed, 32 bits, and size_t on amd64 is unsigned, 64 bits. KABOOM.


This bug only triggers on machines with IPv6 support.

Patch attached, changing in_len and out_len to be size_t, which is the
data type expected by netsnmp_hex_to_binary().

Please print it out, stick it on a big, heavy cluebat and use the said
cluebat to vigorously, repeatedly LART upstream. Thanks.

And, please, build net-snmp with -Wall enabled in the debian package.

JB.

-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.12
Locale: LANG=C, [EMAIL PROTECTED] (charmap=ISO-8859-15)

Versions of packages snmpd depends on:
ii  libc6                         2.3.5-3    GNU C Library: Shared libraries an
ii  libsensors3                   1:2.9.1-5  library to read temperature/voltag
ii  libsnmp5                      5.2.1.2-2  NET SNMP (Simple Network Managemen
ii  libwrap0                      7.6.dbs-8  Wietse Venema's TCP wrappers libra

snmpd recommends no packages.

-- no debconf information
--- ipaddress_linux.c~	2004-10-19 05:23:59.000000000 +0200
+++ ipaddress_linux.c	2005-08-14 12:24:51.497056312 +0200
@@ -174,7 +174,8 @@
     FILE           *in;
     char            line[80], addr[33], if_name[IFNAMSIZ];
     u_char          *buf;
-    int             if_index, pfx_len, scope, flags, rc = 0, in_len, out_len;
+    int             if_index, pfx_len, scope, flags, rc = 0;
+    size_t          in_len, out_len;
     netsnmp_ipaddress_entry *entry;
     _ioctl_extras           *extras;
     static int      log_open_err = 1;

Reply via email to