Hi Niklas,

On Wed, Feb 1, 2017 at 7:02 PM, Niklas Edmundsson <[email protected]> wrote:
>
> We've started to see spurious segfaults with httpd 2.4.25, mpm_event, ssl on
> Ubuntu 14.04LTS. Not frequent, but none the less happening.
>
> #4  ssl_io_filter_output (f=0x7f507013cfe0, bb=0x7f4f840be168) at
> ssl_engine_io.c:1746
>         data = 0x7f5075518000 <error: Cannot access memory at address
> 0x7f5075518000>
>         len = 4194304
>         bucket = 0x7f4f840b1ba8
>         status = <optimized out>
>         filter_ctx = 0x7f507013cf88
>         inctx = <optimized out>
>         outctx = 0x7f507013d008
>         rblock = APR_NONBLOCK_READ

I suspect some cleanup ordering issue happening in
ssl_io_filter_output(), when the EOC bucket is found.

>
> Are we hitting a corner case of process cleanup that plays merry hell with
> https/ssl, or are we just having bad luck? Ideas? Suggestions?

2.4.25 is eager to terminate/shutdown keepalive connections more
quickly (than previous versions) on graceful shutdown (e.g.
MaxConnectionsPerChild reached).

What might happen in ssl_io_filter_output() is that buffered output
data (already deleted but not cleared) end up being reused on
shutdown.

Could you please try the attached patch?


Regards,
Yann.
Index: modules/ssl/ssl_engine_io.c
===================================================================
--- modules/ssl/ssl_engine_io.c	(revision 1781324)
+++ modules/ssl/ssl_engine_io.c	(working copy)
@@ -138,6 +138,7 @@ static int bio_filter_out_pass(bio_filter_out_ctx_
 
     outctx->rc = ap_pass_brigade(outctx->filter_ctx->pOutputFilter->next,
                                  outctx->bb);
+    apr_brigade_cleanup(outctx->bb);
     /* Fail if the connection was reset: */
     if (outctx->rc == APR_SUCCESS && outctx->c->aborted) {
         outctx->rc = APR_ECONNRESET;
@@ -1699,13 +1700,12 @@ static apr_status_t ssl_io_filter_output(ap_filter
     while (!APR_BRIGADE_EMPTY(bb) && status == APR_SUCCESS) {
         apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
 
-        if (APR_BUCKET_IS_METADATA(bucket)) {
+        if (APR_BUCKET_IS_METADATA(bucket) || !filter_ctx->pssl) {
             /* Pass through metadata buckets untouched.  EOC is
              * special; terminate the SSL layer first. */
             if (AP_BUCKET_IS_EOC(bucket)) {
                 ssl_filter_io_shutdown(filter_ctx, f->c, 0);
             }
-            AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(outctx->bb));
 
             /* Metadata buckets are passed one per brigade; it might
              * be more efficient (but also more complex) to use
@@ -1712,11 +1712,10 @@ static apr_status_t ssl_io_filter_output(ap_filter
              * outctx->bb as a true buffer and interleave these with
              * data buckets. */
             APR_BUCKET_REMOVE(bucket);
-            APR_BRIGADE_INSERT_HEAD(outctx->bb, bucket);
-            status = ap_pass_brigade(f->next, outctx->bb);
-            if (status == APR_SUCCESS && f->c->aborted)
-                status = APR_ECONNRESET;
-            apr_brigade_cleanup(outctx->bb);
+            APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket);
+            if (bio_filter_out_pass(outctx) < 0) {
+                status = outctx->rc;
+            }
         }
         else {
             /* Filter a data bucket. */

Reply via email to