• Show log

    Commit

  • Hash : 2d2e70f8
    Author : Patrick Steinhardt
    Date : 2017-11-30T18:10:28

    openssl: fix thread-safety on non-glibc POSIX systems
    
    While the OpenSSL library provides all means to work safely in a
    multi-threaded application, we fail to do so correctly. Quoting from
    crypto_lock(3):
    
        OpenSSL can safely be used in multi-threaded applications provided
        that at least two callback functions are set, locking_function and
        threadid_func.
    
    We do in fact provide the means to set up the locking function via
    `git_openssl_set_locking()`, where we initialize a set of locks by using
    the POSIX threads API and set the correct callback function to lock and
    unlock them.
    
    But what we do not do is setting the `threadid_func` callback. This
    function is being used to correctly locate thread-local data of the
    OpenSSL library and should thus return per-thread identifiers. Digging
    deeper into OpenSSL's documentation, the library does provide a fallback
    in case that locking function is not provided by the user. On Windows
    and BeOS we should be safe, as it simply "uses the system's default
    thread identifying API". On other platforms though OpenSSL will fall
    back to using the address of `errno`, assuming it is thread-local.
    
    While this assumption holds true for glibc-based systems, POSIX in fact
    does not specify whether it is thread-local or not. Quoting from
    errno(3p):
    
        It is unspecified whether errno is a macro or an identifier declared
        with external linkage.
    
    And in fact, with musl there is at least one libc implementation which
    simply declares `errno` as a simple `int` without being thread-local. On
    those systems, the fallback threadid function of OpenSSL will not be
    thread-safe.
    
    Fix this by setting up our own callback for this setting. As users of
    libgit2 may want to set it themselves, we obviously cannot always set
    that function on initialization. But as we already set up primitives for
    threading in `git_openssl_set_locking()`, this function becomes the
    obvious choice where to implement the additional setup.