Skip to content

Commit d41c154

Browse files
committed
Merge pull request #127
More robust solution to prevent deinitializing OpenSSL functions
2 parents 07598b7 + 3d687a2 commit d41c154

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

Makefile.PL

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,133 @@ my $have_deinitialize_ssl = check_lib(
284284
function => 'mariadb_deinitialize_ssl = 0; return 0;',
285285
);
286286

287+
# Check if mysql_server_end() deinitialize OpenSSL library functions
288+
# See: https://github.com/gooddata/DBD-MariaDB/issues/119
289+
my $have_problem_with_openssl = !check_lib(
290+
LIBS => (join ' ', @libdirs, $main_lib),
291+
ccflags => $opt->{cflags},
292+
ldflags => (join ' ', @libdirs, @libs, @ldflags, $Config{perllibs}),
293+
header => \@mysql_headers,
294+
function => << 'EOF'
295+
296+
#ifndef _WIN32
297+
#ifndef _GNU_SOURCE
298+
#define _GNU_SOURCE
299+
#endif
300+
#include <dlfcn.h>
301+
#ifndef RTLD_DEFAULT
302+
#define RTLD_DEFAULT ((void *)0)
303+
#endif
304+
#endif
305+
306+
int (*OPENSSL_init_ssl_func)(unsigned long long, const void *);
307+
void (*SSL_load_error_strings_func)(void);
308+
int (*SSL_library_init_func)(void);
309+
void *(*SSL_CTX_new_func)(const void *method);
310+
void (*SSL_CTX_free_func)(void *ctx);
311+
const void *(*TLS_method_func)(void);
312+
const void *method1;
313+
const void *method2;
314+
void *ctx1;
315+
void *ctx2;
316+
317+
#ifdef _WIN32
318+
319+
BOOL (WINAPI *EnumProcessModules_func)(HANDLE, HMODULE *, DWORD, LPDWORD);
320+
HMODULE psapi_lib;
321+
DWORD size, i;
322+
HMODULE *modules;
323+
324+
modules = NULL;
325+
psapi_lib = LoadLibraryA("Psapi.dll");
326+
if (psapi_lib) {
327+
EnumProcessModules_func = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD))GetProcAddress(psapi_lib, "EnumProcessModules");
328+
if (EnumProcessModules_func) {
329+
if (EnumProcessModules_func((HANDLE)-1, NULL, 0, &size)) {
330+
modules = (HMODULE *)GlobalAlloc(GPTR, size);
331+
if (modules && !EnumProcessModules_func((HANDLE)-1, modules, size, &size))
332+
modules = NULL;
333+
}
334+
}
335+
}
336+
337+
#define SYMBOL(var, type, sym) do { \
338+
var = (type)GetProcAddress(GetModuleHandle(NULL), sym); \
339+
if (!var) { \
340+
if (!modules) \
341+
return 1; \
342+
for (i = 0; i < size/sizeof(*modules); ++i) { \
343+
var = (type)GetProcAddress(modules[i], sym); \
344+
if (var) \
345+
break; \
346+
} \
347+
} \
348+
} while (0)
349+
350+
#else
351+
352+
#define SYMBOL(var, type, sym) do { var = (type)dlsym(RTLD_DEFAULT, sym); } while (0)
353+
354+
#endif
355+
356+
SYMBOL(OPENSSL_init_ssl_func, int (*)(unsigned long long, const void *), "OPENSSL_init_ssl");
357+
SYMBOL(SSL_library_init_func, int (*)(void), "SSL_library_init");
358+
if (!OPENSSL_init_ssl_func && !SSL_library_init_func)
359+
return 0;
360+
SYMBOL(SSL_load_error_strings_func, void (*)(void), "SSL_load_error_strings");
361+
if (!OPENSSL_init_ssl_func && !SSL_load_error_strings_func)
362+
return 0;
363+
SYMBOL(SSL_CTX_new_func, void *(*)(const void *), "SSL_CTX_new");
364+
if (!SSL_CTX_new_func)
365+
return 0;
366+
SYMBOL(SSL_CTX_free_func, void (*)(void *), "SSL_CTX_free");
367+
if (!SSL_CTX_free_func)
368+
return 0;
369+
370+
SYMBOL(TLS_method_func, const void *(*)(void), "TLS_method");
371+
if (!TLS_method_func)
372+
SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_2_method");
373+
if (!TLS_method_func)
374+
SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_1_method");
375+
if (!TLS_method_func)
376+
SYMBOL(TLS_method_func, const void *(*)(void), "TLSv1_method");
377+
if (!TLS_method_func)
378+
return 0;
379+
380+
if (OPENSSL_init_ssl_func) {
381+
OPENSSL_init_ssl_func(0, (void *)0);
382+
} else {
383+
SSL_library_init_func();
384+
SSL_load_error_strings_func();
385+
}
386+
387+
method1 = TLS_method_func();
388+
if (!method1)
389+
return 1;
390+
ctx1 = SSL_CTX_new_func(method1);
391+
if (!ctx1)
392+
return 1;
393+
394+
mysql_server_init(-1, 0, 0);
395+
mysql_server_end();
396+
397+
method2 = TLS_method_func();
398+
if (!method2)
399+
return 1;
400+
ctx2 = SSL_CTX_new_func(method2);
401+
if (!ctx2)
402+
return 1;
403+
404+
SSL_CTX_free_func(ctx1);
405+
SSL_CTX_free_func(ctx2);
406+
407+
return 0;
408+
409+
EOF
410+
);
411+
412+
print "Client library deinitialize OpenSSL library functions: " . ($have_problem_with_openssl ? "yes" : "no") . "\n\n";
413+
287414
my $fileName = File::Spec->catfile("t", "MariaDB.mtest");
288415
(open(FILE, ">$fileName") &&
289416
(print FILE ("{ local " . Data::Dumper->Dump([$opt], ["opt"]) .
@@ -313,6 +440,7 @@ $cflags .= " -DHAVE_EMBEDDED" if $have_embedded;
313440
$cflags .= " -DHAVE_GET_CHARSET_NUMBER" if $have_get_charset_number;
314441
$cflags .= " -DHAVE_GET_OPTION" if $have_get_option;
315442
$cflags .= " -DHAVE_DEINITIALIZE_SSL" if $have_deinitialize_ssl;
443+
$cflags .= " -DHAVE_PROBLEM_WITH_OPENSSL" if $have_problem_with_openssl;
316444
my %o = ( 'NAME' => 'DBD::MariaDB',
317445
'INC' => $cflags,
318446
'dist' => { 'SUFFIX' => ".gz",

MariaDB.xs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ BOOT:
6363
newTypeSub(stash, MYSQL_TYPE_VAR_STRING);
6464
newTypeSub(stash, MYSQL_TYPE_STRING);
6565
#undef newTypeSub
66-
#ifdef HAVE_DEINITIALIZE_SSL
66+
#if defined(HAVE_DEINITIALIZE_SSL) && defined(HAVE_PROBLEM_WITH_OPENSSL)
6767
/* Do not deinitialize OpenSSL library after mysql_server_end()
6868
* See: https://github.com/gooddata/DBD-MariaDB/issues/119 */
6969
mariadb_deinitialize_ssl = 0;

dbdimp.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2951,7 +2951,7 @@ static void mariadb_dr_close_mysql(pTHX_ imp_drh_t *imp_drh, MYSQL *pmysql)
29512951
* These bugs were fixed in MariaDB Connector/C 3.0.5, see: https://jira.mariadb.org/browse/CONC-336
29522952
* But remains in MariaDB Embedded server, see: https://jira.mariadb.org/browse/MDEV-16578
29532953
*/
2954-
#ifndef HAVE_BROKEN_INIT
2954+
#if !defined(HAVE_BROKEN_INIT) && (defined(HAVE_DEINITIALIZE_SSL) || !defined(HAVE_PROBLEM_WITH_OPENSSL))
29552955
if (imp_drh->non_embedded_started)
29562956
{
29572957
mysql_server_end();
@@ -2962,6 +2962,9 @@ static void mariadb_dr_close_mysql(pTHX_ imp_drh_t *imp_drh, MYSQL *pmysql)
29622962
{
29632963
mysql_server_end();
29642964
imp_drh->embedded_started = FALSE;
2965+
#if !defined(HAVE_DEINITIALIZE_SSL) && defined(HAVE_PROBLEM_WITH_OPENSSL)
2966+
warn("DBD::MariaDB disconnect: Client library deinitialized OpenSSL library functions and module Net::SSLeay is now broken");
2967+
#endif
29652968
}
29662969
if (imp_drh->embedded_args)
29672970
{
@@ -3144,6 +3147,7 @@ int mariadb_dr_discon_all (SV *drh, imp_drh_t *imp_drh) {
31443147
#ifndef HAVE_EMBEDDED
31453148
if (imp_drh->non_embedded_started)
31463149
{
3150+
#if defined(HAVE_DEINITIALIZE_SSL) || !defined(HAVE_PROBLEM_WITH_OPENSSL)
31473151
#ifndef HAVE_BROKEN_INIT
31483152
warn("DBD::MariaDB disconnect_all: Client library was not properly deinitialized (possible bug in driver)");
31493153
ret = 0;
@@ -3152,6 +3156,7 @@ int mariadb_dr_discon_all (SV *drh, imp_drh_t *imp_drh) {
31523156
imp_drh->non_embedded_started = FALSE;
31533157
imp_drh->non_embedded_finished = TRUE;
31543158
#endif
3159+
#endif
31553160
}
31563161
#endif
31573162

0 commit comments

Comments
 (0)