From 93558bf5190226494d3b549397fbf94214846d0d Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Sat, 15 Oct 2016 15:23:03 +0100 Subject: [PATCH] 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 (cherry picked from commit cb6ea61c161e88aa0268c77f308469a67b2ec063) --- crypto/dso/dso_dl.c | 34 ++++++++++++++++++++++++++++++++++ crypto/dso/dso_dlfcn.c | 34 ++++++++++++++++++++++++++++++++++ crypto/dso/dso_err.c | 2 ++ crypto/dso/dso_lib.c | 12 ++++++++++++ crypto/dso/dso_locl.h | 2 ++ crypto/dso/dso_vms.c | 4 +++- crypto/dso/dso_win32.c | 1 + include/internal/dso.h | 13 +++++++++++++ util/libcrypto.num | 1 + 9 files changed, 102 insertions(+), 1 deletion(-) diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index bc29fb23e0..d80bf562c7 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 624052b86a..a4b0cdd95b 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 a180580759..07588d5c39 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 bea8776d71..2dac20082c 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -304,6 +304,18 @@ 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); +} + 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 19767871fa..fbfad0544a 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 90d387eb53..b9a98ddd11 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 4ac6e7176d..4a4c34abb6 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/include/internal/dso.h b/include/internal/dso.h index 970beeb195..f513cad3b7 100644 --- a/include/internal/dso.h +++ b/include/internal/dso.h @@ -136,6 +136,17 @@ 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); + /* * 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 @@ -177,6 +188,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 +201,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/util/libcrypto.num b/util/libcrypto.num index db6732edbc..2e439e8b11 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4206,3 +4206,4 @@ 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: -- 2.25.1