Package: rrdtool Version: 1.2.15-0.3 Severity: critical Tags: patch,upstream,fixed-upstream
The non-threadsafe version of the rrdtool library has a wrong length for the buffers of error strings, causing a segfaults in the python or perl bindings. This is a known upstream bug : http://oss.oetiker.ch/rrdtool-trac/ticket/65 It has been fixed in version 1.2.16, with the following patch: http://oss.oetiker.ch/rrdtool-trac/changeset?new=938&new_path=branches% 2F1.2%2Fprogram%2Fsrc%2Frrd_not_thread_safe.c&old=920&old_path=branches% 2F1.2%2Fprogram%2Fsrc%2Frrd_not_thread_safe.c This patch is attached to this mail. I'm also attaching a python script which reproduces this bug. It depends on python-rrd. See the first lines for more explanations
Index: branches/1.2/program/src/rrd_not_thread_safe.c =================================================================== --- branches/1.2/program/src/rrd_not_thread_safe.c (revision 860) +++ branches/1.2/program/src/rrd_not_thread_safe.c (revision 935) @@ -15,18 +15,24 @@ #define ERRBUFLEN 256 -static char rrd_error[MAXLEN] = "\0"; -static char rrd_liberror[ERRBUFLEN] = "\0"; +static char rrd_error[MAXLEN+10]; +static char rrd_liberror[ERRBUFLEN+10]; +static int rrd_context_init = 0; /* The global context is very useful in the transition period to even more thread-safe stuff, it can be used whereever we need a context and do not need to worry about concurrency. */ static struct rrd_context global_ctx = { - sizeof(rrd_error), - sizeof(rrd_liberror), + MAXLEN, + ERRBUFLEN, rrd_error, rrd_liberror }; -#include <stdarg.h> +/* #include <stdarg.h> */ -struct rrd_context *rrd_get_context() { +struct rrd_context *rrd_get_context(void) { + if (! rrd_context_init ){ + rrd_context_init = 1; + global_ctx.rrd_error[0]='\0'; + global_ctx.lib_errstr[0]='\0'; + } return &global_ctx; }
#!/usr/bin/env python # Depends: python-rrd # Number of ds to use. 40 does not trigger the bug, 45 does #ds_number = 40 ds_number = 45 import time, os, rrdtool filename = "/tmp/test.rrd" if os.path.exists(filename): os.remove(filename) rrd_cmd = [filename, "--step", "300", "--start", str( int(time.time()) - 10 ), 'RRA:AVERAGE:0.5:1:12'] for i in range(ds_number): rrd_cmd.append("DS:ds%s:COUNTER:600:U:U" % i) rrdtool.create(*rrd_cmd) data = str(int(time.time())) for i in range(ds_number + 1): data += ":1000" print "updating..." rrdtool.update(filename, data)