[Libwebsockets] Double freeing causes crashing??

Andy Green andy at warmcat.com
Wed Nov 18 12:33:26 CET 2015



On 18 November 2015 14:19:13 GMT+08:00, Duy Lan Nguyen <ndlan2k at gmail.com> wrote:
>I've just tested the proxy basic authentication but it doesn't seem to
>work.
>
>The error from squid3 proxy's log is
>"192.168.137.1 TCP_DENIED/407 3731 CONNECT 192.168.137.1:443
>%cc%cc%cc%cc%cc%cctest1 HIER_NONE/- text/html"

Thanks... I pushed a fix

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

-Andy

>The user name is supposed to be test1, so there seem to be some bytes
>"%cc"
>preceding it (you can see that character at
>http://www.degraeve.com/reference/urlencoding.php).
>
>In using lws, I set the proxy in this string "
>test1:password at 192.168.137.106:3128". And I use wss.
>
>I set up squid3's proxy basic authentication following this instruction
>http://stackoverflow.com/questions/3297196/how-to-set-up-a-squid-proxy-with-basic-username-and-password-authentication,
>and it works using Chrome browser via the proxy and user name and
>password
>as above.
>
>Thanks,
>Lan
>
>
>On Sat, Nov 7, 2015 at 6:28 PM, Andy Green <andy at warmcat.com> wrote:
>
>>
>>
>> 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