From 6406e2108db29697501a84015e46296b8d09356d Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Thu, 5 Oct 2017 18:25:52 +0000 Subject: [PATCH] Makes `large stream optimization' optional --- apache2/apache2_io.c | 6 ++++- apache2/modsecurity.h | 3 +++ apache2/msc_reqbody.c | 53 ++++++++++++++++++++++++++++++++++++++++-- apache2/re_operators.c | 9 ++++++- configure.ac | 18 +++++++++++++- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/apache2/apache2_io.c b/apache2/apache2_io.c index 9007f9d5..2e7325dc 100644 --- a/apache2/apache2_io.c +++ b/apache2/apache2_io.c @@ -192,7 +192,6 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) { if (msr->txcfg->debuglog_level >= 4) { msr_log(msr, 4, "Input filter: Reading request body."); } - if (modsecurity_request_body_start(msr, error_msg) < 0) { return -1; } @@ -283,9 +282,14 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) { } if (msr->txcfg->stream_inbody_inspection == 1) { +#ifndef MSC_LARGE_STREAM_INPUT + msr->stream_input_length+=buflen; + modsecurity_request_body_to_stream(msr, buf, buflen, error_msg); +#else if (modsecurity_request_body_to_stream(msr, buf, buflen, error_msg) < 0) { return -1; } +#endif } msr->reqbody_length += buflen; diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index 601b5f24..f24bc756 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -287,7 +287,10 @@ struct modsec_rec { unsigned int resbody_contains_html; apr_size_t stream_input_length; +#ifdef MSC_LARGE_STREAM_INPUT apr_size_t stream_input_allocated_length; +#endif + char *stream_input_data; apr_size_t stream_output_length; char *stream_output_data; diff --git a/apache2/msc_reqbody.c b/apache2/msc_reqbody.c index ebf4e516..fc6b380b 100644 --- a/apache2/msc_reqbody.c +++ b/apache2/msc_reqbody.c @@ -428,9 +428,59 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr, } apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, const char *buffer, int buflen, char **error_msg) { +#ifndef MSC_LARGE_STREAM_INPUT + char *stream_input_body = NULL; + char *data = NULL; + int first_pkt = 0; +#else apr_size_t allocate_length = 0; char* allocated = NULL; +#endif +#ifndef MSC_LARGE_STREAM_INPUT + if(msr->stream_input_data == NULL) { + msr->stream_input_data = (char *)calloc(sizeof(char), msr->stream_input_length + 1); + first_pkt = 1; + } + else { + + data = (char *)malloc(msr->stream_input_length + 1 - buflen); + + if(data == NULL) + return -1; + + memset(data, 0, msr->stream_input_length + 1 - buflen); + memcpy(data, msr->stream_input_data, msr->stream_input_length - buflen); + + stream_input_body = (char *)realloc(msr->stream_input_data, msr->stream_input_length + 1); + + msr->stream_input_data = (char *)stream_input_body; + } + + if (msr->stream_input_data == NULL) { + if(data) { + free(data); + data = NULL; + } + *error_msg = apr_psprintf(msr->mp, "Unable to allocate memory to hold request body on stream. Asked for %" APR_SIZE_T_FMT " bytes.", + msr->stream_input_length + 1); + return -1; + } + + memset(msr->stream_input_data, 0, msr->stream_input_length+1); + + if(first_pkt) { + memcpy(msr->stream_input_data, buffer, msr->stream_input_length); + } else { + memcpy(msr->stream_input_data, data, msr->stream_input_length - buflen); + memcpy(msr->stream_input_data+(msr->stream_input_length - buflen), buffer, buflen); + } + + if(data) { + free(data); + data = NULL; + } +#else if (msr->stream_input_data == NULL) { // Is the request body length known beforehand? (requests that are not Transfer-Encoding: chunked) if (msr->request_content_length > 0) { @@ -458,7 +508,6 @@ apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, const char *buf else { // Do we need to expand the space we have previously allocated? if ((msr->stream_input_length + buflen) > msr->stream_input_allocated_length) { - // If this becomes a hotspot again, consider increasing by some percent extra each time, for fewer reallocs allocate_length = msr->stream_input_length + buflen; @@ -480,10 +529,10 @@ apr_status_t modsecurity_request_body_to_stream(modsec_rec *msr, const char *buf } } } - // Append buffer to msr->stream_input_data memcpy(msr->stream_input_data + msr->stream_input_length, buffer, buflen); msr->stream_input_length += buflen; +#endif return 1; } diff --git a/apache2/re_operators.c b/apache2/re_operators.c index 05db118f..b6d1c03c 100644 --- a/apache2/re_operators.c +++ b/apache2/re_operators.c @@ -634,18 +634,25 @@ nextround: free(msr->stream_input_data); msr->stream_input_data = NULL; msr->stream_input_length = 0; +#ifdef MSC_LARGE_STREAM_INPUT msr->stream_input_allocated_length = 0; msr->stream_input_data = (char *)malloc(size); +#else + msr->stream_input_data = (char *)malloc(size+1); +#endif if(msr->stream_input_data == NULL) { return -1; } msr->stream_input_length = size; +#ifdef MSC_LARGE_STREAM_INPUT msr->stream_input_allocated_length = size; memset(msr->stream_input_data, 0x0, size); - +#else + memset(msr->stream_input_data, 0x0, size+1); +#endif msr->if_stream_changed = 1; memcpy(msr->stream_input_data, data, size); diff --git a/configure.ac b/configure.ac index e3a3595f..01d2fb4b 100644 --- a/configure.ac +++ b/configure.ac @@ -690,6 +690,22 @@ AC_ARG_ENABLE(modsec-api, modsec_api= ]) +# MSC_LARGE_STREAM_INPUT +AC_ARG_ENABLE(large-stream-input, + AS_HELP_STRING([--enable-large-stream-input], + [Enable optimization for large stream input]), +[ + if test "$enableval" == "yes"; then + large_stream_input="-DMSC_LARGE_STREAM_INPUT" + MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS $large_stream_input" + else + large_stream_input= + fi +], +[ + large_stream_input= +]) + # Find apxs AC_MSG_NOTICE(looking for Apache module support via DSO through APXS) AC_ARG_WITH(apxs, @@ -812,7 +828,7 @@ else fi fi -MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $htaccess_config $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_context $collection_global_lock" +MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $htaccess_config $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api $cpu_type $unique_id $log_filename $log_server $log_collection_delete_problem $log_dechunk $log_stopwatch $log_handler $log_server_context $collection_global_lock $large_stream_input" APXS_WRAPPER=build/apxs-wrapper APXS_EXTRA_CFLAGS=""