[openssl-commits] [openssl] master update
Matt Caswell
matt at openssl.org
Wed Nov 2 23:40:17 UTC 2016
The branch master has been updated
via 2b59d1beaad43d9cf8eb916a437db63bc8ce1d3a (commit)
via b6d5ba1a9f004d637acac18ae3519fe063b6b5e1 (commit)
via b987d748e46d4ec19a45e5ec9e890a9003a361d6 (commit)
via 5836780f436e03be231ff245f04f2f9f2f0ede91 (commit)
via b39eda7ee69a9277c722f8789736e00dc680cda6 (commit)
via cb6ea61c161e88aa0268c77f308469a67b2ec063 (commit)
from ce95f3b724f71f42dd57af4a0a8e2f571deaf94d (commit)
- Log -----------------------------------------------------------------
commit 2b59d1beaad43d9cf8eb916a437db63bc8ce1d3a
Author: Matt Caswell <matt at openssl.org>
Date: Fri Oct 28 11:03:22 2016 +0100
Implement GET_MODULE_HANDLE_EX_FLAG_PIN for windows
Rather than leaking a reference, just call GetModuleHandleEx and pin the
module on Windows.
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit b6d5ba1a9f004d637acac18ae3519fe063b6b5e1
Author: Matt Caswell <matt at openssl.org>
Date: Tue Oct 18 15:11:57 2016 +0100
Link using -znodelete
Instead of deliberately leaking a reference to ourselves, use nodelete
which does this more neatly. Only for Linux at the moment.
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit b987d748e46d4ec19a45e5ec9e890a9003a361d6
Author: Matt Caswell <matt at openssl.org>
Date: Tue Oct 18 14:16:35 2016 +0100
Add a test to dynamically load and unload the libraries
This should demonstrate that the atexit() handling is working properly (or
at least not crashing) on process exit.
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit 5836780f436e03be231ff245f04f2f9f2f0ede91
Author: Matt Caswell <matt at openssl.org>
Date: Tue Oct 18 14:13:25 2016 +0100
Ensure that libcrypto and libssl do not unload until the process exits
Because we use atexit() to cleanup after ourselves, this will cause a
problem if we have been dynamically loaded and then unloaded again: the
atexit() handler may no longer be there.
Most modern atexit() implementations can handle this, however there are
still difficulties if libssl gets unloaded before libcrypto, because of
the atexit() callback that libcrypto makes to libssl.
The most robust solution seems to be to ensure that libcrypto and libssl
never unload. This is done by simply deliberately leaking a dlopen()
reference to them.
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit b39eda7ee69a9277c722f8789736e00dc680cda6
Author: Matt Caswell <matt at openssl.org>
Date: Sat Oct 15 16:01:40 2016 +0100
Add a DSO_dsobyaddr() function
This works the same way as DSO_pathbyaddr() but instead returns a ptr to
the DSO that contains the provided symbol.
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit cb6ea61c161e88aa0268c77f308469a67b2ec063
Author: Matt Caswell <matt at openssl.org>
Date: Sat Oct 15 15:23:03 2016 +0100
Partial revert of 3d8b2ec42 to add back DSO_pathbyaddr
Commit 3d8b2ec42 removed various unused functions. However now we need to
use one of them! This commit resurrects DSO_pathbyaddr(). We're not going to
resurrect the Windows version though because what we need to achieve can be
done a different way on Windows.
Reviewed-by: Tim Hudson <tjh at openssl.org>
-----------------------------------------------------------------------
Summary of changes:
Configurations/10-main.conf | 25 ++--
crypto/dso/dso_dl.c | 34 ++++++
crypto/dso/dso_dlfcn.c | 34 ++++++
crypto/dso/dso_err.c | 2 +
crypto/dso/dso_lib.c | 35 +++++-
crypto/dso/dso_locl.h | 2 +
crypto/dso/dso_vms.c | 4 +-
crypto/dso/dso_win32.c | 1 +
crypto/init.c | 70 +++++++++++
include/internal/dso.h | 24 ++++
test/build.info | 6 +
test/recipes/90-test_shlibload.t | 37 ++++++
test/shlibloadtest.c | 243 +++++++++++++++++++++++++++++++++++++++
util/libcrypto.num | 2 +
14 files changed, 503 insertions(+), 16 deletions(-)
create mode 100644 test/recipes/90-test_shlibload.t
create mode 100644 test/shlibloadtest.c
diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf
index 9b4c78f..b77efbf 100644
--- a/Configurations/10-main.conf
+++ b/Configurations/10-main.conf
@@ -632,7 +632,8 @@ sub vms_info {
thread_scheme => "pthreads",
dso_scheme => "dlfcn",
shared_target => "linux-shared",
- shared_cflag => "-fPIC",
+ shared_cflag => "-fPIC -DOPENSSL_USE_NODELETE",
+ shared_ldflag => "-znodelete",
shared_extension => ".so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
},
"linux-generic64" => {
@@ -648,14 +649,14 @@ sub vms_info {
inherit_from => [ "linux-generic64", asm("ppc64_asm") ],
cflags => add("-m64 -DB_ENDIAN"),
perlasm_scheme => "linux64",
- shared_ldflag => "-m64",
+ shared_ldflag => add("-m64"),
multilib => "64",
},
"linux-ppc64le" => {
inherit_from => [ "linux-generic64", asm("ppc64_asm") ],
cflags => add("-m64 -DL_ENDIAN"),
perlasm_scheme => "linux64le",
- shared_ldflag => "-m64",
+ shared_ldflag => add("-m64"),
},
"linux-armv4" => {
@@ -711,7 +712,7 @@ sub vms_info {
inherit_from => [ "linux-generic32", asm("mips32_asm") ],
cflags => add("-mabi=32 -DBN_DIV3W"),
perlasm_scheme => "o32",
- shared_ldflag => "-mabi=32",
+ shared_ldflag => add("-mabi=32"),
},
# mips32 and mips64 below refer to contemporary MIPS Architecture
# specifications, MIPS32 and MIPS64, rather than to kernel bitness.
@@ -720,14 +721,14 @@ sub vms_info {
cflags => add("-mabi=n32 -DBN_DIV3W"),
bn_ops => "SIXTY_FOUR_BIT RC4_CHAR",
perlasm_scheme => "n32",
- shared_ldflag => "-mabi=n32",
+ shared_ldflag => add("-mabi=n32"),
multilib => "32",
},
"linux64-mips64" => {
inherit_from => [ "linux-generic64", asm("mips64_asm") ],
cflags => add("-mabi=64 -DBN_DIV3W"),
perlasm_scheme => "64",
- shared_ldflag => "-mabi=64",
+ shared_ldflag => add("-mabi=64"),
multilib => "64",
},
@@ -754,7 +755,7 @@ sub vms_info {
cflags => add("-m64 -DL_ENDIAN"),
bn_ops => "SIXTY_FOUR_BIT_LONG",
perlasm_scheme => "elf",
- shared_ldflag => "-m64",
+ shared_ldflag => add("-m64"),
multilib => "64",
},
"linux-x86_64-clang" => {
@@ -781,7 +782,7 @@ sub vms_info {
inherit_from => [ "linux-generic64", asm("s390x_asm") ],
cflags => add("-m64 -DB_ENDIAN"),
perlasm_scheme => "64",
- shared_ldflag => "-m64",
+ shared_ldflag => add("-m64"),
multilib => "64",
},
"linux32-s390x" => {
@@ -805,7 +806,7 @@ sub vms_info {
cflags => add("-m31 -Wa,-mzarch -DB_ENDIAN"),
bn_asm_src => sub { my $r=join(" ", at _); $r=~s|asm/s390x\.S|bn_asm.c|; $r; },
perlasm_scheme => "31",
- shared_ldflag => "-m31",
+ shared_ldflag => add("-m31"),
multilib => "/highgprs",
},
@@ -821,14 +822,14 @@ sub vms_info {
# but -Wa,-Av8plus should do the trick no matter what.
inherit_from => [ "linux-generic32", asm("sparcv9_asm") ],
cflags => add("-m32 -mcpu=ultrasparc -Wa,-Av8plus -DB_ENDIAN -DBN_DIV2W"),
- shared_ldflag => "-m32",
+ shared_ldflag => add("-m32"),
},
"linux64-sparcv9" => {
# GCC 3.1 is a requirement
inherit_from => [ "linux-generic64", asm("sparcv9_asm") ],
cflags => add("-m64 -mcpu=ultrasparc -DB_ENDIAN"),
bn_ops => "BN_LLONG RC4_CHAR",
- shared_ldflag => "-m64",
+ shared_ldflag => add("-m64"),
multilib => "64",
},
@@ -857,7 +858,7 @@ sub vms_info {
dso_scheme => "dlfcn",
shared_target => "linux-shared",
shared_cflag => "--pic",
- shared_ldflag => "-z --sysv --shared",
+ shared_ldflag => add("-z --sysv --shared"),
shared_extension => ".so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
ranlib => "true",
},
diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c
index bc29fb2..d80bf56 100644
--- a/crypto/dso/dso_dl.c
+++ b/crypto/dso/dso_dl.c
@@ -22,6 +22,7 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname);
static char *dl_name_converter(DSO *dso, const char *filename);
static char *dl_merger(DSO *dso, const char *filespec1,
const char *filespec2);
+static int dl_pathbyaddr(void *addr, char *path, int sz);
static void *dl_globallookup(const char *name);
static DSO_METHOD dso_meth_dl = {
@@ -34,6 +35,7 @@ static DSO_METHOD dso_meth_dl = {
dl_merger,
NULL, /* init */
NULL, /* finish */
+ dl_pathbyaddr,
dl_globallookup
};
@@ -235,6 +237,38 @@ static char *dl_name_converter(DSO *dso, const char *filename)
return (translated);
}
+static int dl_pathbyaddr(void *addr, char *path, int sz)
+{
+ struct shl_descriptor inf;
+ int i, len;
+
+ if (addr == NULL) {
+ union {
+ int (*f) (void *, char *, int);
+ void *p;
+ } t = {
+ dl_pathbyaddr
+ };
+ addr = t.p;
+ }
+
+ for (i = -1; shl_get_r(i, &inf) == 0; i++) {
+ if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) ||
+ ((size_t)addr >= inf.dstart && (size_t)addr < inf.dend)) {
+ len = (int)strlen(inf.filename);
+ if (sz <= 0)
+ return len + 1;
+ if (len >= sz)
+ len = sz - 1;
+ memcpy(path, inf.filename, len);
+ path[len++] = 0;
+ return len;
+ }
+ }
+
+ return -1;
+}
+
static void *dl_globallookup(const char *name)
{
void *ret;
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index 624052b..a4b0cdd 100644
--- a/crypto/dso/dso_dlfcn.c
+++ b/crypto/dso/dso_dlfcn.c
@@ -44,6 +44,7 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
static char *dlfcn_name_converter(DSO *dso, const char *filename);
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2);
+static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
static void *dlfcn_globallookup(const char *name);
static DSO_METHOD dso_meth_dlfcn = {
@@ -56,6 +57,7 @@ static DSO_METHOD dso_meth_dlfcn = {
dlfcn_merger,
NULL, /* init */
NULL, /* finish */
+ dlfcn_pathbyaddr,
dlfcn_globallookup
};
@@ -306,6 +308,38 @@ static int dladdr(void *address, Dl_info *dl)
}
# endif /* __sgi */
+static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
+{
+# ifdef HAVE_DLINFO
+ Dl_info dli;
+ int len;
+
+ if (addr == NULL) {
+ union {
+ int (*f) (void *, char *, int);
+ void *p;
+ } t = {
+ dlfcn_pathbyaddr
+ };
+ addr = t.p;
+ }
+
+ if (dladdr(addr, &dli)) {
+ len = (int)strlen(dli.dli_fname);
+ if (sz <= 0)
+ return len + 1;
+ if (len >= sz)
+ len = sz - 1;
+ memcpy(path, dli.dli_fname, len);
+ path[len++] = 0;
+ return len;
+ }
+
+ ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());
+# endif
+ return -1;
+}
+
static void *dlfcn_globallookup(const char *name)
{
void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c
index a180580..07588d5 100644
--- a/crypto/dso/dso_err.c
+++ b/crypto/dso/dso_err.c
@@ -38,6 +38,7 @@ static ERR_STRING_DATA DSO_str_functs[] = {
{ERR_FUNC(DSO_F_DSO_LOAD), "DSO_load"},
{ERR_FUNC(DSO_F_DSO_MERGE), "DSO_merge"},
{ERR_FUNC(DSO_F_DSO_NEW_METHOD), "DSO_new_method"},
+ {ERR_FUNC(DSO_F_DSO_PATHBYADDR), "DSO_pathbyaddr"},
{ERR_FUNC(DSO_F_DSO_SET_FILENAME), "DSO_set_filename"},
{ERR_FUNC(DSO_F_DSO_UP_REF), "DSO_up_ref"},
{ERR_FUNC(DSO_F_VMS_BIND_SYM), "vms_bind_sym"},
@@ -50,6 +51,7 @@ static ERR_STRING_DATA DSO_str_functs[] = {
{ERR_FUNC(DSO_F_WIN32_LOAD), "win32_load"},
{ERR_FUNC(DSO_F_WIN32_MERGER), "win32_merger"},
{ERR_FUNC(DSO_F_WIN32_NAME_CONVERTER), "win32_name_converter"},
+ {ERR_FUNC(DSO_F_WIN32_PATHBYADDR), "win32_pathbyaddr"},
{ERR_FUNC(DSO_F_WIN32_SPLITTER), "win32_splitter"},
{ERR_FUNC(DSO_F_WIN32_UNLOAD), "win32_unload"},
{0, NULL}
diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c
index bea8776..52816df 100644
--- a/crypto/dso/dso_lib.c
+++ b/crypto/dso/dso_lib.c
@@ -73,9 +73,11 @@ int DSO_free(DSO *dso)
return 1;
REF_ASSERT_ISNT(i < 0);
- if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
- DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
- return 0;
+ if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
+ if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
+ DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
+ return 0;
+ }
}
if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
@@ -304,6 +306,33 @@ char *DSO_convert_filename(DSO *dso, const char *filename)
return (result);
}
+int DSO_pathbyaddr(void *addr, char *path, int sz)
+{
+ DSO_METHOD *meth = default_DSO_meth;
+ if (meth == NULL)
+ meth = DSO_METHOD_openssl();
+ if (meth->pathbyaddr == NULL) {
+ DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
+ return -1;
+ }
+ return (*meth->pathbyaddr) (addr, path, sz);
+}
+
+DSO *DSO_dsobyaddr(void *addr, int flags)
+{
+ DSO *ret = NULL;
+ char *filename = NULL;
+ int len = DSO_pathbyaddr(addr, NULL, 0);
+
+ filename = OPENSSL_malloc(len);
+ if (filename != NULL
+ && DSO_pathbyaddr(addr, filename, len) == len)
+ ret = DSO_load(NULL, filename, NULL, flags);
+
+ OPENSSL_free(filename);
+ return ret;
+}
+
void *DSO_global_lookup(const char *name)
{
DSO_METHOD *meth = default_DSO_meth;
diff --git a/crypto/dso/dso_locl.h b/crypto/dso/dso_locl.h
index 1976787..fbfad05 100644
--- a/crypto/dso/dso_locl.h
+++ b/crypto/dso/dso_locl.h
@@ -99,6 +99,8 @@ struct dso_meth_st {
/* [De]Initialisation handlers. */
int (*init) (DSO *dso);
int (*finish) (DSO *dso);
+ /* Return pathname of the module containing location */
+ int (*pathbyaddr) (void *addr, char *path, int sz);
/* Perform global symbol lookup, i.e. among *all* modules */
void *(*globallookup) (const char *symname);
};
diff --git a/crypto/dso/dso_vms.c b/crypto/dso/dso_vms.c
index 2e0d84c..e3c157b 100644
--- a/crypto/dso/dso_vms.c
+++ b/crypto/dso/dso_vms.c
@@ -50,7 +50,9 @@ static DSO_METHOD dso_meth_vms = {
vms_name_converter,
vms_merger,
NULL, /* init */
- NULL /* finish */
+ NULL, /* finish */
+ NULL, /* pathbyaddr */
+ NULL /* globallookup */
};
/*
diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c
index 4ac6e71..4a4c34a 100644
--- a/crypto/dso/dso_win32.c
+++ b/crypto/dso/dso_win32.c
@@ -77,6 +77,7 @@ static DSO_METHOD dso_meth_win32 = {
win32_merger,
NULL, /* init */
NULL, /* finish */
+ NULL, /* pathbyaddr */
win32_globallookup
};
diff --git a/crypto/init.c b/crypto/init.c
index 93ec7bb..4363bee 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <assert.h>
#include <internal/thread_once.h>
+#include <internal/dso.h>
static int stopped = 0;
@@ -79,6 +80,34 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base)
return 0;
OPENSSL_cpuid_setup();
base_inited = 1;
+
+#ifndef OPENSSL_USE_NODELETE
+# ifdef DSO_WIN32
+ {
+ HMODULE handle = NULL;
+ BOOL ret;
+
+ /* We don't use the DSO route for WIN32 because there is a better way */
+ ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+ | GET_MODULE_HANDLE_EX_FLAG_PIN,
+ (void *)&base_inited, &handle);
+
+ return (ret == TRUE) ? 1 : 0;
+ }
+# else
+ /*
+ * Deliberately leak a reference to ourselves. This will force the library
+ * to remain loaded until the atexit() handler is run a process exit.
+ */
+ {
+ DSO *dso = NULL;
+
+ dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
+ DSO_free(dso);
+ }
+# endif
+#endif
+
return 1;
}
@@ -575,6 +604,47 @@ int OPENSSL_atexit(void (*handler)(void))
{
OPENSSL_INIT_STOP *newhand;
+#ifndef OPENSSL_USE_NODELETE
+ {
+ union {
+ void *sym;
+ void (*func)(void);
+ } handlersym;
+
+ handlersym.func = handler;
+# ifdef DSO_WIN32
+ {
+ HMODULE handle = NULL;
+ BOOL ret;
+
+ /*
+ * We don't use the DSO route for WIN32 because there is a better
+ * way
+ */
+ ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+ | GET_MODULE_HANDLE_EX_FLAG_PIN,
+ handlersym.sym, &handle);
+
+ if (!ret)
+ return 0;
+ }
+# else
+ /*
+ * Deliberately leak a reference to the handler. This will force the
+ * library/code containing the handler to remain loaded until we run the
+ * atexit handler. If -znodelete has been used then this is
+ * unneccessary.
+ */
+ {
+ DSO *dso = NULL;
+
+ dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
+ DSO_free(dso);
+ }
+# endif
+ }
+#endif
+
newhand = OPENSSL_malloc(sizeof(*newhand));
if (newhand == NULL)
return 0;
diff --git a/include/internal/dso.h b/include/internal/dso.h
index 79d98f4..6acd501 100644
--- a/include/internal/dso.h
+++ b/include/internal/dso.h
@@ -43,6 +43,11 @@ extern "C" {
# define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02
/*
+ * Don't unload the DSO when we call DSO_free()
+ */
+# define DSO_FLAG_NO_UNLOAD_ON_FREE 0x04
+
+/*
* This flag loads the library with public symbols. Meaning: The exported
* symbols of this library are public to all libraries loaded after this
* library. At the moment only implemented in unix.
@@ -131,6 +136,23 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname);
DSO_METHOD *DSO_METHOD_openssl(void);
/*
+ * This function writes null-terminated pathname of DSO module containing
+ * 'addr' into 'sz' large caller-provided 'path' and returns the number of
+ * characters [including trailing zero] written to it. If 'sz' is 0 or
+ * negative, 'path' is ignored and required amount of charachers [including
+ * trailing zero] to accommodate pathname is returned. If 'addr' is NULL, then
+ * pathname of cryptolib itself is returned. Negative or zero return value
+ * denotes error.
+ */
+int DSO_pathbyaddr(void *addr, char *path, int sz);
+
+/*
+ * Like DSO_pathbyaddr() but instead returns a handle to the DSO for the symbol
+ * or NULL on error.
+ */
+DSO *DSO_dsobyaddr(void *addr, int flags);
+
+/*
* This function should be used with caution! It looks up symbols in *all*
* loaded modules and if module gets unloaded by somebody else attempt to
* dereference the pointer is doomed to have fatal consequences. Primary
@@ -171,6 +193,7 @@ int ERR_load_DSO_strings(void);
# define DSO_F_DSO_LOAD 112
# define DSO_F_DSO_MERGE 132
# define DSO_F_DSO_NEW_METHOD 113
+# define DSO_F_DSO_PATHBYADDR 105
# define DSO_F_DSO_SET_FILENAME 129
# define DSO_F_DSO_UP_REF 114
# define DSO_F_VMS_BIND_SYM 115
@@ -183,6 +206,7 @@ int ERR_load_DSO_strings(void);
# define DSO_F_WIN32_LOAD 120
# define DSO_F_WIN32_MERGER 134
# define DSO_F_WIN32_NAME_CONVERTER 125
+# define DSO_F_WIN32_PATHBYADDR 109
# define DSO_F_WIN32_SPLITTER 136
# define DSO_F_WIN32_UNLOAD 121
diff --git a/test/build.info b/test/build.info
index 5246969..818d073 100644
--- a/test/build.info
+++ b/test/build.info
@@ -282,6 +282,12 @@ IF[{- !$disabled{tests} -}]
DEPEND[dtls_mtu_test]=../libcrypto ../libssl
ENDIF
+ IF[{- !disabled{shared} -}]
+ PROGRAMS_NO_INST=shlibloadtest
+ SOURCE[shlibloadtest]=shlibloadtest.c
+ INCLUDE[shlibloadtest]=../include
+ ENDIF
+
IF[{- $disabled{shared} -}]
PROGRAMS_NO_INST=wpackettest cipher_overhead_test
SOURCE[wpackettest]=wpackettest.c testutil.c
diff --git a/test/recipes/90-test_shlibload.t b/test/recipes/90-test_shlibload.t
new file mode 100644
index 0000000..dc35613
--- /dev/null
+++ b/test/recipes/90-test_shlibload.t
@@ -0,0 +1,37 @@
+#! /usr/bin/env perl
+# Copyright 2016 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
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+
+use OpenSSL::Test qw/:DEFAULT bldtop_dir/;
+use OpenSSL::Test::Utils;
+
+#Load configdata.pm
+
+BEGIN {
+ setup("test_shlibload");
+}
+use lib bldtop_dir('.');
+use configdata;
+
+plan skip_all => "Test only supported in a shared build" if disabled("shared");
+
+plan tests => 3;
+
+ok(run(test(["shlibloadtest", "-crypto_first",
+ $unified_info{sharednames}->{libcrypto},
+ $unified_info{sharednames}->{libssl}])),
+ "running shlibloadtest -crypto_first");
+ok(run(test(["shlibloadtest", "-ssl_first",
+ $unified_info{sharednames}->{libcrypto},
+ $unified_info{sharednames}->{libssl}])),
+ "running shlibloadtest -ssl_first");
+ok(run(test(["shlibloadtest", "-just_crypto",
+ $unified_info{sharednames}->{libcrypto},
+ $unified_info{sharednames}->{libssl}])),
+ "running shlibloadtest -just_crypto");
+
diff --git a/test/shlibloadtest.c b/test/shlibloadtest.c
new file mode 100644
index 0000000..be1e784
--- /dev/null
+++ b/test/shlibloadtest.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <openssl/opensslv.h>
+
+#define SSL_CTX_NEW "SSL_CTX_new"
+#define SSL_CTX_FREE "SSL_CTX_free"
+#define TLS_METHOD "TLS_method"
+
+#define ERR_GET_ERROR "ERR_get_error"
+#define OPENSSL_VERSION_NUM_FUNC "OpenSSL_version_num"
+
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct ssl_method_st SSL_METHOD;
+typedef const SSL_METHOD * (*TLS_method_t)(void);
+typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth);
+typedef void (*SSL_CTX_free_t)(SSL_CTX *);
+
+typedef unsigned long (*ERR_get_error_t)(void);
+typedef unsigned long (*OpenSSL_version_num_t)(void);
+
+TLS_method_t TLS_method;
+SSL_CTX_new_t SSL_CTX_new;
+SSL_CTX_free_t SSL_CTX_free;
+
+ERR_get_error_t ERR_get_error;
+OpenSSL_version_num_t OpenSSL_version_num;
+
+
+#ifdef DSO_DLFCN
+
+# include <dlfcn.h>
+
+typedef void * SHLIB;
+typedef void * SHLIB_SYM;
+
+# define SHARED_LIBRARY_SUFFIX ".so"
+
+static int shlib_load(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);
+
+ if (*lib == NULL)
+ return 0;
+
+ return 1;
+}
+
+static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
+{
+ *sym = dlsym(lib, symname);
+
+ return *sym != NULL;
+}
+
+static int shlib_close(SHLIB lib)
+{
+ if (dlclose(lib) != 0)
+ return 0;
+
+ return 1;
+}
+
+#elif defined(DSO_WIN32)
+
+# include <windows.h>
+
+typedef HINSTANCE SHLIB;
+typedef void * SHLIB_SYM;
+
+static int shlib_load(char *filename, SHLIB *lib)
+{
+ *lib = LoadLibraryA(filename);
+ if (*lib == NULL)
+ return 0;
+
+ return 1;
+}
+
+static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
+{
+ *sym = (SHLIB_SYM)GetProcAddress(lib, symname);
+
+ return *sym != NULL;
+}
+
+static int shlib_close(SHLIB lib)
+{
+ if (FreeLibrary(lib) == 0)
+ return 0;
+
+ return 1;
+}
+
+#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"
+
+enum test_types_en {
+ CRYPTO_FIRST,
+ SSL_FIRST,
+ JUST_CRYPTO
+};
+
+int main(int argc, char **argv)
+{
+ SHLIB ssllib, cryptolib;
+ SSL_CTX *ctx;
+ union {
+ 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;
+ enum test_types_en test_type;
+ int i;
+
+ if (argc != 4) {
+ printf("Unexpected number of arguments\n");
+ return 1;
+ }
+
+ if (strcmp(argv[1], CRYPTO_FIRST_OPT) == 0) {
+ test_type = CRYPTO_FIRST;
+ } else if (strcmp(argv[1], SSL_FIRST_OPT) == 0) {
+ test_type = SSL_FIRST;
+ } else if (strcmp(argv[1], JUST_CRYPTO_OPT) == 0) {
+ test_type = JUST_CRYPTO;
+ } else {
+ printf("Unrecognised argument\n");
+ return 1;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if ((i == 0 && (test_type == CRYPTO_FIRST
+ || test_type == JUST_CRYPTO))
+ || (i == 1 && test_type == SSL_FIRST)) {
+ if (!shlib_load(argv[2], &cryptolib)) {
+ printf("Unable to load libcrypto\n");
+ return 1;
+ }
+ }
+ if ((i == 0 && test_type == SSL_FIRST)
+ || (i == 1 && test_type == CRYPTO_FIRST)) {
+ if (!shlib_load(argv[3], &ssllib)) {
+ printf("Unable to load libssl\n");
+ return 1;
+ }
+ }
+ }
+
+ if (test_type != JUST_CRYPTO) {
+ 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)) {
+ printf("Unable to load ssl symbols\n");
+ return 1;
+ }
+
+ TLS_method = (TLS_method_t)tls_method_sym.func;
+ SSL_CTX_new = (SSL_CTX_new_t)ssl_ctx_new_sym.func;
+ SSL_CTX_free = (SSL_CTX_free_t)ssl_ctx_free_sym.func;
+
+ ctx = SSL_CTX_new(TLS_method());
+ if (ctx == NULL) {
+ printf("Unable to create SSL_CTX\n");
+ return 1;
+ }
+ SSL_CTX_free(ctx);
+ }
+
+ if (!shlib_sym(cryptolib, ERR_GET_ERROR, &err_get_error_sym.sym)
+ || !shlib_sym(cryptolib, OPENSSL_VERSION_NUM_FUNC,
+ &openssl_version_num_sym.sym)) {
+ printf("Unable to load crypto symbols\n");
+ return 1;
+ }
+
+ ERR_get_error = (ERR_get_error_t)err_get_error_sym.func;
+ OpenSSL_version_num = (OpenSSL_version_num_t)openssl_version_num_sym.func;
+
+ if (ERR_get_error() != 0) {
+ printf("Unexpected error in error queue\n");
+ return 1;
+ }
+
+ if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER) {
+ printf("Unexpected library version loaded\n");
+ return 1;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if ((i == 0 && test_type == CRYPTO_FIRST)
+ || (i == 1 && test_type == SSL_FIRST)) {
+ if (!shlib_close(ssllib)) {
+ printf("Unable to close libssl\n");
+ return 1;
+ }
+ }
+ if ((i == 0 && (test_type == SSL_FIRST
+ || test_type == JUST_CRYPTO))
+ || (i == 1 && test_type == CRYPTO_FIRST)) {
+ if (!shlib_close(cryptolib)) {
+ printf("Unable to close libcrypto\n");
+ return 1;
+ }
+ }
+ }
+
+ printf("Success\n");
+ return 0;
+}
+#else
+int main(void)
+{
+ printf("Test not implemented on this platform\n");
+ return 0;
+}
+#endif
diff --git a/util/libcrypto.num b/util/libcrypto.num
index e04580c..0b4190b 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4216,3 +4216,5 @@ BIO_meth_get_read_ex 4166 1_1_1 EXIST::FUNCTION:
BIO_write_ex 4167 1_1_1 EXIST::FUNCTION:
BIO_meth_get_write_ex 4168 1_1_1 EXIST::FUNCTION:
BIO_meth_set_write_ex 4169 1_1_1 EXIST::FUNCTION:
+DSO_pathbyaddr 4170 1_1_0c EXIST::FUNCTION:
+DSO_dsobyaddr 4171 1_1_0c EXIST::FUNCTION:
More information about the openssl-commits
mailing list