1
0
mirror of https://github.com/mariadb-corporation/libmarias3.git synced 2026-10-23 14:29:02 +03:00

Fix libcurl/openssl thread safety issues

If libcurl was built with OpenSSL < 1.1.0 then there is a potential
thread safety issue which can cause libmarias3 to crash.

This fix detects which version of OpenSSL (if any) that libcurl was
built with and adds thread locking callbacks to OpenSSL if found unsafe.

Fixes mariadb-corporation/libmarias3#70
This commit is contained in:
Andrew Hutchings
2019-09-30 16:19:14 +01:00
parent a5e3242672
commit b9ffda81d9
4 changed files with 107 additions and 0 deletions

View File

@@ -78,6 +78,7 @@ AX_ENDIAN
AX_HEX_VERSION([LIBMARIAS3],[$VERSION])
AC_SUBST([RPM_RELEASE],[1])
AX_CURL_OPENSSL_UNSAFE
AX_HARDEN_COMPILER_FLAGS
AC_DEFINE_UNQUOTED([C_COMPILER_VENDOR],["$ax_cv_c_compiler_vendor"],[Compiler vendor])

View File

@@ -8,6 +8,7 @@ Version 3.1.2 GA
^^^^^^^^^^^^^^^^
* Make library work with quirks in Google Cloud's S3 implementation
* Detect when libcurl was built with OpenSSL < 1.1.0 and add workaround to thread safety issues in the older OpenSSL versions (affects Ubuntu 16.04 in particular)
Version 3.1.1 GA (2019-06-28)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -0,0 +1,60 @@
# SYNOPSIS
#
# AX_CURL_OPENSSL_UNSAFE
#
# DESCRIPTION
#
# Checks to see if Curl is using a thread safe version of OpenSSL
#
# LICENSE
#
# Copyright (c) 2019 Andrew Hutchings <andrew.hutchings@mariadb.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 1
AC_DEFUN([AX_CURL_OPENSSL_UNSAFE],
[AC_PREREQ([2.63])dnl
AC_CACHE_CHECK([whether curl uses an OpenSSL which is not thread safe],
[ax_cv_curl_openssl_unsafe],
[AC_LANG_PUSH([C])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>]],
[[curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
if (data->ssl_version)
{
if (strncmp(data->ssl_version, "OpenSSL", 7) != 0)
{
return EXIT_FAILURE;
}
if (data->ssl_version[8] == '0')
{
return EXIT_SUCCESS;
}
if ((data->ssl_version[8] == '1') && (data->ssl_version[10] == '0'))
{
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
else
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;]])],
[ax_cv_curl_openssl_unsafe=yes],
[ax_cv_curl_openssl_unsafe=no],
[ax_cv_curl_openssl_unsafe=no])
AC_LANG_POP])
AC_MSG_CHECKING([checking for curl_openssl_unsafe])
AC_MSG_RESULT(["$ax_cv_curl_openssl_unsafe"])
AS_IF([test "x$ax_cv_curl_openssl_unsafe" = xyes],
[AC_DEFINE([HAVE_CURL_OPENSSL_UNSAFE],[1],[define if curl's OpenSSL is not thread safe])])
])

View File

@@ -30,6 +30,28 @@ ms3_realloc_callback ms3_crealloc = (ms3_realloc_callback)realloc;
ms3_strdup_callback ms3_cstrdup = (ms3_strdup_callback)strdup;
ms3_calloc_callback ms3_ccalloc = (ms3_calloc_callback)calloc;
/* Thread locking code for OpenSSL < 1.1.0 */
#ifdef HAVE_CURL_OPENSSL_UNSAFE
#include <openssl/crypto.h>
static pthread_mutex_t *mutex_buf = NULL;
static void __attribute__((unused)) locking_function(int mode, int n, const char *file, int line)
{
(void) file;
(void) line;
if(mode & CRYPTO_LOCK)
pthread_mutex_lock(&(mutex_buf[n]));
else
pthread_mutex_unlock(&(mutex_buf[n]));
}
static unsigned long __attribute__((unused)) id_function(void)
{
return ((unsigned long)pthread_self());
}
#endif
uint8_t ms3_library_init_malloc(ms3_malloc_callback m,
ms3_free_callback f, ms3_realloc_callback r,
ms3_strdup_callback s, ms3_calloc_callback c)
@@ -60,12 +82,35 @@ uint8_t ms3_library_init_malloc(ms3_malloc_callback m,
void ms3_library_init(void)
{
#ifdef HAVE_CURL_OPENSSL_UNSAFE
int i;
mutex_buf = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
if(mutex_buf)
{
for(i = 0; i < CRYPTO_num_locks(); i++)
pthread_mutex_init(&(mutex_buf[i]), NULL);
CRYPTO_set_id_callback(id_function);
CRYPTO_set_locking_callback(locking_function);
}
#endif
curl_global_init(CURL_GLOBAL_DEFAULT);
xmlInitParser();
}
void ms3_library_deinit(void)
{
#ifdef HAVE_CURL_OPENSSL_UNSAFE
int i;
if (mutex_buf)
{
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for(i = 0; i < CRYPTO_num_locks(); i++)
pthread_mutex_destroy(&(mutex_buf[i]));
free(mutex_buf);
mutex_buf = NULL;
}
#endif
curl_global_cleanup();
xmlCleanupParser();
}