Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

segmentation fault might occur when SSL renegotiation happens #1354

Open
tokers opened this issue Jul 24, 2018 · 4 comments
Open

segmentation fault might occur when SSL renegotiation happens #1354

tokers opened this issue Jul 24, 2018 · 4 comments

Comments

@tokers
Copy link
Contributor

tokers commented Jul 24, 2018

Hello!

Recently I found one of our Nginx worker process exited abnormally (segmentation fault). The backtrace is like:

nginx: worker process(ngx_http_lua_ssl_cert_handler+0x1c2) [0x5b8313]
nginx: worker process(tls_post_process_client_hello+0x1be) [0x7302e9]
nginx: worker process(ossl_statem_server_post_process_message+0x6c) [0x72dd0f]
nginx: worker process(read_state_machine) [0x71b25d]
nginx: worker process(state_machine) [0x71abc1]
nginx: worker process(ossl_statem_accept+0x1d) [0x71a74d]
nginx: worker process(ssl3_read_bytes+0xed4) [0x6e9846]
nginx: worker process(ssl3_read_internal) [0x6f33e9]
nginx: worker process(ssl3_read+0x38)
nginx: worker process(ssl_read_internal+0x165)
nginx: worker process(SSL_read+0x5b)
nginx: worker process(ngx_ssl_recv+0xc5)
nginx: worker process(ngx_http_v2_read_handler)
nginx: worker process(ngx_http_v2_idle_handler+0x116)
nginx: worker process(ngx_epoll_process_events)
nginx: worker process(ngx_process_events_and_timers+0xd3)

The coredump point is inside function ngx_http_lua_ssl_cert_handler.

You can reproduce this problem by the following way.

server {
    listen 8443 ssl http2;
    ssl_certificate_by_lua_block {
        return;
    }
     ssl_certificate /path/to/cert;
     ssl_certificate_key /path/to/pkey;
     location / {
          return 200;
     }
}
openssl s_client -connect 127.0.0.1:8443 -alpn h2 -reconnect

Then type "R" in the interactive mode (trigger the TLS reneogatitaion).

ALPN protocol: h2
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 8C3B8082AEEDC0AF9894C28A7ED50F2B52AA5C2274B4E15509DFEA097B12CB42
    Session-ID-ctx:
    Master-Key: DABD0D31B6A799DB05E199DC89045833480E47EF8F43DC2DDD36A4851C2026DB05A242580928135214395734343EADF7
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 92 bf 74 6e 7f 3d 7a 0b-34 4a 48 18 11 7f 60 31   ..tn.=z.4JH...`1
    0010 - 1e 9b 46 8f 11 62 d6 b2-83 ea 2e d5 45 26 a6 46   ..F..b......E&.F
    0020 - a5 c8 13 48 35 0b 87 fd-26 cd 6e aa c1 0a 35 c9   ...H5...&.n...5.
    0030 - 1b 2f 93 5a d6 9d 11 b6-c2 5a df b0 53 23 b3 b4   ./.Z.....Z..S#..
    0040 - de d8 73 50 b6 61 e5 1b-08 b9 9b b4 22 18 cc e0   ..sP.a......"...
    0050 - 3a 13 c0 d0 db f1 7e 3f-2a 01 14 61 4c 08 0e 4c   :.....~?*..aL..L
    0060 - 63 cb 02 93 92 80 03 64-33 c9 aa b0 d8 63 c8 33   c......d3....c.3
    0070 - 92 b5 c9 4c 35 65 fd 62-f0 fd 53 cf 0b 2f 97 c6   ...L5e.b..S../..
    0080 - b7 bc f3 e0 83 15 3a 94-1a 95 78 68 33 99 dc df   ......:...xh3...
    0090 - 67 b5 e6 4a 16 ca 20 e1-43 85 eb fc 6a 52 01 d7   g..J.. .C...jR..
    00a0 - 9b 51 18 b3 e1 3d 32 fd-80 a3 4e 40 7c 45 7f 0b   .Q...=2...N@|E..
    00b0 - 52 06 b8 07 7e ee c6 d3-16 8b df b4 24 f7 f8 2c   R...~.......$..,
    00c0 - 58 0f e9 86 6a a3 84 70-0e 08 87 b0 84 22 51 a5   X...j..p....."Q.

    Start Time: 1532434389
    Timeout   : 7200 (sec)
    Verify return code: 10 (certificate has expired)
    Extended master secret: yes
---
R
RENEGOTIATING
write:errno=0`

Now open Nginx's error log and we can see:

2018/07/24 19:13:25 [alert] 7573#7573: worker process 7574 exited on signal 11 (core dumped)

After analysis, I found the reason finally. This problem occurs when client performed the SSL renegotiation and the current connection is already upgraded to HTTP/2, furthermore, current connection should reuse a TLS session.

When TLS renegotiation happens, the ngx_http_lua_ssl_cert_handler will be called.

Since current connection reused a TLS session, so the cctx inside this function is still NULL, the following if block will not be executed:

 if (cctx && cctx->entered_cert_handler) {
        /* not the first time */

        if (cctx->done) {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                           "lua_certificate_by_lua: cert cb exit code: %d",
                           cctx->exit_code);

            dd("lua ssl cert done, finally");
            return cctx->exit_code;
        }

        return -1;
    }

Then c->data will be treated as the ngx_http_connection_t, we know when the functionngx_http_v2_init called, the c->data will be set to ngx_http_v2_connection_t (rather than the original ngx_http_connection_t). While ngx_http_lua_ssl_cert_handler doesn't distinguish this situation. It just uses the "ngx_http_v2_connection_t" as "ngx_http_connection_t", and some invalid address will be referenced.

@tokers
Copy link
Contributor Author

tokers commented Jul 24, 2018

I have submitted a PR for the fixup: #1355.

@tokers
Copy link
Contributor Author

tokers commented Jul 25, 2018

ping @agentzh .

@kwanhur
Copy link

kwanhur commented Aug 17, 2018

couldn't reproduce it with nginx-1.13.6+lua-nginx-module-0.10.12rc2+openssl-1.1.0g

@tokers
Copy link
Contributor Author

tokers commented Aug 29, 2018

@kwanhur What about openssl-1.1.0h? I can reproduce this problem through OpenResty/1.13.6 built with OpenSSL/1.1.0h.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants