OpenCoverage

dso_dlfcn.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/openssl/src/crypto/dso/dso_dlfcn.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/*-
2 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.-
3 *-
4 * Licensed under the OpenSSL license (the "License"). You may not use-
5 * this file except in compliance with the License. You can obtain a copy-
6 * in the file LICENSE in the source distribution or at-
7 * https://www.openssl.org/source/license.html-
8 */-
9-
10/*-
11 * We need to do this early, because stdio.h includes the header files that-
12 * handle _GNU_SOURCE and other similar macros. Defining it later is simply-
13 * too late, because those headers are protected from re- inclusion.-
14 */-
15#ifndef _GNU_SOURCE-
16# define _GNU_SOURCE /* make sure dladdr is declared */-
17#endif-
18-
19#include "dso_locl.h"-
20-
21#ifdef DSO_DLFCN-
22-
23# ifdef HAVE_DLFCN_H-
24# ifdef __osf__-
25# define __EXTENSIONS__-
26# endif-
27# include <dlfcn.h>-
28# define HAVE_DLINFO 1-
29# if defined(__CYGWIN__) || \-
30 defined(__SCO_VERSION__) || defined(_SCO_ELF) || \-
31 (defined(__osf__) && !defined(RTLD_NEXT)) || \-
32 (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \-
33 defined(__ANDROID__)-
34# undef HAVE_DLINFO-
35# endif-
36# endif-
37-
38/* Part of the hack in "dlfcn_load" ... */-
39# define DSO_MAX_TRANSLATED_SIZE 256-
40-
41static int dlfcn_load(DSO *dso);-
42static int dlfcn_unload(DSO *dso);-
43static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);-
44static char *dlfcn_name_converter(DSO *dso, const char *filename);-
45static char *dlfcn_merger(DSO *dso, const char *filespec1,-
46 const char *filespec2);-
47static int dlfcn_pathbyaddr(void *addr, char *path, int sz);-
48static void *dlfcn_globallookup(const char *name);-
49-
50static DSO_METHOD dso_meth_dlfcn = {-
51 "OpenSSL 'dlfcn' shared library method",-
52 dlfcn_load,-
53 dlfcn_unload,-
54 dlfcn_bind_func,-
55 NULL, /* ctrl */-
56 dlfcn_name_converter,-
57 dlfcn_merger,-
58 NULL, /* init */-
59 NULL, /* finish */-
60 dlfcn_pathbyaddr,-
61 dlfcn_globallookup-
62};-
63-
64DSO_METHOD *DSO_METHOD_openssl(void)-
65{-
66 return &dso_meth_dlfcn;
executed 368 times by 1 test: return &dso_meth_dlfcn;
Executed by:
  • libcrypto.so.1.1
368
67}-
68-
69/*-
70 * Prior to using the dlopen() function, we should decide on the flag we-
71 * send. There's a few different ways of doing this and it's a messy-
72 * venn-diagram to match up which platforms support what. So as we don't have-
73 * autoconf yet, I'm implementing a hack that could be hacked further-
74 * relatively easily to deal with cases as we find them. Initially this is to-
75 * cope with OpenBSD.-
76 */-
77# if defined(__OpenBSD__) || defined(__NetBSD__)-
78# ifdef DL_LAZY-
79# define DLOPEN_FLAG DL_LAZY-
80# else-
81# ifdef RTLD_NOW-
82# define DLOPEN_FLAG RTLD_NOW-
83# else-
84# define DLOPEN_FLAG 0-
85# endif-
86# endif-
87# else-
88# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */-
89# endif-
90-
91/*-
92 * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle-
93 * (void*) returned from dlopen().-
94 */-
95-
96static int dlfcn_load(DSO *dso)-
97{-
98 void *ptr = NULL;-
99 /* See applicable comments in dso_dl.c */-
100 char *filename = DSO_convert_filename(dso, NULL);-
101 int flags = DLOPEN_FLAG;-
102-
103 if (filename == NULL) {
filename == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
104 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);-
105 goto err;
never executed: goto err;
0
106 }-
107# ifdef RTLD_GLOBAL-
108 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
dso->flags & 0x20Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
109 flags |= RTLD_GLOBAL;
never executed: flags |= 0x00100 ;
0
110# endif-
111# ifdef _AIX-
112 if (filename[strlen(filename) - 1] == ')')-
113 flags |= RTLD_MEMBER;-
114# endif-
115 ptr = dlopen(filename, flags);-
116 if (ptr == NULL) {
ptr == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
117 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);-
118 ERR_add_error_data(4, "filename(", filename, "): ", dlerror());-
119 goto err;
never executed: goto err;
0
120 }-
121 if (!sk_void_push(dso->meth_data, (char *)ptr)) {
!sk_void_push(..., (char *)ptr)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
122 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);-
123 goto err;
never executed: goto err;
0
124 }-
125 /* Success */-
126 dso->loaded_filename = filename;-
127 return 1;
executed 368 times by 1 test: return 1;
Executed by:
  • libcrypto.so.1.1
368
128 err:-
129 /* Cleanup! */-
130 OPENSSL_free(filename);-
131 if (ptr != NULL)
ptr != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
132 dlclose(ptr);
never executed: dlclose(ptr);
0
133 return 0;
never executed: return 0;
0
134}-
135-
136static int dlfcn_unload(DSO *dso)-
137{-
138 void *ptr;-
139 if (dso == NULL) {
dso == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
140 DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);-
141 return 0;
never executed: return 0;
0
142 }-
143 if (sk_void_num(dso->meth_data) < 1)
sk_void_num(ds...meth_data) < 1Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
144 return 1;
never executed: return 1;
0
145 ptr = sk_void_pop(dso->meth_data);-
146 if (ptr == NULL) {
ptr == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
147 DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);-
148 /*-
149 * Should push the value back onto the stack in case of a retry.-
150 */-
151 sk_void_push(dso->meth_data, ptr);-
152 return 0;
never executed: return 0;
0
153 }-
154 /* For now I'm not aware of any errors associated with dlclose() */-
155 dlclose(ptr);-
156 return 1;
executed 368 times by 1 test: return 1;
Executed by:
  • libcrypto.so.1.1
368
157}-
158-
159static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)-
160{-
161 void *ptr;-
162 union {-
163 DSO_FUNC_TYPE sym;-
164 void *dlret;-
165 } u;-
166-
167 if ((dso == NULL) || (symname == NULL)) {
(dso == ((void *)0) )Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
(symname == ((void *)0) )Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-736
168 DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);-
169 return NULL;
never executed: return ((void *)0) ;
0
170 }-
171 if (sk_void_num(dso->meth_data) < 1) {
sk_void_num(ds...meth_data) < 1Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-736
172 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);-
173 return NULL;
never executed: return ((void *)0) ;
0
174 }-
175 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);-
176 if (ptr == NULL) {
ptr == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-736
177 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);-
178 return NULL;
never executed: return ((void *)0) ;
0
179 }-
180 u.dlret = dlsym(ptr, symname);-
181 if (u.dlret == NULL) {
u.dlret == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-736
182 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);-
183 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());-
184 return NULL;
never executed: return ((void *)0) ;
0
185 }-
186 return u.sym;
executed 736 times by 1 test: return u.sym;
Executed by:
  • libcrypto.so.1.1
736
187}-
188-
189static char *dlfcn_merger(DSO *dso, const char *filespec1,-
190 const char *filespec2)-
191{-
192 char *merged;-
193-
194 if (!filespec1 && !filespec2) {
!filespec1Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
!filespec2Description
TRUEnever evaluated
FALSEnever evaluated
0-368
195 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);-
196 return NULL;
never executed: return ((void *)0) ;
0
197 }-
198 /*-
199 * If the first file specification is a rooted path, it rules. same goes-
200 * if the second file specification is missing.-
201 */-
202 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
!filespec2Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
filespec1 != ((void *)0)Description
TRUEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
FALSEnever evaluated
filespec1[0] == '/'Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
203 merged = OPENSSL_strdup(filespec1);-
204 if (merged == NULL) {
merged == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
205 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);-
206 return NULL;
never executed: return ((void *)0) ;
0
207 }-
208 }
never executed: end of block
0
209 /*-
210 * If the first file specification is missing, the second one rules.-
211 */-
212 else if (!filespec1) {
!filespec1Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
213 merged = OPENSSL_strdup(filespec2);-
214 if (merged == NULL) {
merged == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
215 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);-
216 return NULL;
never executed: return ((void *)0) ;
0
217 }-
218 } else {
never executed: end of block
0
219 /*-
220 * This part isn't as trivial as it looks. It assumes that the-
221 * second file specification really is a directory, and makes no-
222 * checks whatsoever. Therefore, the result becomes the-
223 * concatenation of filespec2 followed by a slash followed by-
224 * filespec1.-
225 */-
226 int spec2len, len;-
227-
228 spec2len = strlen(filespec2);-
229 len = spec2len + strlen(filespec1);-
230-
231 if (spec2len && filespec2[spec2len - 1] == '/') {
spec2lenDescription
TRUEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
FALSEnever evaluated
filespec2[spec2len - 1] == '/'Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
232 spec2len--;-
233 len--;-
234 }
never executed: end of block
0
235 merged = OPENSSL_malloc(len + 2);-
236 if (merged == NULL) {
merged == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
237 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);-
238 return NULL;
never executed: return ((void *)0) ;
0
239 }-
240 strcpy(merged, filespec2);-
241 merged[spec2len] = '/';-
242 strcpy(&merged[spec2len + 1], filespec1);-
243 }
executed 368 times by 1 test: end of block
Executed by:
  • libcrypto.so.1.1
368
244 return merged;
executed 368 times by 1 test: return merged;
Executed by:
  • libcrypto.so.1.1
368
245}-
246-
247static char *dlfcn_name_converter(DSO *dso, const char *filename)-
248{-
249 char *translated;-
250 int len, rsize, transform;-
251-
252 len = strlen(filename);-
253 rsize = len + 1;-
254 transform = (strstr(filename, "/") == NULL);-
255 if (transform) {
transformDescription
TRUEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
368
256 /* We will convert this to "%s.so" or "lib%s.so" etc */-
257 rsize += strlen(DSO_EXTENSION); /* The length of ".so" */-
258 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
(DSO_flags(dso) & 0x02) == 0Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
259 rsize += 3; /* The length of "lib" */
never executed: rsize += 3;
0
260 }
executed 368 times by 1 test: end of block
Executed by:
  • libcrypto.so.1.1
368
261 translated = OPENSSL_malloc(rsize);-
262 if (translated == NULL) {
translated == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 736 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-736
263 DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);-
264 return NULL;
never executed: return ((void *)0) ;
0
265 }-
266 if (transform) {
transformDescription
TRUEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
368
267 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
(DSO_flags(dso) & 0x02) == 0Description
TRUEnever evaluated
FALSEevaluated 368 times by 1 test
Evaluated by:
  • libcrypto.so.1.1
0-368
268 sprintf(translated, "lib%s" DSO_EXTENSION, filename);
never executed: sprintf(translated, "lib%s" ".so", filename);
0
269 else-
270 sprintf(translated, "%s" DSO_EXTENSION, filename);
executed 368 times by 1 test: sprintf(translated, "%s" ".so", filename);
Executed by:
  • libcrypto.so.1.1
368
271 } else-
272 sprintf(translated, "%s", filename);
executed 368 times by 1 test: sprintf(translated, "%s", filename);
Executed by:
  • libcrypto.so.1.1
368
273 return translated;
executed 736 times by 1 test: return translated;
Executed by:
  • libcrypto.so.1.1
