[openssl-dev] bug in openssl 1.0.2a, s3_pkt.c ssl3_write_bytes()

George Wang gwang at litespeedtech.com
Mon May 18 22:58:35 UTC 2015


Hi,

Have to send it again. I have posted it to google group, did not get any
response.

below is the bug report.

---------------

It is likely the code change between 1.0.1m and 1.0.2a in s3_pkt.c
ssl3_write_bytes() introduces a bug.

We got similar core dumps from both LiteSpeed Enterprise Web Server and
OpenLiteSpeed when OpenSSL 1.0.2a is used.

Below is an example from related call stack backtrace:

#0  0x00000034e06897cb in memcpy () from /lib64/libc.so.6
#1  0x00000000005efbde in do_ssl3_write (s=0x36938a0, type=23,
buf=0x7fff96fc2830 "=server.xxxxxxxxx.com", len=16384,
create_empty_fragment=0) at s3_pkt.c:1005
#2  0x00000000005ef690 in ssl3_write_bytes (s=0x36938a0, type=23,
buf_=0x7fff96fba830, len=332) at s3_pkt.c:819
#3  0x0000000000633a1c in ssl3_write (s=0x36938a0, buf=0x7fff96fba830,
len=332) at s3_lib.c:4399
#4  0x00000000006051fb in SSL_write (s=0x36938a0, buf=0x7fff96fba830,
num=332) at ssl_lib.c:1046
#5  0x000000000052ce78 in SSLConnection::write (this=0x2e0d1c8,
    pBuf=0x7fff96fba830 "HTTP/1.1 200 OK\r\nCache-Control: public,
max-age=2592000\r\nExpires: Sun, 31 May 2015 03:40:08 GMT\r\nETag:
\"272eb-52dd9559-8cbab174726a68a6\"\r\nLast-Modified: Mon, 20 Jan 2014
21:30:01 GMT\r\nContent-Type: im"..., len=332) at
/home/gwang/release/litespeed/src/sslpp/sslconnection.cpp:139

The problem is in ssl3_write_bytes(), local variables:
(gdb) up
#2  0x00000000005ef690 in ssl3_write_bytes (s=0x36938a0, type=23,
buf_=0x7fff96fba830, len=332) at s3_pkt.c:819
819     in s3_pkt.c
(gdb) info local
buf = 0x7fff96fba830 "HTTP/1.1 200 OK\r\nCache-Control: public,
max-age=2592000\r\nExpires: Sun, 31 May 2015 03:40:08 GMT\r\nETag:
\"272eb-52dd9559-8cbab174726a68a6\"\r\nLast-Modified: Mon, 20 Jan 2014
21:30:01 GMT\r\nContent-Type: im"...
tot = 32768
n = 4294934860
nw = 16384
max_send_fragment = 16384
wb = 0x36faa28
i = 16384

