[Libwebsockets] Double freeing causes crashing??

Andy Green andy at warmcat.com
Sun Nov 8 02:26:55 CET 2015



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.

-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
>> >>
>> >>
>>
>>




More information about the Libwebsockets mailing list