@cryptotaxi247 / netdata-1 / commits / 74f1f51f5

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;