736
274}-
275-
276# ifdef __sgi-
277/*--
278This is a quote from IRIX manual for dladdr(3c):-
279-
280 <dlfcn.h> does not contain a prototype for dladdr or definition of-
281 Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,-
282 but contains no dladdr prototype and no IRIX library contains an-
283 implementation. Write your own declaration based on the code below.-
284-
285 The following code is dependent on internal interfaces that are not-
286 part of the IRIX compatibility guarantee; however, there is no future-
287 intention to change this interface, so on a practical level, the code-
288 below is safe to use on IRIX.-
289*/-
290# include <rld_interface.h>-
291# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR-
292# define _RLD_INTERFACE_DLFCN_H_DLADDR-
293typedef struct Dl_info {-
294 const char *dli_fname;-
295 void *dli_fbase;-
296 const char *dli_sname;-
297 void *dli_saddr;-
298 int dli_version;-
299 int dli_reserved1;-
300 long dli_reserved[4];-
301} Dl_info;-
302# else-
303typedef struct Dl_info Dl_info;-
304# endif-
305# define _RLD_DLADDR 14-
306-
307static int dladdr(void *address, Dl_info *dl)-
308{-
309 void *v;-
310 v = _rld_new_interface(_RLD_DLADDR, address, dl);-
311 return (int)v;-
312}-
313# endif /* __sgi */-
314-
315# ifdef _AIX-
316/*--
317 * See IBM's AIX Version 7.2, Technical Reference:-
318 * Base Operating System and Extensions, Volume 1 and 2-
319 * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm-
320 */-
321# include <sys/ldr.h>-
322# include <errno.h>-
323/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */-
324# define DLFCN_LDINFO_SIZE 86976-
325typedef struct Dl_info {-
326 const char *dli_fname;-
327} Dl_info;-
328/*-
329 * This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual-
330 * address of a function, which is just located in the DATA segment instead of-
331 * the TEXT segment.-
332 */-
333static int dladdr(void *ptr, Dl_info *dl)-
334{-
335 uintptr_t addr = (uintptr_t)ptr;-
336 unsigned int found = 0;-
337 struct ld_info *ldinfos, *next_ldi, *this_ldi;-
338-
339 if ((ldinfos = OPENSSL_malloc(DLFCN_LDINFO_SIZE)) == NULL) {-
340 errno = ENOMEM;-
341 dl->dli_fname = NULL;-
342 return 0;-
343 }-
344-
345 if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) {-
346 /*--
347 * Error handling is done through errno and dlerror() reading errno:-
348 * ENOMEM (ldinfos buffer is too small),-
349 * EINVAL (invalid flags),-
350 * EFAULT (invalid ldinfos ptr)-
351 */-
352 OPENSSL_free((void *)ldinfos);-
353 dl->dli_fname = NULL;-
354 return 0;-
355 }-
356 next_ldi = ldinfos;-
357-
358 do {-
359 this_ldi = next_ldi;-
360 if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg)-
361 && (addr < ((uintptr_t)this_ldi->ldinfo_textorg +-
362 this_ldi->ldinfo_textsize)))-
363 || ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg)-
364 && (addr < ((uintptr_t)this_ldi->ldinfo_dataorg +-
365 this_ldi->ldinfo_datasize)))) {-
366 char *buffer, *member;-
367 size_t buffer_sz, member_len;-
368-
369 buffer_sz = strlen(this_ldi->ldinfo_filename) + 1;-
370 member = this_ldi->ldinfo_filename + buffer_sz;-
371 if ((member_len = strlen(member)) > 0)-
372 buffer_sz += 1 + member_len + 1;-
373 found = 1;-
374 if ((buffer = OPENSSL_malloc(buffer_sz)) != NULL) {-
375 OPENSSL_strlcpy(buffer, this_ldi->ldinfo_filename, buffer_sz);-
376 if (member_len > 0) {-
377 /*-
378 * Need to respect a possible member name and not just-
379 * returning the path name in this case. See docs:-
380 * sys/ldr.h, loadquery() and dlopen()/RTLD_MEMBER.-
381 */-
382 OPENSSL_strlcat(buffer, "(", buffer_sz);-
383 OPENSSL_strlcat(buffer, member, buffer_sz);-
384 OPENSSL_strlcat(buffer, ")", buffer_sz);-
385 }-
386 dl->dli_fname = buffer;-
387 } else {-
388 errno = ENOMEM;-
389 }-
390 } else {-
391 next_ldi = (struct ld_info *)((uintptr_t)this_ldi +-
392 this_ldi->ldinfo_next);-
393 }-
394 } while (this_ldi->ldinfo_next && !found);-
395 OPENSSL_free((void *)ldinfos);-
396 return (found && dl->dli_fname != NULL);-
397}-
398# endif /* _AIX */-
399-
400static int dlfcn_pathbyaddr(void *addr, char *path, int sz)-
401{-
402# ifdef HAVE_DLINFO-
403 Dl_info dli;-
404 int len;-
405-
406 if (addr == NULL) {
addr == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
407 union {-
408 int (*f) (void *, char *, int);-
409 void *p;-
410 } t = {-
411 dlfcn_pathbyaddr-
412 };-
413 addr = t.p;-
414 }
never executed: end of block
0
415-
416 if (dladdr(addr, &dli)) {
dladdr(addr, &dli)Description
TRUEnever evaluated
FALSEnever evaluated
0
417 len = (int)strlen(dli.dli_fname);-
418 if (sz <= 0) {
sz <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
419# ifdef _AIX-
420 OPENSSL_free((void *)dli.dli_fname);-
421# endif-
422 return len + 1;
never executed: return len + 1;
0
423 }-
424 if (len >= sz)
len >= szDescription
TRUEnever evaluated
FALSEnever evaluated
0
425 len = sz - 1;
never executed: len = sz - 1;
0
426 memcpy(path, dli.dli_fname, len);-
427 path[len++] = 0;-
428# ifdef _AIX-
429 OPENSSL_free((void *)dli.dli_fname);-
430# endif-
431 return len;
never executed: return len;
0
432 }-
433-
434 ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());-
435# endif-
436 return -1;
never executed: return -1;
0
437}-
438-
439static void *dlfcn_globallookup(const char *name)-
440{-
441 void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);-
442-
443 if (handle) {
handleDescription
TRUEnever evaluated
FALSEnever evaluated
0
444 ret = dlsym(handle, name);-
445 dlclose(handle);-
446 }
never executed: end of block
0
447-
448 return ret;
never executed: return ret;
0
449}-
450#endif /* DSO_DLFCN */-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2