Got some more info on this bug. It's a memory use after free.

There's a problem with ssl_st::write_hash. It's cached
in dtls1_buffer_message() function for each handshake message and got freed
and replaced by new hash context when forming Change Cipher Spec message
(in ssl_replace_hash(), see stack trace below). So, when we want to resend
lost packet, old (already freed) hash context is used to create MACs for
messages we want to resend, leading to crash on Win32 and undefined
behavior on Linux.

It's not a problem for initial handshake, because s->write_hash is zero and
nothing gets destroyed when forming  Change Cipher Spec.

Any ideas how to workaround/fix this are appreciated.

Here is the report from clang AddressSanitizer:

==32258==ERROR: AddressSanitizer: heap-use-after-free on address
0x60400000b890 at pc 0xa541d0 bp 0x7f9225188c50 sp 0x7f9225188c48
READ of size 8 at 0x60400000b890 thread T1
    #0 0xa541cf in EVP_MD_CTX_md evp_lib.c:285
    #1 0x66e790 in dtls1_do_write d1_both.c:275
    #2 0x682231 in dtls1_retransmit_message d1_both.c:1290
    #3 0x67fe96 in dtls1_retransmit_buffered_messages d1_both.c:1145
    #4 0x64f934 in dtls1_handle_timeout d1_lib.c:451
    #5 0x65b6d4 in dtls1_read_bytes d1_pkt.c:832
    #6 0x67640a in dtls1_get_message_fragment d1_both.c:789
    #7 0x674459 in dtls1_get_message d1_both.c:437
    #8 0x79835b in ssl3_get_new_session_ticket s3_clnt.c:2040
    #9 0x63a5c1 in dtls1_connect d1_clnt.c:641
    #10 0x6bef29 in SSL_do_handshake ssl_lib.c:2564
    #11 0x4e11aa in _ZN17DtlsSrtpTransport18handshakeIterationEv
test.cpp:348
    #12 0x5070b2 in _ZN17DtlsSrtpTransport19receiveTimerExpiredEv
test.cpp:423
    #13 0x505128 in operator() test.cpp:392
    #14 0x504951 in
_ZNSt3__18__invokeIRZN17DtlsSrtpTransport18handshakeIterationEvEUlvE_JEEEDTclclsr3std3__1E7forwardIT_Efp_Espclsr3std3__1E7forwardIT0_Efp0_EEEOS4_DpOS5_
__functional_base:341
    #15 0x6069e9 in _ZNKSt3__18functionIFvvEEclEv functional:1436
    #16 0x603c64 in _ZN15AsyncDispatcher3runEv test.cpp:170
    #17 0x603928 in operator() test.cpp:88
    #18 0x6021c5 in
_ZNSt3__17forwardIZN15AsyncDispatcherC1EvEUlvE_EEOT_RNS_16remove_referenceIS3_E4typeE
type_traits:1341
    #19 0x460083 in _ZN6__asan10AsanThread11ThreadStartEm ??:?
    #20 0x7f922847e0a1 in start_thread pthread_create.c:?
    #21 0x7f922788b49c in __clone ??:?
0x60400000b890 is located 0 bytes inside of 48-byte region
[0x60400000b890,0x60400000b8c0)
freed by thread T1 here:
    #0 0x459a04 in __interceptor_free ??:?
    #1 0x897bdf in CRYPTO_free mem.c:397
    #2 0x9f97cf in EVP_MD_CTX_destroy digest.c:370
    #3 0x693983 in ssl_clear_hash_ctx ssl_lib.c:3244
    #4 0x6ca125 in ssl_replace_hash ssl_lib.c:3236
    #5 0x83e213 in tls1_change_cipher_state t1_enc.c:425
    #6 0x639971 in dtls1_connect d1_clnt.c:560
    #7 0x6bef29 in SSL_do_handshake ssl_lib.c:2564
    #8 0x4e11aa in _ZN17DtlsSrtpTransport18handshakeIterationEv test.cpp:348
    #9 0x4d7d98 in operator() test.cpp:219
    #10 0x4d52c1 in
_ZNSt3__18__invokeIRZN17DtlsSrtpTransport18handleIncomingDataERKNS_6vectorIhNS_9allocatorIhEEEEEUlvE_JEEEDTclclsr3std3__1E7forwardIT_Efp_Espclsr3std3__1E7forwardIT0_Efp0_EEEOSA_DpOSB_
__functional_base:341
    #11 0x6069e9 in _ZNKSt3__18functionIFvvEEclEv functional:1436
    #12 0x603c64 in _ZN15AsyncDispatcher3runEv test.cpp:170
    #13 0x603928 in operator() test.cpp:88
    #14 0x6021c5 in
_ZNSt3__17forwardIZN15AsyncDispatcherC1EvEUlvE_EEOT_RNS_16remove_referenceIS3_E4typeE
type_traits:1341
    #15 0x460083 in _ZN6__asan10AsanThread11ThreadStartEm ??:?
