Fixed stack buffer overflow in rrdcached and added more security checks

Resolves: RHEL-173257
This commit is contained in:
Jaroslav Škarvada 2026-05-20 15:06:07 +02:00
parent f9c1e5e34a
commit 97d0f9f249
2 changed files with 263 additions and 1 deletions

View File

@ -0,0 +1,254 @@
diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c
index 54a4ec0..6058501 100644
--- a/src/rrd_daemon.c
+++ b/src/rrd_daemon.c
@@ -334,7 +334,13 @@ static void do_log (int priority, const char *format, ...)
char buffer[32];
pthread_mutex_lock(&log_lock);
time_t now = time(NULL);
- strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", gmtime(&now));
+ struct tm tm_buf;
+
+ if (gmtime_r(&now, &tm_buf) == NULL) {
+ snprintf(buffer, sizeof(buffer), "(time error)");
+ } else {
+ strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_buf);
+ }
fprintf(log_fh, "%s [%d] ", buffer, priority);
vfprintf(log_fh, format, args);
fprintf(log_fh, "\n");
@@ -555,7 +561,7 @@ static int check_pidfile(void)
{
int pid_fd;
pid_t pid;
- char pid_str[16];
+ char pid_str[16] = {0};
pid_fd = open_pidfile("open", O_RDWR);
if (pid_fd < 0){
@@ -740,11 +746,7 @@ static int add_response_info(listen_socket_t *sock, char *fmt, ...) /* {{{ */
if (sock->batch_start) return 0; /* no extra info returned when in BATCH */
va_start(argp, fmt);
-#ifdef HAVE_VSNPRINTF
len = vsnprintf(buffer, sizeof(buffer), fmt, argp);
-#else
- len = vsprintf(buffer, fmt, argp);
-#endif
va_end(argp);
if (len < 0)
{
@@ -829,14 +831,12 @@ static int send_response (listen_socket_t *sock, response_code rc,
rc = RESP_OK;
} else {
rclen = snprintf(buffer, sizeof buffer, "%d ", lines);
+ if (rclen < 0 || rclen >= (int) sizeof(buffer))
+ return -1;
}
va_start(argp, fmt);
-#ifdef HAVE_VSNPRINTF
len = vsnprintf(buffer+rclen, sizeof(buffer)-rclen, fmt, argp);
-#else
- len = vsprintf(buffer+rclen, fmt, argp);
-#endif
va_end(argp);
if (len < 0)
return -1;
@@ -2301,7 +2301,8 @@ static int handle_request_create (HANDLER_PROTO) /* {{{ */
char *file_copy = NULL, *dir = NULL, *dir2 = NULL;
char *tok;
int ac = 0;
- char *av[128];
+#define MAX_CREATE_AV 128
+ char *av[MAX_CREATE_AV];
char **sources = NULL;
int sources_length = 0;
char *template = NULL;
@@ -2408,8 +2409,26 @@ static int handle_request_create (HANDLER_PROTO) /* {{{ */
no_overwrite = 1;
continue;
}
- if( ! strncmp(tok,"DS:",3) ) { av[ac++]=tok; continue; }
- if( ! strncmp(tok,"RRA:",4) ) { av[ac++]=tok; continue; }
+ if( ! strncmp(tok,"DS:",3) ) {
+ if (ac >= MAX_CREATE_AV) {
+ rc = send_response(sock, RESP_ERR,
+ "Too many DS/RRA definitions (max %d)\n",
+ MAX_CREATE_AV);
+ goto done;
+ }
+ av[ac++]=tok;
+ continue;
+ }
+ if( ! strncmp(tok,"RRA:",4) ) {
+ if (ac >= MAX_CREATE_AV) {
+ rc = send_response(sock, RESP_ERR,
+ "Too many DS/RRA definitions (max %d)\n",
+ MAX_CREATE_AV);
+ goto done;
+ }
+ av[ac++]=tok;
+ continue;
+ }
rc = syntax_error(sock,cmd);
goto done;
}
diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index d21415e..654bf7c 100644
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
@@ -2471,7 +2471,7 @@ int draw_horizontal_grid(
}
}
} else {
- sprintf(graph_label, im->primary_axis_format,
+ snprintf(graph_label, sizeof(graph_label), im->primary_axis_format,
scaledstep * (double) i, sisym);
}
}
@@ -3797,10 +3797,14 @@ static cairo_status_t cairo_output(
{
image_desc_t *im = (image_desc_t*)closure;
- im->rendered_image =
- (unsigned char*)realloc(im->rendered_image, im->rendered_image_size + length);
- if (im->rendered_image == NULL)
- return CAIRO_STATUS_WRITE_ERROR;
+ {
+ unsigned char *tmp =
+ (unsigned char *) realloc(im->rendered_image,
+ im->rendered_image_size + length);
+ if (tmp == NULL)
+ return CAIRO_STATUS_WRITE_ERROR;
+ im->rendered_image = tmp;
+ }
memcpy(im->rendered_image + im->rendered_image_size, data, length);
im->rendered_image_size += length;
return CAIRO_STATUS_SUCCESS;
@@ -4089,6 +4093,15 @@ int graph_paint_timestring(
(double *) malloc(sizeof(double) * im->xsize * 2);
int drawem = 0;
+ if (foreY == NULL || foreX == NULL ||
+ backY == NULL || backX == NULL) {
+ free(foreY);
+ free(foreX);
+ free(backY);
+ free(backX);
+ return -1;
+ }
+
for (ii = 0; ii <= im->xsize; ii++) {
double ybase, ytop;
@@ -5736,6 +5749,12 @@ int vdef_calc(
case VDEF_PERCENT:{
rrd_value_t *array;
int field;
+ if (steps == 0) {
+ dst->vf.val = DNAN;
+ dst->vf.when = 0;
+ dst->vf.never = 1;
+ break;
+ }
if ((array = (rrd_value_t*)malloc(steps * sizeof(double))) == NULL) {
rrd_set_error("malloc VDEV_PERCENT");
return -1;
@@ -5765,6 +5784,12 @@ int vdef_calc(
if (!isnan(data[step * src->ds_cnt])) { nancount++; }
}
/* and allocate it */
+ if (nancount == 0) {
+ dst->vf.val = DNAN;
+ dst->vf.when = 0;
+ dst->vf.never = 1;
+ break;
+ }
if ((array = (rrd_value_t*)malloc(nancount * sizeof(double))) == NULL) {
rrd_set_error("malloc VDEV_PERCENT");
return -1;
diff --git a/src/rrd_graph_helper.c b/src/rrd_graph_helper.c
index 5632e67..e28c424 100644
--- a/src/rrd_graph_helper.c
+++ b/src/rrd_graph_helper.c
@@ -870,7 +870,7 @@ static int parse_xport(enum gf_en,parsedargs_t*,image_desc_t *const);
static void legend_shift(char *legend)
{
if (!legend || !legend[0]) { return; }
- memmove(legend+2,legend,strlen(legend));
+ memmove(legend+2,legend,strlen(legend)+1);
legend[0]=' ';
legend[1]=' ';
}
diff --git a/src/rrd_xport.c b/src/rrd_xport.c
index 04a449c..3f01a40 100644
--- a/src/rrd_xport.c
+++ b/src/rrd_xport.c
@@ -357,6 +357,16 @@ static int rrd_xport_fn(
/* printf("step: %lu\n",*step); */
free(step_list);
+ if (*step == 0) {
+ rrd_set_error("xport step is zero");
+ free(ref_list);
+ for (unsigned long k = *col_cnt; k > 0; k--)
+ free(legend_list[k - 1]);
+ *col_cnt = 0;
+ free(legend_list);
+ return (-1);
+ }
+
*start = im->start - im->start % (*step);
*end = im->end - im->end % (*step);
@@ -371,26 +381,30 @@ static int rrd_xport_fn(
(rrd_value_t *) malloc((*col_cnt) * row_cnt *
sizeof(rrd_value_t))) == NULL) {
free(ref_list);
+ for (unsigned long k = *col_cnt; k > 0; k--)
+ free(legend_list[k - 1]);
+ *col_cnt = 0;
free(legend_list);
rrd_set_error("malloc xport data area");
return (-1);
}
dstptr = (*data);
+ long unsigned int chosen_idx = 0;
/* fill data structure */
- for (dst_row = 0; (int) dst_row < (int) row_cnt; dst_row++) {
- for (i = 0; i < (int) (*col_cnt); i++) {
+ for (dst_row = 0; dst_row < row_cnt; dst_row++) {
+ for (i = 0; (unsigned long) i < *col_cnt; i++) {
long vidx = im->gdes[ref_list[i]].vidx;
time_t now = *start + dst_row * *step;
- (*dstptr++) = im->gdes[vidx].data[(unsigned long)
- floor((double)
- (now -
- im->gdes[vidx].start)
- / im->gdes[vidx].step)
- * im->gdes[vidx].ds_cnt +
- im->gdes[vidx].ds];
+ if (im->gdes[vidx].step > 0 &&
+ now >= im->gdes[vidx].start) {
+ chosen_idx = floor((double) (now - im->gdes[vidx].start) / im->gdes[vidx].step) * im->gdes[vidx].ds_cnt + im->gdes[vidx].ds;
+ (*dstptr++) = im->gdes[vidx].data[chosen_idx];
+ } else {
+ (*dstptr++) = DNAN;
+ }
}
}
@@ -963,6 +977,9 @@ static void escapeJSON(
size_t l = strlen(txt);
size_t pos = 0;
+ if (tmp == NULL)
+ return;
+
/* now iterate over the chars */
for (size_t i = 0; (i < l) && (pos < len); i++, pos++) {
switch (txt[i]) {

View File

@ -18,7 +18,7 @@
Summary: Round Robin Database Tool to store and display time-series data
Name: rrdtool
Version: 1.7.2
Release: 21%{?dist}
Release: 22%{?dist}
License: GPLv2+ with exceptions
URL: https://oss.oetiker.ch/rrdtool/
Source0: https://oss.oetiker.ch/%{name}/pub/%{name}-%{version}.tar.gz
@ -30,6 +30,9 @@ Patch3: rrdtool-1.6.0-ruby-2-fix.patch
# enable php bindings on ppc
Patch4: rrdtool-1.4.8-php-ppc-fix.patch
Patch5: rrdtool-1.7.2-python-rpath-fix.patch
# backported from:
# https://github.com/oetiker/rrdtool-1.x/commit/4218ec7127ba6c7ea1c20d7c8ea6e2b3f83df73a
Patch6: rrdtool-1.7.2-CVE-2026-43958.patch
Requires: dejavu-sans-mono-fonts
Requires(post): systemd
@ -167,6 +170,7 @@ The %{name}-lua package includes RRDtool bindings for Lua.
%endif
%patch4 -p1 -b .php-ppc-fix
%patch5 -p1 -b .python-rpath-fix
%patch6 -p1 -b .CVE-2026-43958
# Fix to find correct python dir on lib64
perl -pi -e 's|get_python_lib\(0,0,prefix|get_python_lib\(1,0,prefix|g' \
@ -396,6 +400,10 @@ LD_LIBRARY_PATH=%{buildroot}%{_libdir} php -n \
%endif
%changelog
* Wed May 20 2026 Jaroslav Škarvada <jskarvad@redhat.com> - 1.7.2-22
- Fixed stack buffer overflow in rrdcached and added more security checks
Resolves: RHEL-173257
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 1.7.2-21
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688