[Libwebsockets] Double freeing causes crashing??

Andy Green andy at warmcat.com
Sat Nov 7 00:40:58 CET 2015



On 6 November 2015 16:51:29 GMT+08:00, Duy Lan Nguyen <ndlan2k at gmail.com> wrote:
>Sorry, it was due to referring to already freed memory, not double
>freeing.
>I can point to where it happens.
>At line 300,
>http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tree/lib/client-handshake.c#n300,
>wsi is freed by lws_free(wsi) (in function
>libwebsocket_client_connect_2,
>called by lws_client_socket_service, called by libwebsocket_service_fd
><=
>lws_plat_service <= libwebsocket_service).
>But that wsi memory is referred to again at
>http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tree/lib/lws-plat-win.c#n45
>(in function wsi_from_fd, called by libwebsocket_context_destroy).
>
>Do you think it is the problem? I can fix it by assigning wsi=NULL
>after
>freeing and checking if wsi!=NULL before referring to its memory, then
>git-pushing the change. Is that ok?

No that has a slightly deeper cause, which is we errored out of client connection init, but didn't take care to remove the connection from the fd list on that path.  However that was fixed a while ago

http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/commit/?id=b5cf69fdb57c4025572cde1007e0ff16108d4f80

How old is your lws?

-Andy

