diff options
Diffstat (limited to 'src/lib/libcrypto/dso/dso_dlfcn.c')
-rw-r--r-- | src/lib/libcrypto/dso/dso_dlfcn.c | 114 |
1 files changed, 79 insertions, 35 deletions
diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c index d48b4202f2..f734c1c6b7 100644 --- a/src/lib/libcrypto/dso/dso_dlfcn.c +++ b/src/lib/libcrypto/dso/dso_dlfcn.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* dso_dlfcn.c */ | 1 | /* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */ |
2 | /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL | 2 | /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL |
3 | * project 2000. | 3 | * project 2000. |
4 | */ | 4 | */ |
@@ -56,10 +56,6 @@ | |||
56 | * | 56 | * |
57 | */ | 57 | */ |
58 | 58 | ||
59 | #ifdef __linux | ||
60 | #define _GNU_SOURCE | ||
61 | #endif | ||
62 | |||
63 | #include <stdio.h> | 59 | #include <stdio.h> |
64 | #include "cryptlib.h" | 60 | #include "cryptlib.h" |
65 | #include <openssl/dso.h> | 61 | #include <openssl/dso.h> |
@@ -89,6 +85,8 @@ static int dlfcn_finish(DSO *dso); | |||
89 | static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); | 85 | static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); |
90 | #endif | 86 | #endif |
91 | static char *dlfcn_name_converter(DSO *dso, const char *filename); | 87 | static char *dlfcn_name_converter(DSO *dso, const char *filename); |
88 | static char *dlfcn_merger(DSO *dso, const char *filespec1, | ||
89 | const char *filespec2); | ||
92 | 90 | ||
93 | static DSO_METHOD dso_meth_dlfcn = { | 91 | static DSO_METHOD dso_meth_dlfcn = { |
94 | "OpenSSL 'dlfcn' shared library method", | 92 | "OpenSSL 'dlfcn' shared library method", |
@@ -103,6 +101,7 @@ static DSO_METHOD dso_meth_dlfcn = { | |||
103 | #endif | 101 | #endif |
104 | NULL, /* ctrl */ | 102 | NULL, /* ctrl */ |
105 | dlfcn_name_converter, | 103 | dlfcn_name_converter, |
104 | dlfcn_merger, | ||
106 | NULL, /* init */ | 105 | NULL, /* init */ |
107 | NULL /* finish */ | 106 | NULL /* finish */ |
108 | }; | 107 | }; |
@@ -145,13 +144,19 @@ static int dlfcn_load(DSO *dso) | |||
145 | void *ptr = NULL; | 144 | void *ptr = NULL; |
146 | /* See applicable comments in dso_dl.c */ | 145 | /* See applicable comments in dso_dl.c */ |
147 | char *filename = DSO_convert_filename(dso, NULL); | 146 | char *filename = DSO_convert_filename(dso, NULL); |
147 | int flags = DLOPEN_FLAG; | ||
148 | 148 | ||
149 | if(filename == NULL) | 149 | if(filename == NULL) |
150 | { | 150 | { |
151 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME); | 151 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME); |
152 | goto err; | 152 | goto err; |
153 | } | 153 | } |
154 | ptr = dlopen(filename, DLOPEN_FLAG); | 154 | |
155 | #ifdef RTLD_GLOBAL | ||
156 | if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS) | ||
157 | flags |= RTLD_GLOBAL; | ||
158 | #endif | ||
159 | ptr = dlopen(filename, flags); | ||
155 | if(ptr == NULL) | 160 | if(ptr == NULL) |
156 | { | 161 | { |
157 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); | 162 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); |
@@ -250,7 +255,7 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) | |||
250 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_NULL_HANDLE); | 255 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_NULL_HANDLE); |
251 | return(NULL); | 256 | return(NULL); |
252 | } | 257 | } |
253 | *(void**)(tsym) = dlsym(ptr, symname); | 258 | *(void **)(tsym) = dlsym(ptr, symname); |
254 | if(sym == NULL) | 259 | if(sym == NULL) |
255 | { | 260 | { |
256 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); | 261 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); |
@@ -260,6 +265,73 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) | |||
260 | return(sym); | 265 | return(sym); |
261 | } | 266 | } |
262 | 267 | ||
268 | static char *dlfcn_merger(DSO *dso, const char *filespec1, | ||
269 | const char *filespec2) | ||
270 | { | ||
271 | char *merged; | ||
272 | |||
273 | if(!filespec1 && !filespec2) | ||
274 | { | ||
275 | DSOerr(DSO_F_DLFCN_MERGER, | ||
276 | ERR_R_PASSED_NULL_PARAMETER); | ||
277 | return(NULL); | ||
278 | } | ||
279 | /* If the first file specification is a rooted path, it rules. | ||
280 | same goes if the second file specification is missing. */ | ||
281 | if (!filespec2 || filespec1[0] == '/') | ||
282 | { | ||
283 | merged = OPENSSL_malloc(strlen(filespec1) + 1); | ||
284 | if(!merged) | ||
285 | { | ||
286 | DSOerr(DSO_F_DLFCN_MERGER, | ||
287 | ERR_R_MALLOC_FAILURE); | ||
288 | return(NULL); | ||
289 | } | ||
290 | strcpy(merged, filespec1); | ||
291 | } | ||
292 | /* If the first file specification is missing, the second one rules. */ | ||
293 | else if (!filespec1) | ||
294 | { | ||
295 | merged = OPENSSL_malloc(strlen(filespec2) + 1); | ||
296 | if(!merged) | ||
297 | { | ||
298 | DSOerr(DSO_F_DLFCN_MERGER, | ||
299 | ERR_R_MALLOC_FAILURE); | ||
300 | return(NULL); | ||
301 | } | ||
302 | strcpy(merged, filespec2); | ||
303 | } | ||
304 | else | ||
305 | /* This part isn't as trivial as it looks. It assumes that | ||
306 | the second file specification really is a directory, and | ||
307 | makes no checks whatsoever. Therefore, the result becomes | ||
308 | the concatenation of filespec2 followed by a slash followed | ||
309 | by filespec1. */ | ||
310 | { | ||
311 | int spec2len, len; | ||
312 | |||
313 | spec2len = (filespec2 ? strlen(filespec2) : 0); | ||
314 | len = spec2len + (filespec1 ? strlen(filespec1) : 0); | ||
315 | |||
316 | if(filespec2 && filespec2[spec2len - 1] == '/') | ||
317 | { | ||
318 | spec2len--; | ||
319 | len--; | ||
320 | } | ||
321 | merged = OPENSSL_malloc(len + 2); | ||
322 | if(!merged) | ||
323 | { | ||
324 | DSOerr(DSO_F_DLFCN_MERGER, | ||
325 | ERR_R_MALLOC_FAILURE); | ||
326 | return(NULL); | ||
327 | } | ||
328 | strcpy(merged, filespec2); | ||
329 | merged[spec2len] = '/'; | ||
330 | strcpy(&merged[spec2len + 1], filespec1); | ||
331 | } | ||
332 | return(merged); | ||
333 | } | ||
334 | |||
263 | static char *dlfcn_name_converter(DSO *dso, const char *filename) | 335 | static char *dlfcn_name_converter(DSO *dso, const char *filename) |
264 | { | 336 | { |
265 | char *translated; | 337 | char *translated; |
@@ -294,32 +366,4 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename) | |||
294 | return(translated); | 366 | return(translated); |
295 | } | 367 | } |
296 | 368 | ||
297 | #ifdef OPENSSL_FIPS | ||
298 | static void dlfcn_ref_point(){} | ||
299 | |||
300 | int DSO_pathbyaddr(void *addr,char *path,int sz) | ||
301 | { | ||
302 | Dl_info dli; | ||
303 | int len; | ||
304 | |||
305 | if (addr == NULL) | ||
306 | { | ||
307 | union { void(*f)(void); void *p; } t = { dlfcn_ref_point }; | ||
308 | addr = t.p; | ||
309 | } | ||
310 | |||
311 | if (dladdr(addr,&dli)) | ||
312 | { | ||
313 | len = (int)strlen(dli.dli_fname); | ||
314 | if (sz <= 0) return len+1; | ||
315 | if (len >= sz) len=sz-1; | ||
316 | memcpy(path,dli.dli_fname,len); | ||
317 | path[len++]=0; | ||
318 | return len; | ||
319 | } | ||
320 | |||
321 | ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror()); | ||
322 | return -1; | ||
323 | } | ||
324 | #endif | ||
325 | #endif /* DSO_DLFCN */ | 369 | #endif /* DSO_DLFCN */ |