Package: net-snmpd
Version: 5.2.3-7
Severity: important

Following up on Nicole's initial report, I have duplicated this error and have 
included a patch that resolves it.  This error occurs on the amd64 architecture 
when the syslog string encoding of the received snmp trap exceeds 1024 bytes.

In the file snmplib/snmp_logging.c, the function snmp_vlog( int, char*, va_list 
) attempts to vsnprintf on the va_list passed in from snmp_log().  It captures 
the number of bytes written and writes the snmp log string if the length is not 
zero and could be formatted.  It functions correctly as long as the length 
value is less than LOGLENGTH (defined as 1024).

If the string length is >= LOGLENGTH, it needs to malloc the length of the 
string plus one byte for the null terminator.  If successful, it attempts to 
vsnprintf into the buffer using the same va_list ap.  This is where the fault 
occurs because the value of ap is "indeterminate" after the first call where we 
fetched the length.  This is documented in the ISO C99 specification in section 
7.15 (3) (http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf).

To overcome this, we must make a copy of the va_list variable before the first 
vsnprintf.  If the number of bytes written is less than LOGLENGTH, we just 
discard the value with va_end().  However, if the dynamically sized buffer must 
be used, the second call to vsnprintf will use the virgin copy of the original 
va_list variable (the original is tainted at this point).  Here too, va_end() 
must be called after we are finished.  The va_end call for the original va_list 
ap variable happens in the caller, snmp_log().

These changes already exist in the latest net-snmp distribution.

diff -ubBr pristine/net-snmp-5.2.3/snmplib/snmp_logging.c 
net-snmp-5.2.3/snmplib/snmp_logging.c
--- pristine/net-snmp-5.2.3/snmplib/snmp_logging.c      2006-01-25 
08:28:12.000000000 -0800
+++ net-snmp-5.2.3/snmplib/snmp_logging.c       2009-02-12 16:29:48.000000000 
-0800
@@ -1135,19 +1135,26 @@
     char            buffer[LOGLENGTH];
     int             length;
     char           *dynamic;
+    va_list         aq;

+    va_copy( aq, ap );
     length = vsnprintf(buffer, LOGLENGTH, format, ap);
+    va_end( aq );

-    if (length == 0)
+    if (length == 0) {
+      va_end( aq );
         return (0);             /* Empty string */
+    }

     if (length == -1) {
         snmp_log_string(LOG_ERR, "Could not format log-string\n");
+        va_end( aq );
         return (-1);
     }

     if (length < LOGLENGTH) {
         snmp_log_string(priority, buffer);
+        va_end(aq);
         return (0);
     }

@@ -1156,12 +1163,14 @@
         snmp_log_string(LOG_ERR,
                         "Could not allocate memory for log-message\n");
         snmp_log_string(priority, buffer);
+        va_end(aq);
         return (-2);
     }

-    vsnprintf(dynamic, length + 1, format, ap);
+    vsnprintf(dynamic, length + 1, format, aq);
     snmp_log_string(priority, dynamic);
     free(dynamic);
+    va_end(aq);
     return 0;
 }


Reply via email to