[openssl-commits] [openssl] OpenSSL_1_1_0-stable update
Richard Levitte
levitte at openssl.org
Sat Apr 14 12:07:49 UTC 2018
The branch OpenSSL_1_1_0-stable has been updated
via e4fa7cc3fb9909c6aee411de15a06f918687b8e2 (commit)
from ec46830f8a4ce62c0c8ee7677b1eb8e53ee16df1 (commit)
- Log -----------------------------------------------------------------
commit e4fa7cc3fb9909c6aee411de15a06f918687b8e2
Author: Matthias Kraft <matthias.kraft at softwareag.com>
Date: Wed Mar 7 01:48:45 2018 +0100
Custome built dladdr() for AIX.
Implemented a stripped down dladdr()-implementation using AIX' own
loadquery()-function. Following the SGI example in the same code, the
DL_info only has the dli_fname member. As the scope of
dlfcn_pathbyaddr() is the filename, this implementation does not
consider archive members, which can be dlopen()ed in AIX.
Added DATA segment checking to catch ptrgl virtual addresses.
Added test case for DSO_dsobyaddr(), but only for DSO_DLFCN.
Added PIC-flag to aix*-cc build targets.
Signed-off-by: Matthias Kraft <makr at gmx.eu>
Reviewed-by: Andy Polyakov <appro at openssl.org>
Reviewed-by: Rich Salz <rsalz at openssl.org>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5626)
-----------------------------------------------------------------------
Summary of changes:
Configurations/10-main.conf | 2 +
crypto/dso/dso_dlfcn.c | 83 ++++++++++++++++++++++++++++++++++++++--
crypto/init.c | 17 +++++++-
test/recipes/90-test_shlibload.t | 6 ++-
test/shlibloadtest.c | 58 +++++++++++++++++++++++++---
5 files changed, 155 insertions(+), 11 deletions(-)
diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf
index 8559667..7e66705 100644
--- a/Configurations/10-main.conf
+++ b/Configurations/10-main.conf
@@ -1210,6 +1210,7 @@ sub vms_info {
perlasm_scheme => "aix32",
dso_scheme => "dlfcn",
shared_target => "aix-shared",
+ shared_cflag => "-qpic",
shared_ldflag => "-q32 -G",
shared_extension => ".so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
arflags => "-X 32",
@@ -1228,6 +1229,7 @@ sub vms_info {
perlasm_scheme => "aix64",
dso_scheme => "dlfcn",
shared_target => "aix-shared",
+ shared_cflag => "-qpic",
shared_ldflag => "-q64 -G",
shared_extension => ".so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
arflags => "-X 64",
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index a4b0cdd..e01425b 100644
--- a/crypto/dso/dso_dlfcn.c
+++ b/crypto/dso/dso_dlfcn.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-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
@@ -26,7 +26,7 @@
# endif
# include <dlfcn.h>
# define HAVE_DLINFO 1
-# if defined(_AIX) || defined(__CYGWIN__) || \
+# if defined(__CYGWIN__) || \
defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
(defined(__osf__) && !defined(RTLD_NEXT)) || \
(defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
@@ -308,6 +308,76 @@ static int dladdr(void *address, Dl_info *dl)
}
# endif /* __sgi */
+# ifdef _AIX
+/*-
+ * See IBM's AIX Version 7.2, Technical Reference:
+ * Base Operating System and Extensions, Volume 1 and 2
+ * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm
+ */
+# include <sys/ldr.h>
+# include <errno.h>
+/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */
+# define DLFCN_LDINFO_SIZE 86976
+typedef struct Dl_info {
+ const char *dli_fname;
+} Dl_info;
+/*
+ * This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual
+ * address of a function, which is just located in the DATA segment instead of
+ * the TEXT segment.
+ */
+static int dladdr(void *ptr, Dl_info *dl)
+{
+ uintptr_t addr = (uintptr_t)ptr;
+ unsigned int found = 0;
+ struct ld_info *ldinfos, *next_ldi, *this_ldi;
+
+ if ((ldinfos = (struct ld_info *)OPENSSL_malloc(DLFCN_LDINFO_SIZE)) == NULL) {
+ errno = ENOMEM;
+ dl->dli_fname = NULL;
+ return 0;
+ }
+
+ if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) {
+ /*-
+ * Error handling is done through errno and dlerror() reading errno:
+ * ENOMEM (ldinfos buffer is too small),
+ * EINVAL (invalid flags),
+ * EFAULT (invalid ldinfos ptr)
+ */
+ OPENSSL_free((void *)ldinfos);
+ dl->dli_fname = NULL;
+ return 0;
+ }
+ next_ldi = ldinfos;
+
+ do {
+ this_ldi = next_ldi;
+ if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg)
+ && (addr < ((uintptr_t)this_ldi->ldinfo_textorg +
+ this_ldi->ldinfo_textsize)))
+ || ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg)
+ && (addr < ((uintptr_t)this_ldi->ldinfo_dataorg +
+ this_ldi->ldinfo_datasize)))) {
+ found = 1;
+ /*
+ * Ignoring the possibility of a member name and just returning
+ * the path name. See docs: sys/ldr.h, loadquery() and
+ * dlopen()/RTLD_MEMBER.
+ */
+ if ((dl->dli_fname =
+ OPENSSL_strdup(this_ldi->ldinfo_filename)) == NULL)
+ errno = ENOMEM;
+ } else {
+ next_ldi =
+ (struct ld_info *)((uintptr_t)this_ldi + this_ldi->ldinfo_next);
+ }
+ } while (this_ldi->ldinfo_next && !found);
+ OPENSSL_free((void *)ldinfos);
+ return (found && dl->dli_fname != NULL);
+}
+# endif /* _AIX */
+
static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
{
# ifdef HAVE_DLINFO
@@ -326,12 +396,19 @@ static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
if (dladdr(addr, &dli)) {
len = (int)strlen(dli.dli_fname);
- if (sz <= 0)
+ if (sz <= 0) {
+# ifdef _AIX
+ OPENSSL_free((void *)dli.dli_fname);
+# endif
return len + 1;
+ }
if (len >= sz)
len = sz - 1;
memcpy(path, dli.dli_fname, len);
path[len++] = 0;
+# ifdef _AIX
+ OPENSSL_free((void *)dli.dli_fname);
+# endif
return len;
}
diff --git a/crypto/init.c b/crypto/init.c
index 173eac3..1553113 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2017 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
@@ -114,6 +114,15 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base)
ERR_set_mark();
dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
+# ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n",
+ (dso == NULL ? "No!" : "Yes."));
+ /*
+ * In case of No!, it is uncertain our exit()-handlers can still be
+ * called. After dlclose() the whole library might have been unloaded
+ * already.
+ */
+# endif
DSO_free(dso);
ERR_pop_to_mark();
}
@@ -657,6 +666,12 @@ int OPENSSL_atexit(void (*handler)(void))
ERR_set_mark();
dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
+# ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr,
+ "OPENSSL_INIT: OPENSSL_atexit: obtained DSO reference? %s\n",
+ (dso == NULL ? "No!" : "Yes."));
+ /* See same code above in ossl_init_base() for an explanation. */
+# endif
DSO_free(dso);
ERR_pop_to_mark();
}
diff --git a/test/recipes/90-test_shlibload.t b/test/recipes/90-test_shlibload.t
index aa8d98d..04d5265 100644
--- a/test/recipes/90-test_shlibload.t
+++ b/test/recipes/90-test_shlibload.t
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# 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
@@ -20,7 +20,7 @@ use configdata;
plan skip_all => "Test only supported in a shared build" if disabled("shared");
-plan tests => 3;
+plan tests => 4;
my $libcrypto_idx = $unified_info{rename}->{libcrypto} // "libcrypto";
my $libssl_idx = $unified_info{rename}->{libssl} // "libssl";
@@ -35,4 +35,6 @@ ok(run(test(["shlibloadtest", "-ssl_first", $libcrypto, $libssl])),
"running shlibloadtest -ssl_first");
ok(run(test(["shlibloadtest", "-just_crypto", $libcrypto, $libssl])),
"running shlibloadtest -just_crypto");
+ok(run(test(["shlibloadtest", "-dso_ref", $libcrypto, $libssl])),
+ "running shlibloadtest -dso_ref");
diff --git a/test/shlibloadtest.c b/test/shlibloadtest.c
index 25df363..919bf7c 100644
--- a/test/shlibloadtest.c
+++ b/test/shlibloadtest.c
@@ -40,6 +40,16 @@ 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 <dlfcn.h>
typedef void * SHLIB;
@@ -108,11 +118,13 @@ static int shlib_close(SHLIB lib)
# 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)
@@ -123,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;
@@ -138,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;
@@ -145,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");
@@ -161,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)) {
@@ -215,6 +230,38 @@ int main(int argc, char **argv)
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");
More information about the openssl-commits
mailing list