X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Fshlibloadtest.c;h=919bf7c5f0b33c92286b8bec0f922d3b1d0f2945;hp=20030d94a8fafdb96d87e62cb8ba9ce87b7c089b;hb=e4fa7cc3fb9909c6aee411de15a06f918687b8e2;hpb=b754f9a3a5bccffc7e8f534fefd13fc0ef7aaf13 diff --git a/test/shlibloadtest.c b/test/shlibloadtest.c index 20030d94a8..919bf7c5f0 100644 --- a/test/shlibloadtest.c +++ b/test/shlibloadtest.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,6 +12,9 @@ #include #include +/* The test is only currently implemented for DSO_DLFCN and DSO_WIN32 */ +#if defined(DSO_DLFCN) || defined(DSO_WIN32) + #define SSL_CTX_NEW "SSL_CTX_new" #define SSL_CTX_FREE "SSL_CTX_free" #define TLS_METHOD "TLS_method" @@ -35,31 +38,27 @@ static SSL_CTX_free_t SSL_CTX_free; static ERR_get_error_t ERR_get_error; static OpenSSL_version_num_t OpenSSL_version_num; - #ifdef DSO_DLFCN +# define DSO_DSOBYADDR "DSO_dsobyaddr" +# define DSO_FREE "DSO_free" + +typedef void DSO; +typedef DSO * (*DSO_dsobyaddr_t)(void (*addr)(), int flags); +typedef int (*DSO_free_t)(DSO *dso); + +static DSO_dsobyaddr_t DSO_dsobyaddr; +static DSO_free_t DSO_free; + # include typedef void * SHLIB; typedef void * SHLIB_SYM; # define SHLIB_INIT NULL -# define SHARED_LIBRARY_SUFFIX ".so" - -static int shlib_load(char *filename, SHLIB *lib) +static int shlib_load(const char *filename, SHLIB *lib) { - char *tmpfile; - size_t filenamelen = strlen(filename); - - /* Total length = base filename len + suffix len + 1 for NULL terminator */ - tmpfile = malloc(filenamelen + sizeof(SHARED_LIBRARY_SUFFIX) + 1); - if (tmpfile == NULL) - return 0; - strcpy(tmpfile, filename); - strcpy(tmpfile + filenamelen, SHARED_LIBRARY_SUFFIX); - - *lib = dlopen(tmpfile, RTLD_GLOBAL | RTLD_LAZY); - free(tmpfile); + *lib = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); if (*lib == NULL) return 0; @@ -90,7 +89,7 @@ typedef HINSTANCE SHLIB; typedef void * SHLIB_SYM; # define SHLIB_INIT 0 -static int shlib_load(char *filename, SHLIB *lib) +static int shlib_load(const char *filename, SHLIB *lib) { *lib = LoadLibraryA(filename); if (*lib == NULL) @@ -116,17 +115,16 @@ static int shlib_close(SHLIB lib) #endif -/* The test is only currently implemented for DSO_DLFCN and DSO_WIN32 */ -#if defined(DSO_DLFCN) || defined(DSO_WIN32) - # define CRYPTO_FIRST_OPT "-crypto_first" # define SSL_FIRST_OPT "-ssl_first" # define JUST_CRYPTO_OPT "-just_crypto" +# define DSO_REFTEST_OPT "-dso_ref" enum test_types_en { CRYPTO_FIRST, SSL_FIRST, - JUST_CRYPTO + JUST_CRYPTO, + DSO_REFTEST }; int main(int argc, char **argv) @@ -137,7 +135,7 @@ int main(int argc, char **argv) void (*func) (void); SHLIB_SYM sym; } tls_method_sym, ssl_ctx_new_sym, ssl_ctx_free_sym, err_get_error_sym, - openssl_version_num_sym; + openssl_version_num_sym, dso_dsobyaddr_sym, dso_free_sym; enum test_types_en test_type; int i; @@ -152,6 +150,8 @@ int main(int argc, char **argv) test_type = SSL_FIRST; } else if (strcmp(argv[1], JUST_CRYPTO_OPT) == 0) { test_type = JUST_CRYPTO; + } else if (strcmp(argv[1], DSO_REFTEST_OPT) == 0) { + test_type = DSO_REFTEST; } else { printf("Unrecognised argument\n"); return 1; @@ -159,7 +159,8 @@ int main(int argc, char **argv) for (i = 0; i < 2; i++) { if ((i == 0 && (test_type == CRYPTO_FIRST - || test_type == JUST_CRYPTO)) + || test_type == JUST_CRYPTO + || test_type == DSO_REFTEST)) || (i == 1 && test_type == SSL_FIRST)) { if (!shlib_load(argv[2], &cryptolib)) { printf("Unable to load libcrypto\n"); @@ -175,7 +176,7 @@ int main(int argc, char **argv) } } - if (test_type != JUST_CRYPTO) { + if (test_type != JUST_CRYPTO && test_type != DSO_REFTEST) { if (!shlib_sym(ssllib, TLS_METHOD, &tls_method_sym.sym) || !shlib_sym(ssllib, SSL_CTX_NEW, &ssl_ctx_new_sym.sym) || !shlib_sym(ssllib, SSL_CTX_FREE, &ssl_ctx_free_sym.sym)) { @@ -210,11 +211,57 @@ int main(int argc, char **argv) return 1; } - if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER) { + /* + * The bits that COMPATIBILITY_MASK lets through MUST be the same in + * the library and in the application. + * The bits that are masked away MUST be a larger or equal number in + * the library compared to the application. + */ +# define COMPATIBILITY_MASK 0xfff00000L + if ((OpenSSL_version_num() & COMPATIBILITY_MASK) + != (OPENSSL_VERSION_NUMBER & COMPATIBILITY_MASK)) { printf("Unexpected library version loaded\n"); return 1; } + if ((OpenSSL_version_num() & ~COMPATIBILITY_MASK) + < (OPENSSL_VERSION_NUMBER & ~COMPATIBILITY_MASK)) { + printf("Unexpected library version loaded\n"); + return 1; + } + + if (test_type == DSO_REFTEST) { +# ifdef DSO_DLFCN + /* + * This is resembling the code used in ossl_init_base() and + * OPENSSL_atexit() to block unloading the library after dlclose(). + * We are not testing this on Windows, because it is done there in a + * completely different way. Especially as a call to DSO_dsobyaddr() + * will always return an error, because DSO_pathbyaddr() is not + * implemented there. + */ + if (!shlib_sym(cryptolib, DSO_DSOBYADDR, &dso_dsobyaddr_sym.sym) + || !shlib_sym(cryptolib, DSO_FREE, &dso_free_sym.sym)) { + printf("Unable to load crypto dso symbols\n"); + return 1; + } + + DSO_dsobyaddr = (DSO_dsobyaddr_t)dso_dsobyaddr_sym.func; + DSO_free = (DSO_free_t)dso_free_sym.func; + + { + DSO *hndl; + /* use known symbol from crypto module */ + if ((hndl = DSO_dsobyaddr((void (*)())ERR_get_error, 0)) != NULL) { + DSO_free(hndl); + } else { + printf("Unable to obtain DSO reference from crypto symbol\n"); + return 1; + } + } +# endif /* DSO_DLFCN */ + } + for (i = 0; i < 2; i++) { if ((i == 0 && test_type == CRYPTO_FIRST) || (i == 1 && test_type == SSL_FIRST)) { @@ -224,7 +271,8 @@ int main(int argc, char **argv) } } if ((i == 0 && (test_type == SSL_FIRST - || test_type == JUST_CRYPTO)) + || test_type == JUST_CRYPTO + || test_type == DSO_REFTEST)) || (i == 1 && test_type == CRYPTO_FIRST)) { if (!shlib_close(cryptolib)) { printf("Unable to close libcrypto\n");