>Besides, in the code as follows, I waited for the thread of
>libwebsocket_service loop to stop before calling
>libwebsocket_context_destroy(). So I think the crash may happen even
>without threading.
>if (pVeraSocket)
>{
>if (pVeraSocket->m_hThreadService && pVeraContext &&
>pVeraContext->m_pVeraSocketInfo)
>{
>pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = TRUE;
>
>WaitForSingleObject(pVeraSocket->m_hThreadService, INFINITE);
>CloseHandle(pVeraSocket->m_hThreadService);
>pVeraSocket->m_hThreadService = NULL;
>pVeraSocket->m_dwThreadServiceId = 0;
>}
>...
>}
>
>if (pVeraContext)
>                {
>s_rgppVeraSocketInfo[pVeraContext->m_nConnTicket] = NULL;
>    if (pVeraContext->m_pContext)
>{
>libwebsocket_context_destroy(pVeraContext->m_pContext);
>pVeraContext->m_pContext = NULL;
>}
>                }
>
>I have a further question. I was trying to develop based on the
>following
>description of libwebsocket_service() at
>https://libwebsockets.org/libwebsockets-api-doc.html. If I don't
>interpret
>it incorrectly, it means I could create another thread for the
>libwebsocket_service() loop so that it doesn't block the main thread,
>which
>can do other stuff. So how should I interpret this description?
>"*int* *libwebsocket_service* (*struct libwebsocket_context **
>*context*,
>*int* *timeout_ms*)
>...Description
>
>This function deals with any pending websocket traffic, for three kinds
>of
>event. It handles these events on both server and client types of
>connection the same.
>
>1) Accept new connections to our context's server
>
>2) Call the receive callback for incoming frame data received by server
>or
>client connections.
>
>You need to call this service function periodically to all the above
>functions to happen; if your application is single-threaded you can
>just
>call it in your main event loop.
>
>Alternatively you can fork a new process that asynchronously handles
>calling this service in a loop. In that case you are happy if this call
>blocks your thread until it needs to take care of something and would
>call
>it with a large nonzero timeout. Your loop then takes no CPU while
>there is
>nothing happening.
>
>If you are calling it in a single-threaded app, you don't want it to
>wait
>around blocking other things in your loop from happening, so you would
>call
>it with a timeout_ms of 0, so it returns immediately if nothing is
>pending,
>or as soon as it services whatever was pending."
>
>Thanks,
>Lan
>
>
>
>On Wed, Nov 4, 2015 at 7:16 PM, Andy Green <andy at warmcat.com> wrote:
>
>>
>>
>> On 5 November 2015 09:52:11 GMT+08:00, Duy Lan Nguyen
><ndlan2k at gmail.com>
>> wrote:
>> >Hi Andy and Anyone-who-can-help,
>> >
>> >We have a situation of double freeing and crashing here and wonder
>if
>> >anyone can help.
>>
>> Maybe someone else can help.
>>
>> I don't have windows, and lws doesn't have threads.
>>
>> If you can make a patch that does the minimum to lws-test-server to
>make
>> the problem come on Linux, I'll study it.  But the answer is likely
>in your
>> threading additions outside of lws.
>>
>> -Andy
>>
>> >We use lws as follows, with highlights
>> >
>> >We have a connection function VeraConnect that calls
>> >libwebsocket_create_context and libwebsocket_client_connect, and
>> >creates
>> >another thread PollService for the polling service
>> >libwebsocket_service. If
>> >VeraConnect fails, it will clean up by stopping the thread
>PollService
>> >and
>> >calling libwebsocket_context_destroy. The functions VeraConnect and
>> >PollService are summarized as below.
>> >
>> >...
>> >VeraConnect(...)
>> >{
>> >....
>> >  if (!pVeraContext->m_pContext)
>> >    {
>> >        pVeraContext->m_pContext = libwebsocket_create_context
>> >(pVeraContext->m_pInfo);
>> >        if (!pVeraContext->m_pContext) {
>> >            ret = VERA_FAIL;
>> >            goto exit;
>> >        }
>> >    }
>> >
>> >pVeraSocket->m_pWSI =
>> >libwebsocket_client_connect(pVeraContext->m_pContext,
>> >...);
>> >
>> >    if (!pVeraSocket->m_pWSI) {
>> >        ret = VERA_FAIL;
>> >        goto exit;
>> >    }
>> >
>> >  pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = FALSE;
>> >
>> >  pVeraSocket->m_hThreadService = CreateThread(
>> >...
>> >        PollService,       // thread function name
>> >        pVeraContext,          // argument to thread function
>> >...);   // returns the thread identifier
>> >
>> >exit:
>> >  if (ret != VERA_OK)
>> >    {
>> >if (pVeraSocket)
>> >{
>> >if (pVeraSocket->m_hThreadService && pVeraContext &&
>> >pVeraContext->m_pVeraSocketInfo)
>> >{
>> >pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = TRUE;
>> >
>> >WaitForSingleObject(pVeraSocket->m_hThreadService, INFINITE);
>> >CloseHandle(pVeraSocket->m_hThreadService);
>> >pVeraSocket->m_hThreadService = NULL;
>> >pVeraSocket->m_dwThreadServiceId = 0;
>> >}
>> >...
>> >}
>> >
>> >if (pVeraContext)
>> >                {
>> >s_rgppVeraSocketInfo[pVeraContext->m_nConnTicket] = NULL;
>> >    if (pVeraContext->m_pContext)
>> >{
>> >libwebsocket_context_destroy(pVeraContext->m_pContext);
>> >pVeraContext->m_pContext = NULL;
>> >}
>> >                }
>> >...
>> >   }
>> >...
>> >}
>> >...
>> >... PollService(LPVOID lpParam)
>> >{
>> >        int n = 0;
>> >VeraContext *pVeraContext = (VeraContext *)lpParam;
>> >
>> >if (pVeraContext && pVeraContext->m_pVeraSocketInfo &&
>> >pVeraContext->m_pContext)
>> >{
>> >BOOL *pfSocketClosed =
>> >&pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed;
>> >struct libwebsocket_context *pContext = pVeraContext->m_pContext;
>> >
>> >while (n >= 0 && !*pfSocketClosed) {
>> >n = libwebsocket_service(pContext, 64);
>> >}
>> >}
>> >        return 0;
>> >}
>> >
>> >Sometimes, our first VeraConnect call fails, then the immediate next
>> >VeraConnect call crashes. The crash details are below, with line
>> >numbers (e.g.
>> >one line below refers to calling wsi_from_fd() near line 310 of
>> >context.c
>> >in function libwebsocket_context_destroy()). Basically, the memory
>has
>> >been
>> >freed by libwebsocket_service below (its trace includes
>> >libwebsocket_service_fd, lws_client_socket_service,
>> >libwebsocket_client_connect_2, _realloc), but it is then freed again
>by
>> >the
>> >libwebsocket_context_destroy() inside VeraConnect. Therefore it
>> >crashes.
>> >
>> >So could anyone please tell me if my way of using lws should be
>changed
>> >to
>> >fix this? Or is there a way to change lws to avoid this crash?
>> >
>> >Many thanks,
>> >Lan
>> >
>> >original faulting stack:
>> >
>> >0:003> .ecxr
>> >rax=000000000477cee0 rbx=0000000013f70c50 rcx=0000000000000000
>> >rdx=000000000402d680 rsi=0000000000000000 rdi=0000000000000000
>> >rip=00000000ff3f159a rsp=000000000659f788 rbp=00000000ff406ba0
>> > r8=0000000000000004  r9=0000000013f70c50 r10=0000000000000280
>> >r11=0000000000000004 r12=0000000000000000 r13=0000000000000102
>> >r14=000000000659f880 r15=0000000004847ff8
>> >iopl=0         nv up ei pl nz na pe nc
>> >cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b
>> >efl=00010202
>> >phantom!wsi_from_fd+0x3a:
>> >00000000`ff3f159a 44395060        cmp     dword ptr [rax+60h],r10d
>> >ds:00000000`0477cf40=????????
>> >0:003> kv
>> >  *** Stack trace for last set context - .thread/.cxr resets it
>> >Child-SP          RetAddr           : Args to
>> >Child                                                           :
>Call
>> >Site
>> >00000000`0659f788 00000000`ff3efe1f : 00000000`00000000
>> >00000000`ff3a1c74
>> >00000000`ff3a1c78 00000000`03eade30 : phantom!wsi_from_fd+0x3a
>> >[c:\libwebsockets\lib\lws-plat-win.c @ 45]
>> >00000000`0659f790 00000000`ff3c2b7f : 00000000`00000102
>> >00000000`03eade30
>> >00000000`03eade20 00000000`04847fe0 :
>> >phantom!libwebsocket_context_destroy+0x5f
>> >[c:\libwebsockets\lib\context.c @ 310]
>> >00000000`0659f7d0 00000000`ff3bec11 : 00000000`0659f898
>> >00000000`02460000
>> >00000000`00000050 00000000`ff40e5f8 : phantom!VeraConnect+0x29f
>> >[c:\socketcode\c\verasock\verasocklws.c @ 1194]
>> >...
>> >00000000`0659ff10 00000000`76fa3281 : 00000000`00000000
>> >00000000`00000000
>> >00000000`00000000 00000000`00000000 :
>kernel32!BaseThreadInitThunk+0xd
>> >00000000`0659ff40 00000000`00000000 : 00000000`00000000
>> >00000000`00000000
>> >00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
>> >
>> >0:003> !heap -p -a 000000000477cee0
>> >    address 000000000477cee0 found in
>> >    _DPH_HEAP_ROOT @ 3d51000
>> >    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr
>> >VirtSize)
>> >                                    3d549c0:          477c000
>> >2000
>> >*** ERROR: Symbol file could not be found.  Defaulted to export
>symbols
>> >for
>> >verifier.dll -
>> >    000007fef45b8726
>>
>>verifier!VerifierDisableFaultInjectionExclusionRange+0x000000000000234e
>> >    000000007703c415 ntdll!RtlDebugFreeHeap+0x0000000000000035
>> >    0000000076fdd0fe ntdll! ??
>::FNODOBFM::`string'+0x00000000000122e2
>> >    0000000076fc2075 ntdll!RtlFreeHeap+0x00000000000001a2
>> >*** ERROR: Symbol file could not be found.  Defaulted to export
>symbols
>> >for
>> >msvcrt.dll -
>> >    000007fefd4e10c4 msvcrt!free+0x000000000000001c
>> >    00000000ff3f2bac phantom!_realloc+0x000000000000001c
>> >[c:\libwebsockets\lib\alloc.c @ 9]
>> >00000000ff3f0e77
>> >phantom!libwebsocket_client_connect_2+0x00000000000003b7
>> >[c:\libwebsockets\lib\client-handshake.c @ 289]
>> >  00000000ff3f5385
>phantom!lws_client_socket_service+0x0000000000000045
>> >[c:\libwebsockets\lib\client.c @ 63]
>> >    00000000ff3f0a46
>phantom!libwebsocket_service_fd+0x00000000000003f6
>> >[c:\libwebsockets\lib\service.c @ 616]
>> >    00000000ff3f1909 phantom!lws_plat_service+0x0000000000000119
>> >[c:\libwebsockets\lib\lws-plat-win.c @ 164]
>> >    00000000ff3c1cf6 phantom!PollService+0x0000000000000036
>> >[c:\socketcode\c\verasock\verasocklws.c @ 377]
>> >    0000000076e6f56d kernel32!BaseThreadInitThunk+0x000000000000000d
>> >    0000000076fa3281 ntdll!RtlUserThreadStart+0x000000000000001d
>>
>>




More information about the Libwebsockets mailing list