fix for buffer overflow when web_buffer is increased
Costa Tsaousis (ktsaou) committed
Apr 7, 2014 at 18:56 UTC
74f1f51f50203401a696564150f0a52bb03569a3
1 file changed
+21
-21
netdata.c
+21
-21
@@ -96,15 +96,15 @@
96
#define CT_IMAGE_SVG_XML 14
97
98
// configuration
99
-#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
99
+#define DEBUG (D_WEB_BUFFER|D_WEB_CLIENT|D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
100
//#define DEBUG 0xffffffff
101
//#define DEBUG (0)
102
103
#define EXIT_FAILURE 1
104
#define LISTEN_BACKLOG 100
105
106
-#define MAX_SOCKET_DATA_LENGTH (256 * 1024)
107
-#define SOCKET_DATA_LENGTH_INCREASE_STEP 65536
106
+#define INITIAL_WEB_DATA_LENGTH 65536
107
+#define WEB_DATA_LENGTH_INCREASE_STEP 65536
108
#define ZLIB_CHUNK 16384
109
110
#define MAX_HTTP_HEADER_SIZE 16384
@@ -699,6 +699,7 @@ void web_buffer_increase(struct web_buffer *b, size_t free_size_required)
699
700
if(left >= free_size_required) return;
701
size_t increase = free_size_required - left;
702
+ if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
703
704
debug(D_WEB_BUFFER, "Increasing data buffer from size %d to %d.", b->size, b->size + increase);
705
@@ -782,7 +783,7 @@ struct web_client *web_client_create(int listener)
783
if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0) error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
784
}
785
785
- w->data = web_buffer_create(MAX_SOCKET_DATA_LENGTH);
786
+ w->data = web_buffer_create(INITIAL_WEB_DATA_LENGTH);
787
if(!w->data) {
788
close(w->ifd);
789
free(w);
@@ -822,7 +823,7 @@ struct web_client *web_client_free(struct web_client *w)
823
824
void rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
825
{
825
- web_buffer_increase(wb, 8192);
826
+ web_buffer_increase(wb, 16384);
827
828
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t{\n");
829
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"id\" : \"%s\",\n", st->id);
@@ -849,7 +850,7 @@ void rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
850
851
void rrd_stats_graph_json(RRD_STATS *st, char *options, struct web_buffer *wb)
852
{
852
- web_buffer_increase(wb, 4096);
853
+ web_buffer_increase(wb, 16384);
854
855
wb->bytes += sprintf(&wb->buffer[wb->bytes], RRD_GRAPH_JSON_HEADER);
856
rrd_stats_one_json(st, options, wb);
@@ -858,7 +859,7 @@ void rrd_stats_graph_json(RRD_STATS *st, char *options, struct web_buffer *wb)
859
860
void rrd_stats_all_json(struct web_buffer *wb)
861
{
861
- web_buffer_increase(wb, 4096);
862
+ web_buffer_increase(wb, 16384);
863
864
size_t c;
865
RRD_STATS *st;
@@ -898,8 +899,6 @@ long long rrd_stats_dimension_get(RRD_DIMENSION *rd, size_t position)
899
900
void rrd_stats_json(RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show, size_t group_count, int group_method)
901
{
901
- char *b = wb->buffer;
902
-
902
pthread_mutex_lock(&st->mutex);
903
904
// check the options
@@ -931,7 +930,7 @@ void rrd_stats_json(RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show
930
931
if(!dimensions) {
932
pthread_mutex_unlock(&st->mutex);
934
- wb->bytes = sprintf(b, "No dimensions yet.");
933
+ wb->bytes = sprintf(wb->buffer, "No dimensions yet.");
934
return;
935
}
936
@@ -941,14 +940,14 @@ void rrd_stats_json(RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show
940
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
941
group_values[c] = group_counts[c] = 0;
942
944
- wb->bytes += sprintf(&b[wb->bytes], "{\n \"cols\":\n [\n");
945
- wb->bytes += sprintf(&b[wb->bytes], " {\"id\":\"\",\"label\":\"time\",\"pattern\":\"\",\"type\":\"datetime\"}");
943
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], "{\n \"cols\":\n [\n");
944
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], " {\"id\":\"\",\"label\":\"time\",\"pattern\":\"\",\"type\":\"datetime\"}");
945
946
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
947
if(!rd->hidden)
949
- wb->bytes += sprintf(&b[wb->bytes], ",\n {\"id\":\"\",\"label\":\"%s\",\"pattern\":\"\",\"type\":\"number\"}", rd->name);
948
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], ",\n {\"id\":\"\",\"label\":\"%s\",\"pattern\":\"\",\"type\":\"number\"}", rd->name);
949
951
- wb->bytes += sprintf(&b[wb->bytes], " ],\n \"rows\":\n [\n");
950
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], " ],\n \"rows\":\n [\n");
951
952
// to allow grouping on the same values, we need a pad
953
pad = current_entry % group_count;
@@ -995,7 +994,7 @@ void rrd_stats_json(RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show
994
sprintf(dtm, "\"Date(%d, %d, %d, %d, %d, %d, %d)\"", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(st->times[t].tv_usec / 1000)); // datetime
995
// strftime(dtm, 200, "\"Date(%Y, %m, %d, %H, %M, %S)\"", tm); // datetime
996
// strftime(dtm, 200, "[%H, %M, %S, 0]", tm); // timeofday
998
- wb->bytes += sprintf(&b[wb->bytes], "%s {\"c\":[{\"v\":%s}", printed?"]},\n":"", dtm);
997
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], "%s {\"c\":[{\"v\":%s}", printed?"]},\n":"", dtm);
998
999
printed++;
1000
}
@@ -1048,15 +1047,15 @@ void rrd_stats_json(RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show
1047
1048
if(((count-pad) % group_count) == 0) {
1049
if(!rd->hidden)
1051
- wb->bytes += sprintf(&b[wb->bytes], ",{\"v\":%0.1Lf}", group_values[c]);
1052
- //wb->bytes += sprintf(&b[wb->bytes], ",{\"v\":%lld}", group_values[c]);
1050
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{\"v\":%0.1Lf}", group_values[c]);
1051
+ //wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{\"v\":%lld}", group_values[c]);
1052
1053
group_values[c] = group_counts[c] = 0;
1054
}
1055
}
1056
}
1058
- if(printed) wb->bytes += sprintf(&b[wb->bytes], "]}");
1059
- wb->bytes += sprintf(&b[wb->bytes], "\n ]\n}\n");
1057
+ if(printed) wb->bytes += sprintf(&wb->buffer[wb->bytes], "]}");
1058
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ]\n}\n");
1059
1060
pthread_mutex_unlock(&st->mutex);
1061
}
@@ -1450,6 +1449,7 @@ void web_client_process(struct web_client *w)
1449
}
1450
1451
gettimeofday(&w->tv_ready, NULL);
1452
+ debug(D_WEB_CLIENT, "%llu: Generated response of %ld bytes in %llu microseconds.", w->id, w->data->bytes, usecdiff(&w->tv_ready, &w->tv_in));
1453
w->data->date = time(NULL);
1454
w->data->sent = 0;
1455
@@ -1604,7 +1604,7 @@ void web_client_process(struct web_client *w)
1604
if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) error("%llu: failed to disable TCP_NODELAY on socket.", w->id);
1605
1606
// sent the HTTP header
1607
- debug(D_WEB_CLIENT, "%llu: Sending response HTTP header of size %d: '%s'", w->id, headerlen, w->response_header);
1607
+ debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %d: '%s'", w->id, headerlen, w->response_header);
1608
1609
bytes = send(w->ofd, w->response_header, headerlen, 0);
1610
if(bytes != headerlen)
@@ -1832,7 +1832,7 @@ ssize_t web_client_send(struct web_client *w)
1832
ssize_t web_client_receive(struct web_client *w)
1833
{
1834
// do we have any space for more data?
1835
- web_buffer_increase(w->data, SOCKET_DATA_LENGTH_INCREASE_STEP);
1835
+ web_buffer_increase(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
1836
1837
ssize_t left = w->data->size - w->data->bytes;
1838
ssize_t bytes;