previously allocated by thread T1 here:
    #0 0x459ae4 in __interceptor_malloc ??:?
    #1 0x89228c in default_malloc_ex mem.c:79
    #2 0x895a5c in CRYPTO_malloc mem.c:308
    #3 0x9f4515 in EVP_MD_CTX_create digest.c:131
    #4 0x6ca12a in ssl_replace_hash ssl_lib.c:3237
    #5 0x83e213 in tls1_change_cipher_state t1_enc.c:425
    #6 0x639971 in dtls1_connect d1_clnt.c:560
    #7 0x6bef29 in SSL_do_handshake ssl_lib.c:2564
    #8 0x4e11aa in _ZN17DtlsSrtpTransport18handshakeIterationEv test.cpp:348
    #9 0x4d7d98 in operator() test.cpp:219
    #10 0x4d52c1 in
_ZNSt3__18__invokeIRZN17DtlsSrtpTransport18handleIncomingDataERKNS_6vectorIhNS_9allocatorIhEEEEEUlvE_JEEEDTclclsr3std3__1E7forwardIT_Efp_Espclsr3std3__1E7forwardIT0_Efp0_EEEOSA_DpOSB_
__functional_base:341
    #11 0x6069e9 in _ZNKSt3__18functionIFvvEEclEv functional:1436
    #12 0x603c64 in _ZN15AsyncDispatcher3runEv test.cpp:170
    #13 0x603928 in operator() test.cpp:88
    #14 0x6021c5 in
_ZNSt3__17forwardIZN15AsyncDispatcherC1EvEUlvE_EEOT_RNS_16remove_referenceIS3_E4typeE
type_traits:1341
    #15 0x460083 in _ZN6__asan10AsanThread11ThreadStartEm ??:?
Thread T1 created by T0 here:
    #0 0x455a50 in __interceptor_pthread_create ??:?
    #1 0x5ff729 in thread<<lambda at test.cpp:88:31>, , void> thread:355
    #2 0x5fd7b9 in thread<<lambda at test.cpp:88:31>, , void> thread:360
    #3 0x5fd068 in AsyncDispatcher test.cpp:88
    #4 0x4a3e3c in AsyncDispatcher test.cpp:89
    #5 0x4688f7 in main test.cpp:516
    #6 0x7f92277c7bc4 in __libc_start_main ??:?



On Fri, Dec 13, 2013 at 5:55 PM, Dmitry Sobinov via RT <r...@openssl.org>wrote:

> Hello
>
> While testing renegotiations for DTLS-SRTP, found a crash on Windows.
> OpenSSL version is 1.0.1e, also tested on the latest 1.0.1 snapshot. There
> were 2 possible stack traces:
>
>   AddLiveService.dll!EVP_MD_size(const env_md_st * md) Line 273 C
> > AddLiveService.dll!dtls1_do_write(ssl_st * s, int type) Line 275 C
>   AddLiveService.dll!dtls1_retransmit_message(ssl_st * s, unsigned short
> seq, unsigned long frag_off, int * found) Line 1293 C
>   AddLiveService.dll!dtls1_retransmit_buffered_messages(ssl_st * s) Line
> 1145 C
>   AddLiveService.dll!dtls1_handle_timeout(ssl_st * s) Line 450 C
>   AddLiveService.dll!dtls1_read_bytes(ssl_st * s, int type, unsigned char *
> buf, int len, int peek) Line 832 C
>   AddLiveService.dll!dtls1_get_message_fragment(ssl_st * s, int st1, int
> stn, long max, int * ok) Line 789 C
>   AddLiveService.dll!dtls1_get_message(ssl_st * s, int st1, int stn, int
> mt, long max, int * ok) Line 436 C
>   AddLiveService.dll!ssl3_get_new_session_ticket(ssl_st * s) Line 2046 C
>   AddLiveService.dll!dtls1_connect(ssl_st * s) Line 631 C
>   AddLiveService.dll!SSL_do_handshake(ssl_st * s) Line 2562 C
>
> and
>
>   msvcr120d.dll!memcpy(unsigned char * dst, unsigned char * src, unsigned
> long count) Line 188 Unknown
> > dtls_test.exe!dtls1_get_message_fragment(ssl_st * s, int st1, int stn,
> long max, int * ok) Line 789 C
>   dtls_test.exe!dtls1_get_message(ssl_st * s, int st1, int stn, int mt,
> long max, int * ok) Line 436 C
>   dtls_test.exe!ssl3_get_new_session_ticket(ssl_st * s) Line 2046 C
>   dtls_test.exe!dtls1_connect(ssl_st * s) Line 631 C
>   dtls_test.exe!SSL_do_handshake(ssl_st * s) Line 2562 C
>
> Both are segfaults (access violations). On linux rehandshake doesn't finish
> at all (failure after 1-2 minutes on timeout).
>
> You can find sample c++11 source file to reproduce this issue. In-memory
> BIO pair is used, client and server in the same process. When no flights
> are dropped, everything is fine.
>
> The sample can be compiled by MSVC 2013 on Windows and g++ 4.7+ (g++ -o
> dtlstest main.cpp -std=c++11 -lssl -lcrypto -lpthread -g) or clang 3.2+.
>
>
> ---
> Dmitry Sobinov
> AddLive.com
> Live video and voice for your application
>
>


---
Dmitry Sobinov
AddLive.com
Live video and voice for your application

Reply via email to