Skip to content

Crash with WinSSL #3412

Closed
Closed

Description

@MarcelRaad

I did this

See the WinSSL autobuilds since December 23 on https://curl.haxx.se/dev/builds.html:

test 2043...[Disable certificate revocation checks]
../src/curl.exe --output log/curl2043.out --include --trace-ascii log/trace2043 --trace-time --ssl-no-revoke -I https://revoked.grc.com/ >log/stdout2043 2>log/stderr2043
sh: line 1: 6648 Segmentation fault

I expected the following

No segmentation fault

curl/libcurl version

Daily tarball since December 23

operating system

Windows 10, MSYS2 shell, MinGW-w64

I'll try to have a look when I'm back from my holidays tomorrow.

Activity

  1. gvanem commented on Dec 27, 2018

    @gvanem
    Contributor

    Verified from the cmd-line using a MSVC-built curl.exe.
    Here:

    void Curl_ssl_sessionid_lock(struct connectdata *conn)
    {
      if(SSLSESSION_SHARED(conn->data))

    conn->data == NULL!

  2. danielgustafsson commented on Dec 28, 2018

    @danielgustafsson
    Contributor

    Could fb445a1 and/or f3ce387 be related to this?

  3. MarcelRaad commented on Dec 28, 2018

    @MarcelRaad
    MemberAuthor

    Full call stack:

    Curl_ssl_sessionid_lock(connectdata * conn=0x000001d48f950560) Line 286
    Curl_schannel_shutdown(connectdata * conn=0x000001d48f950560, int sockindex=0) Line 2017
    Curl_ssl_shutdown(connectdata * conn=0x000001d48f950560, int sockindex=0) Line 560
    Curl_schannel_close(connectdata * conn=0x000001d48f950560, int sockindex=0) Line 1922
    Curl_ssl_close(connectdata * conn=0x000001d48f950560, int sockindex=0) Line 556
    Curl_disconnect(Curl_easy * data=0x000001d48f91eef0, connectdata * conn=0x000001d48f950560, bool dead_connection=false) Line 804
    Curl_conncache_close_all_connections(conncache * connc=0x000001d48a21d9b0) Line 580
    curl_multi_cleanup(Curl_multi * multi=0x000001d48a21d8c0) Line 2287
    
  4. MarcelRaad commented on Jan 1, 2019

    @MarcelRaad
    MemberAuthor

    Bisected to fb445a1.

  5. bagder commented on Jan 1, 2019

    @bagder
    Member

    Thanks. I'll look into it asap...

  6. bagder commented on Jan 3, 2019

    @bagder
    Member

    I would've expected f3ce387 to have addressed that issue since it brings back the conn->data assignment in Curl_disconnect:

    curl/lib/url.c

    Line 786 in 251cabf

    conn->data = data;

    @MarcelRaad can you see what exactly is wrong at vtls/vtls.c:286 ?

  7. MarcelRaad commented on Jan 3, 2019

    @MarcelRaad
    MemberAuthor

    What happens is that conn->data gets set to NULL at

    curl/lib/url.c

    Line 793 in ba266b3

    Curl_conncache_remove_conn(data, conn, TRUE);
    and the crash because of that happens at

    curl/lib/url.c

    Line 802 in ba266b3

    Curl_ssl_close(conn, FIRSTSOCKET);
    then with the call stack posted above.

    According to the comment, the assignment in your snippet is for conn->handler->disconnect, which is not even called.

  8. bagder commented on Jan 3, 2019

    @bagder
    Member

    I think it looks like a mistake that Curl_ssl_shutdown gets called when a single connection is closed (from within Curl_schannel_close). Looking at vtls/openssl:Curl_ossl_close() as a comparison it doesn't do that (and neither does any other TLS backend). There's a separate call to the shutdown function.

    The shutdown function needs a 'data' pointer to find the session_id cache (and lock/unlock it).

    I'm not sure what the best fix for this is now, but it might be to allow the shutdown to just skip the lock/unlock if there's no transfer associated with the connection anymore. Maybe like this:

    diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
    index 56fd93e1e..ef9b068fa 100644
    --- a/lib/vtls/schannel.c
    +++ b/lib/vtls/schannel.c
    @@ -5,11 +5,11 @@
      *                            | (__| |_| |  _ <| |___
      *                             \___|\___/|_| \_\_____|
      *
      * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
      * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
    - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
    + * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
      *
      * This software is licensed as described in the file COPYING, which
      * you should have received as part of this distribution. The terms
      * are also available at https://curl.haxx.se/docs/copyright.html.
      *
    @@ -2011,13 +2011,15 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
         Curl_safefree(BACKEND->ctxt);
       }
     
       /* free SSPI Schannel API credential handle */
       if(BACKEND->cred) {
    -    Curl_ssl_sessionid_lock(conn);
    +    if(conn->data)
    +      Curl_ssl_sessionid_lock(conn);
         Curl_schannel_session_free(BACKEND->cred);
    -    Curl_ssl_sessionid_unlock(conn);
    +    if(conn->data)
    +      Curl_ssl_sessionid_unlock(conn);
         BACKEND->cred = NULL;
       }
     
       /* free internal buffer for received encrypted data */
       if(BACKEND->encdata_buffer != NULL) {
  9. MarcelRaad commented on Jan 18, 2019

    @MarcelRaad
    MemberAuthor

    @bagder Can you push that please? It's necessary for testing #3321.

  10. added a commit that references this issue on Jan 18, 2019
    b6a0b17
  11. chris-araman commented on Feb 6, 2019

    @chris-araman
    Contributor

    I'm still seeing something similar, even after 6ee6729.

    I think we may need to check that data is not NULL here:

    if(data->set.verbose || data->set.errorbuffer) {

    ...because Curl_schannel_shutdown also passes data to failf/Curl_failf. The infof/Curl_infof call already makes this check here:

    if(data && data->set.verbose) {

    However, it seems like anywhere we might call failf, it would be useful to have some context to be able to provide debugging information to the caller. So, maybe @bagder's hunch is correct, that we might need a more complete fix.
    #3412 (comment)

    I don't have a proposed fix, but I think for now I'm just going to try checking for data here and seeing how far I get.

    if(sspi_status != SEC_E_OK)

  12. gvanem commented on Feb 6, 2019

    @gvanem
    Contributor

    @chris-araman

    I think we may need to check that data is not NULL here:
    [curl/lib/sendf.c]
    (

    if(data->set.verbose || data->set.errorbuffer) {
    )

    That is close to where issue #3505 crashes too (at line 162).
    Different function, but the maybe the assumptions WRT to Schannel are perhaps related?

  13. chris-araman commented on Feb 6, 2019

    @chris-araman
    Contributor

    @gvanem, thanks. I agree it looks like the same invariant is at issue in #3505. I will move my discussion there.

  14. locked as resolved and limited conversation to collaborators on May 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions