1818
1919#include <apr_base64.h>
2020
21-
2221/* Those are defined twice, lets keep it defined just once by `undef`
2322 * the first one.
2423 */
3130#define NOTE_NGINX_REQUEST_CTX "nginx-ctx"
3231#define TXID_SIZE 25
3332
33+ /*
34+ * If MOVE_REQUEST_CHAIN_TO_MODSEC is set, the chain will be moved into the
35+ * ModSecurity brigade, after be processed by ModSecurity, it needs to be moved
36+ * to nginx chains again, in order to be processed by other modules. It seems
37+ * that this is not working well whenever the request body is delivered into
38+ * chunks. Resulting in segfaults.
39+ *
40+ * If MOVE_REQUEST_CHAIN_TO_MODSEC is _not_ set, a copy of the request body
41+ * will be delivered to ModSecurity and after processed it will be released,
42+ * not modifying the nginx chain.
43+ *
44+ * The malfunctioning can be observer while running the following regression
45+ * tests:
46+ * #15 - SecRequestBodyInMemoryLimit
47+ * #16 - SecRequestBodyInMemoryLimit (greater)
48+ * #19 - SecRequestBodyLimitAction ProcessPartial (multipart/greater - chunked)
49+ * (from: regression/config/10-request-directives.t)
50+ */
51+ /*
52+ #define MOVE_REQUEST_CHAIN_TO_MODSEC
53+ */
54+
55+
3456#define tuxb
3557
3658/*
@@ -492,8 +514,8 @@ ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const
492514static ngx_inline ngx_int_t
493515ngx_http_modsecurity_load_request_body (ngx_http_request_t * r )
494516{
495- ngx_http_modsecurity_ctx_t * ctx ;
496-
517+ ngx_http_modsecurity_ctx_t * ctx ;
518+ ngx_chain_t * chain ;
497519
498520 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
499521 "ModSec: loading request body." );
@@ -502,33 +524,47 @@ ngx_http_modsecurity_load_request_body(ngx_http_request_t *r)
502524
503525 modsecSetBodyBrigade (ctx -> req , ctx -> brigade );
504526
505- if (r -> request_body == NULL || r -> request_body -> bufs == NULL ) {
506- ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
507- "ModSec: request was null." );
508-
509- return move_chain_to_brigade (NULL , ctx -> brigade , r -> pool , 1 );
527+ if (r -> request_body == NULL ) {
528+ chain = NULL ;
510529 }
530+ else {
531+ chain = r -> request_body -> bufs ;
532+ }
533+
511534
512- if (move_chain_to_brigade (r -> request_body -> bufs , ctx -> brigade , r -> pool , 1 ) != NGX_OK ) {
535+ #ifdef MOVE_REQUEST_CHAIN_TO_MODSEC
536+ if (move_chain_to_brigade (chain , ctx -> brigade , r -> pool , 1 ) != NGX_OK ) {
513537 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
514538 "ModSec: failed to move chain to brigade." );
515539
516540 return NGX_ERROR ;
517541 }
518542
519543 r -> request_body = NULL ;
544+ #else
545+ if (copy_chain_to_brigade (chain , ctx -> brigade , r -> pool , 1 ) != NGX_OK ) {
546+ ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
547+ "ModSec: failed to copy chain to brigade." );
548+
549+ return NGX_ERROR ;
550+ }
551+ #endif
520552
521553 return NGX_OK ;
522554}
523555
524556static ngx_inline ngx_int_t
525557ngx_http_modsecurity_save_request_body (ngx_http_request_t * r )
526558{
527- ngx_http_modsecurity_ctx_t * ctx ;
528- apr_off_t content_length ;
529- ngx_buf_t * buf ;
530- ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity );
559+ ngx_http_modsecurity_ctx_t * ctx ;
560+ #ifdef MOVE_REQUEST_CHAIN_TO_MODSEC
561+ apr_off_t content_length ;
562+ ngx_buf_t * buf ;
563+ #endif
564+
565+ ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity );
531566
567+ #ifdef MOVE_REQUEST_CHAIN_TO_MODSEC
532568 apr_brigade_length (ctx -> brigade , 0 , & content_length );
533569
534570 buf = ngx_create_temp_buf (ctx -> r -> pool , (size_t ) content_length );
@@ -550,10 +586,15 @@ ngx_http_modsecurity_save_request_body(ngx_http_request_t *r)
550586
551587 }
552588
553-
554589 r -> headers_in .content_length_n = content_length ;
555590
556- ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , "ModSec: Content length: %O, Content length n: %O" , content_length , r -> headers_in .content_length_n );
591+ ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
592+ "ModSec: Content length: %O, Content length n: %O" , content_length ,
593+ r -> headers_in .content_length_n );
594+ #else
595+ apr_brigade_cleanup (ctx -> brigade );
596+ #endif
597+
557598 return NGX_OK ;
558599}
559600
@@ -787,7 +828,7 @@ ngx_http_modsecurity_status(ngx_http_request_t *r, int status)
787828 * @param r pointer to ngx_http_request_t.
788829 *
789830 */
790- static void
831+ ngx_int_t
791832ngx_http_modsecurity_process_request (ngx_http_request_t * r )
792833{
793834 ngx_int_t rc = 0 ;
@@ -802,23 +843,21 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
802843 if (ngx_http_modsecurity_load_request (r ) != NGX_OK ) {
803844 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
804845 "ModSec: failed while loading the request." );
805- ngx_http_finalize_request (r , NGX_HTTP_INTERNAL_SERVER_ERROR );
806- goto terminate ;
846+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
807847 }
808848
809849 if (ngx_http_modsecurity_load_headers_in (r ) != NGX_OK ) {
810850 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
811851 "ModSec: failed while loading the headers." );
812- ngx_http_finalize_request (r , NGX_HTTP_INTERNAL_SERVER_ERROR );
813- goto terminate ;
852+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
814853 }
815854
816855 rc = modsecProcessRequestHeaders (ctx -> req );
817856 rc = ngx_http_modsecurity_status (r , rc );
818857 if (rc != NGX_DECLINED ) {
819858 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
820859 "ModSec: failed while processing the request headers" );
821- ngx_http_finalize_request ( r , rc ) ;
860+ return rc ;
822861 }
823862
824863 /* Here we check if ModSecurity is enabled or disabled again.
@@ -841,12 +880,15 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
841880 }
842881
843882 if (load_request_body == 1 ) {
883+ ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
884+ "ModSec: loading request body..." );
885+
844886 rc = ngx_http_modsecurity_load_request_body (r );
845887 if (rc != NGX_OK )
846888 {
847889 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
848890 "ModSec: failed while loading the request body." );
849- ngx_http_finalize_request ( r , NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
891+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
850892 }
851893
852894
@@ -862,24 +904,23 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
862904 "ModSec: finalizing the connection after process the " \
863905 "request body." );
864906
865- ngx_http_finalize_request ( r , rc ) ;
907+ return rc ;
866908 }
867909 if (load_request_body == 1 ) {
868910 if (ngx_http_modsecurity_save_request_body (r ) != NGX_OK )
869911 {
870912 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
871913 "ModSec: failed while saving the request body" );
872- ngx_http_finalize_request ( r , NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
914+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
873915 }
874916 if (ngx_http_modsecurity_save_headers_in (r ) != NGX_OK )
875917 {
876918 ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
877919 "ModSec: failed while saving the headers in" );
878- ngx_http_finalize_request ( r , NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
920+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
879921 }
880922 }
881- terminate :
882- return ;
923+ return NGX_OK ;
883924}
884925
885926
@@ -1102,14 +1143,22 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r) {
11021143
11031144 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
11041145 "ModSec: request is ready to be processed." );
1105- ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
1106- "ModSec: chuncked? %d" , r -> chunked );
1107- ngx_http_modsecurity_process_request (r );
1146+ rc = ngx_http_modsecurity_process_request (r );
11081147 ctx -> request_processed = 1 ;
1148+
1149+ if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE ) {
1150+ ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
1151+ "ModSec: returning a special response after process " \
1152+ "a request: %d" , rc );
1153+
1154+ return rc ;
1155+ }
1156+
1157+
11091158 }
11101159
11111160 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
1112- "ModSec: returning NGX_OK. Count++ :P " );
1161+ "ModSec: returning NGX_DECLINED. " );
11131162
11141163 return NGX_DECLINED ;
11151164}
0 commit comments