(gdb) print s->s3->wnum
$1 = 0
(gdb) print *wb
$2 = {buf = 0x3952da0 " \002\224\027\003\001@ =server.xxxxxxxxx.com",
len = 16472, offset = 3, left = 0}
(gdb) print *s->s3
$3 = {flags = 1, delay_buf_pop_ret = 0, read_sequence =
"\000\000\000\000\000\000\000\v", read_mac_secret_size = 20,
  read_mac_secret = "\266\v\346\331+\341\223\065ѧZo6'=\302q\347\031K",
'\000' <repeats 43 times>, write_sequence =
"\000\000\000\000\000\000\000\026", write_mac_secret_size = 20,
  write_mac_secret =
"\245\351ڵx\373\026S\274j\177\242\334ҙ\204\226\360S\263", '\000'
<repeats 43 times>,
  server_random =
"\277a\006S\000zU\214\243\337\373\070>z\205S\222`\245pZ\222WW\226\021\025\345\377\252\065\213",

  client_random =
"UB\365\224\222 at zL\353\312\347tO\270\350_\346Xݢ\214!\212Z\251P\310?\365\232\n*",
need_empty_fragments = 0, empty_fragment_done = 1, init_extra = 1, rbuf
= {buf = 0x0,
    len = 33096, offset = 792, left = 0}, wbuf = {buf = 0x3952da0 "
\002\224\027\003\001@ =server.xxxxxxxxx.com", len = 16472, offset = 3,
left = 0}, rrec = {type = 23, length = 0,
    off = 0,
    data = 0x2ae5aa8 "GET
/files/cache/1c90376361dd83f4e4778af84377185a.jpg HTTP/1.1\r\nHost:
www.xxxxxxxxxxxx.com\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS
X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Versi"...,
    input = 0x2ae5aa8 "GET
/files/cache/1c90376361dd83f4e4778af84377185a.jpg HTTP/1.1\r\nHost:
www.xxxxxxxxxxxx.com\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS
X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Versi"..., comp =
0x0, epoch = 0, seq_num = "\000\000\000\000\000\000\000"}, wrec = {type
= 23, length = 16384, off = 0,
    data = 0x3952da8 "=server.xxxxxxxxx.com", input = 0x7fff96fc2830
"=server.xxxxxxxxx.com", comp = 0x0, epoch = 0, seq_num =
"\000\000\000\000\000\000\000"}, alert_fragment = "\000",
  alert_fragment_len = 0, handshake_fragment = "\000\000\000",
handshake_fragment_len = 0, wnum = 0, wpend_tot = 16384, wpend_type =
23, wpend_ret = 16384,
  wpend_buf = 0x7fff96fbe830 "\223)\374\226\377\177", handshake_buffer =
0x0, handshake_dgst = 0x36d5f60, change_cipher_spec = 0, warn_alert = 0,
fatal_alert = 0, alert_dispatch = 0,
  send_alert = "\000", renegotiate = 0, total_renegotiations = 0,
num_renegotiations = 0, in_read_app_data = 0, client_opaque_prf_input =
0x0, client_opaque_prf_input_len = 0,
  server_opaque_prf_input = 0x0, server_opaque_prf_input_len = 0, tmp =
{cert_verify_md = '\000' <repeats 127 times>,
    finish_md = "Ը\343c\271ե\224N\373g\256", '\000' <repeats 115 times>,
finish_md_len = 12, peer_finish_md =
"\022\221\257\371\231\f\324%\317:\342,", '\000' <repeats 115 times>,
    peer_finish_md_len = 12, message_size = 12, message_type = 20,
new_cipher = 0xb8a440, dh = 0x0, ecdh = 0x0, next_state = 8640,
reuse_message = 0, cert_req = 0, ctype_num = 0,
    ctype = "\000\000\000\000\000\000\000\000", ca_names = 0x0,
use_rsa_tmp = 0, key_block_length = 0, key_block = 0x0, new_sym_enc =
0xb8c4a0, new_hash = 0x0, new_mac_pkey_type = 855,
    new_mac_secret_size = 20, new_compression = 0x0, cert_request = 0},
previous_client_finished = "\022\221\257\371\231\f\324%\317:\342,",
'\000' <repeats 51 times>,
  previous_client_finished_len = 12 '\f', previous_server_finished =
"Ը\343c\271ե\224N\373g\256", '\000' <repeats 51 times>,
previous_server_finished_len = 12 '\f',
  send_connection_binding = 0, next_proto_neg_seen = 0,
is_probably_safari = 1 '\001', alpn_selected = 0x0, alpn_selected_len = 0}


The variable causing problem is

tot = 32768

tot should be less than "len", while, len = 332

analyzing the code change between 1.0.1m and 1.0.2a, the following code
should be the source of the problem,

    /*
     * first check if there is a SSL3_BUFFER still being written out.  This
     * will happen with non blocking IO
     */
    if (wb->left != 0) {
        i = ssl3_write_pending(s, type, &buf[tot], s->s3->wpend_tot);
        if (i <= 0) {
            /* XXX should we ssl3_release_write_buffer if i<0? */
            s->s3->wnum = tot;
            return i;
        }
        tot += i;               /* this might be last fragment */
    }


looks like ssl3_write_pending() return 16384, increase "tot" value by
16384, made it greater than "len", end up causing "n = 4294934860".

It only happens when there are pending data flushed. 1.0.1m code does
not have the logic to flush pending data.

I hope someone really know how it should work can help to fix this.

1.0.2a is not very stable, we see some other strange behaviors as well.

We use 1.0.2a because we want to have ALPN for our HTTP/2
implementation, but looks like we may have to fallback to 1.0.1m, or
looking into something else if we have to have ALPN.


Best regards,
George Wang


More information about the openssl-dev mailing list