Opened 7 months ago

Closed 7 months ago

Last modified 7 months ago

#1646 closed defect (fixed)

Nginx 1.15.4 segfault during normal ssllabs.com test

Reported by: marcin.wanat@… Owned by: mdounin
Priority: major Milestone:
Component: other Version: 1.15.x
Keywords: Cc:
uname -a: Linux local 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.15.4 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) built with OpenSSL 1.1.1 11 Sep 2018 TLS SNI support enabled configure arguments: --prefix=/usr/local/nginx --with-threads --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module --with-openssl=../openssl-1.1.1

Description

I have compiled latest nginx 1.15.4 and noticed that it segfault every time when trying to do ssllabs test (https://www.ssllabs.com/ssltest/) on any vhost. It always segfault during "Testing renegotiation" stage. I have generated core dump and backtrace is always the same:

backtrace
#0 ngx_http_ssl_servername (ssl_conn=0x1eccef0, ad=0x7ffd4e5949d0, arg=0x0) at src/http/ngx_http_request.c:878
#1 0x000000000057bc9f in ssl_parse_clienthello_tlsext ()
#2 0x000000000057227e in tls_process_client_hello ()
#3 0x00000000005678bd in state_machine ()
#4 0x000000000054fd42 in ssl3_read_bytes ()
#5 0x00000000005556a5 in ssl3_read ()
#6 0x000000000055edc9 in SSL_read ()
#7 0x0000000000495f76 in ngx_ssl_recv (c=0x1c18a40, buf=0x1efb21a "", size=886) at src/event/ngx_event_openssl.c:1746
#8 0x00000000004b00ed in ngx_http_read_request_header (r=0x1da0e60) at src/http/ngx_http_request.c:1418
#9 0x00000000004afc46 in ngx_http_process_request_headers (rev=0x1c8f730) at src/http/ngx_http_request.c:1285
#10 0x0000000000491415 in ngx_epoll_process_events (cycle=0x162e050, timer=42349, flags=1) at src/event/modules/ngx_epoll_module.c:902
#11 0x0000000000481540 in ngx_process_events_and_timers (cycle=0x162e050) at src/event/ngx_event.c:242
#12 0x000000000048ebe8 in ngx_worker_process_cycle (cycle=0x162e050, data=0x0) at src/os/unix/ngx_process_cycle.c:750
#13 0x000000000048bac8 in ngx_spawn_process (cycle=0x162e050, proc=0x48eb3a <ngx_worker_process_cycle>, data=0x0, name=0x6e7ee8 "worker process", respawn=-3) at src/os/unix/ngx_process.c:199
#14 0x000000000048ddfd in ngx_start_worker_processes (cycle=0x162e050, n=4, type=-3) at src/os/unix/ngx_process_cycle.c:359
#15 0x000000000048d54d in ngx_master_process_cycle (cycle=0x162e050) at src/os/unix/ngx_process_cycle.c:131
#16 0x000000000044e751 in main (argc=1, argv=0x7ffd4e5953d8) at src/core/nginx.c:382

Tested on different servers and OSes (Fedora 28, Centos 7.5) with different configs, every time it results in segfault. The same problem exists when compiled with openssl-1.1.1 or with openssl-1.1.0i.

My test config is:

worker_processes 4;

events {

worker_connections 2048;

}

http {

ssl_dhparam /usr/local/nginx/conf/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

server {

listen xx.xx.xx.xx:443;
server_name www.xxx.com
ssl_certificate /etc/letsencrypt/live/xxx.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.com/privkey.pem;

location / {

root /srv/www;

}

}

Change History (6)

comment:1 Changed 7 months ago by marcin.wanat@…

I do apologize for lact of formatting, but it looks like i cannot edit it now.

comment:2 Changed 7 months ago by mdounin

  • Owner set to mdounin
  • Status changed from new to assigned

Thanks for the report. The following patch should fix this:

# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 1538490291 -10800
#      Tue Oct 02 17:24:51 2018 +0300
# Node ID 7a99ccd1c7dcd9f2863c61c775358c2306f48282
# Parent  7bf3c323cb6e15e73dc612b56ee973d06ab15542
SSL: fixed segfault on renegotiation (ticket #1646).

In e3ba4026c02d (1.15.4) nginx own renegotiation checks were disabled
if SSL_OP_NO_RENEGOTIATION is available.  But since SSL_OP_NO_RENEGOTIATION
is only set on a connection, not in an SSL context, SSL_clear_option()
removed it as long as a matching virtual server was found.  This resulted
in a segmentation fault similar to one fixed in a6902a941279 (1.9.8),
affecting nginx built with OpenSSL 1.1.0h or higher.

To fix this, SSL_OP_NO_RENEGOTIATION is now explicitly set in
ngx_http_ssl_servername() after adjusting options.  Additionally, instead
of c->ssl->renegotiation we now check c->ssl->handshaked, which seems
to be a more correct flag to test, and will prevent the segmentation fault
from happening even if SSL_OP_NO_RENEGOTIATION is not working.

diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -854,7 +854,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *
 
     c = ngx_ssl_get_connection(ssl_conn);
 
-    if (c->ssl->renegotiation) {
+    if (c->ssl->handshaked) {
         return SSL_TLSEXT_ERR_NOACK;
     }
 
@@ -919,6 +919,10 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *
 #endif
 
         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
+
+#ifdef SSL_OP_NO_RENEGOTIATION
+        SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION);
+#endif
     }
 
     return SSL_TLSEXT_ERR_OK;

comment:3 Changed 7 months ago by marcin.wanat@…

Thank you for fast reply!
It looks like the patch has fixed problem with ssllabs test. Will test this now using A/B on production and will reopen this ticket if found any problem related to this patch.

comment:4 Changed 7 months ago by Maxim Dounin <mdounin@…>

In 7367:bf1ac3dc1e68/nginx:

SSL: fixed segfault on renegotiation (ticket #1646).

In e3ba4026c02d (1.15.4) nginx own renegotiation checks were disabled
if SSL_OP_NO_RENEGOTIATION is available. But since SSL_OP_NO_RENEGOTIATION
is only set on a connection, not in an SSL context, SSL_clear_option()
removed it as long as a matching virtual server was found. This resulted
in a segmentation fault similar to the one fixed in a6902a941279 (1.9.8),
affecting nginx built with OpenSSL 1.1.0h or higher.

To fix this, SSL_OP_NO_RENEGOTIATION is now explicitly set in
ngx_http_ssl_servername() after adjusting options. Additionally, instead
of c->ssl->renegotiation we now check c->ssl->handshaked, which seems
to be a more correct flag to test, and will prevent the segmentation fault
from happening even if SSL_OP_NO_RENEGOTIATION is not working.

comment:5 Changed 7 months ago by mdounin

  • Resolution set to fixed
  • Status changed from assigned to closed

Thanks for testing. The fix was committed and now available in nginx 1.15.5 release.

comment:6 Changed 7 months ago by Sergey Kandaurov <pluknet@…>

In 1380:f50c7d90f5c9/nginx-tests:

Tests: more https sni tests with renegotiation (ticket #1646).

Note: See TracTickets for help on using tickets.