[openssl-commits] [openssl] OpenSSL_1_1_0-stable update
Matt Caswell
matt at openssl.org
Wed Nov 2 23:40:29 UTC 2016
The branch OpenSSL_1_1_0-stable has been updated
via 2e6b83f608b7a4b315146895ac911e8c06d40db1 (commit)
via 848dc9619049f6aaad91b367eed309d987009e5e (commit)
via 389d4655b143bc6d495ca6c48809aac8f4356e01 (commit)
via 4af9f7fe79ff82b90c16969b7e5871435056377b (commit)
via f722f18e1a3560c13bd018711a30acca73c8d619 (commit)
via 93558bf5190226494d3b549397fbf94214846d0d (commit)
from 717f4026d593119cf493b3c1e045462c540f4cb3 (commit)
- Log -----------------------------------------------------------------
commit 2e6b83f608b7a4b315146895ac911e8c06d40db1
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>
(cherry picked from commit 2b59d1beaad43d9cf8eb916a437db63bc8ce1d3a)
commit 848dc9619049f6aaad91b367eed309d987009e5e
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>
(cherry picked from commit b6d5ba1a9f004d637acac18ae3519fe063b6b5e1)
commit 389d4655b143bc6d495ca6c48809aac8f4356e01
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>
(cherry picked from commit b987d748e46d4ec19a45e5ec9e890a9003a361d6)
commit 4af9f7fe79ff82b90c16969b7e5871435056377b
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>
(cherry picked from commit 5836780f436e03be231ff245f04f2f9f2f0ede91)
commit f722f18e1a3560c13bd018711a30acca73c8d619
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>
(cherry picked from commit b39eda7ee69a9277c722f8789736e00dc680cda6)
commit 93558bf5190226494d3b549397fbf94214846d0d
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>
(cherry picked from commit cb6ea61c161e88aa0268c77f308469a67b2ec063)
-----------------------------------------------------------------------
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 | 23 ++++
test/build.info | 6 +
test/recipes/90-test_shlibload.t | 37 ++++++
test/shlibloadtest.c | 243 +++++++++++++++++++++++++++++++++++++++
util/libcrypto.num | 2 +
14 files changed, 502 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 adb40e3..c80d02f 100644
--- a/Configurations/10-main.conf
+++ b/Configurations/10-main.conf
@@ -631,7 +631,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" => {
@@ -647,14 +648,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" => {
@@ -710,7 +711,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.
@@ -719,14 +720,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",
},
@@ -753,7 +754,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" => {
@@ -779,7 +780,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" => {
@@ -803,7 +804,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",
},
@@ -819,14 +820,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",
},
@@ -855,7 +856,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 90d387e..b9a98dd 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 7423ecc..a939cb1 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 970beeb..f5de8a2 100644
--- a/include/internal/dso.h
+++ b/include/internal/dso.h
@@ -43,6 +43,10 @@ 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
+/*
* The following flag controls the translation of symbol names to upper case.
* This is currently only being implemented for OpenVMS.
*/
@@ -137,6 +141,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
@@ -177,6 +198,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
@@ -189,6 +211,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 b8fc431..e3a961d 100644
--- a/test/build.info
+++ b/test/build.info
@@ -274,6 +274,12 @@ IF[{- !$disabled{tests} -}]
SOURCE[bio_enc_test]=bio_enc_test.c
INCLUDE[bio_enc_test]=../include
DEPEND[bio_enc_test]=../libcrypto
+
+ IF[{- !disabled{shared} -}]
+ PROGRAMS_NO_INST=shlibloadtest
+ SOURCE[shlibloadtest]=shlibloadtest.c
+ INCLUDE[shlibloadtest]=../include
+ ENDIF
ENDIF
{-
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 db6732e..a16cc9f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4206,3 +4206,5 @@ ECPARAMETERS_new 4156 1_1_0 EXIST::FUNCTION:EC
OCSP_RESPID_set_by_name 4157 1_1_0a EXIST::FUNCTION:OCSP
OCSP_RESPID_set_by_key 4158 1_1_0a EXIST::FUNCTION:OCSP
OCSP_RESPID_match 4159 1_1_0a EXIST::FUNCTION:OCSP
+DSO_pathbyaddr 4170 1_1_0c EXIST::FUNCTION:
+DSO_dsobyaddr 4171 1_1_0c EXIST::FUNCTION:
More information about the openssl-commits
mailing list