[Libwebsockets] Double freeing causes crashing??

Andy Green andy at warmcat.com
Sun Nov 8 03:28:14 CET 2015



On 8 November 2015 09:26:55 GMT+08:00, Andy Green <andy at warmcat.com> wrote:
>
>
>On 7 November 2015 14:46:49 GMT+08:00, Duy Lan Nguyen
><ndlan2k at gmail.com> wrote:
>>Awesome, mine is older than that.
>>
>>It seems to me that lws has supported proxy, but not yet proxy
>>authentication using user name and password. Do you plan to support
>>that in
>>a near future?
>
>Depends what you mean... according to this
>
>https://wiki.archlinux.org/index.php/Proxy_settings
>
>You can just stick your auth details behind the proxy url
>
>echo -n "username: "; read username
>if [[ $username != "" ]]; then
>   echo -n "password: "
>   read -es password
>   local pre="$username:$password@"
>fi
>
>export http_proxy="http://$pre$server:$port/"
>export https_proxy=$http_proxy
>...
>
>There are other kinds of proxy auth like http basic auth you can add in
>user code.

I pushed a patch to support the user:pw@ syntax and send the header with a base64 version of it on proxy connect.  I tested the parsing but the header part is untested since no suitable proxy here.

Please let me know how it goes.

-Andy

>-Andy
>
>
>>Thanks,
>>Lan
>>
>>
>>On Fri, Nov 6, 2015 at 3:40 PM, Andy Green <andy at warmcat.com> wrote:
>>
>>>
>>>
>>> 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
>>> >>
>>> >>
>>>
>>>
>
>_______________________________________________
>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org
>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets




More information about the Libwebsockets mailing list