summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/dso/dso_dlfcn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/dso/dso_dlfcn.c')
-rw-r--r--src/lib/libcrypto/dso/dso_dlfcn.c320
1 files changed, 152 insertions, 168 deletions
diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c
index 648ddb5ac0..245b9b1478 100644
--- a/src/lib/libcrypto/dso/dso_dlfcn.c
+++ b/src/lib/libcrypto/dso/dso_dlfcn.c
@@ -10,7 +10,7 @@
10 * are met: 10 * are met:
11 * 11 *
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 14 *
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in 16 * notice, this list of conditions and the following disclaimer in
@@ -61,10 +61,11 @@
61#include <openssl/dso.h> 61#include <openssl/dso.h>
62 62
63#ifndef DSO_DLFCN 63#ifndef DSO_DLFCN
64DSO_METHOD *DSO_METHOD_dlfcn(void) 64DSO_METHOD *
65 { 65DSO_METHOD_dlfcn(void)
66{
66 return NULL; 67 return NULL;
67 } 68}
68#else 69#else
69 70
70#ifdef HAVE_DLFCN_H 71#ifdef HAVE_DLFCN_H
@@ -87,8 +88,8 @@ static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg);
87#endif 88#endif
88static char *dlfcn_name_converter(DSO *dso, const char *filename); 89static char *dlfcn_name_converter(DSO *dso, const char *filename);
89static char *dlfcn_merger(DSO *dso, const char *filespec1, 90static char *dlfcn_merger(DSO *dso, const char *filespec1,
90 const char *filespec2); 91 const char *filespec2);
91static int dlfcn_pathbyaddr(void *addr,char *path,int sz); 92static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
92static void *dlfcn_globallookup(const char *name); 93static void *dlfcn_globallookup(const char *name);
93 94
94static DSO_METHOD dso_meth_dlfcn = { 95static DSO_METHOD dso_meth_dlfcn = {
@@ -109,286 +110,269 @@ static DSO_METHOD dso_meth_dlfcn = {
109 NULL, /* finish */ 110 NULL, /* finish */
110 dlfcn_pathbyaddr, 111 dlfcn_pathbyaddr,
111 dlfcn_globallookup 112 dlfcn_globallookup
112 }; 113};
113 114
114DSO_METHOD *DSO_METHOD_dlfcn(void) 115DSO_METHOD *
115 { 116DSO_METHOD_dlfcn(void)
116 return(&dso_meth_dlfcn); 117{
117 } 118 return (&dso_meth_dlfcn);
119}
118 120
119/* For this DSO_METHOD, our meth_data STACK will contain; 121/* For this DSO_METHOD, our meth_data STACK will contain;
120 * (i) the handle (void*) returned from dlopen(). 122 * (i) the handle (void*) returned from dlopen().
121 */ 123 */
122 124
123static int dlfcn_load(DSO *dso) 125static int
124 { 126dlfcn_load(DSO *dso)
127{
125 void *ptr = NULL; 128 void *ptr = NULL;
126 /* See applicable comments in dso_dl.c */ 129 /* See applicable comments in dso_dl.c */
127 char *filename = DSO_convert_filename(dso, NULL); 130 char *filename = DSO_convert_filename(dso, NULL);
128 int flags = RTLD_LAZY; 131 int flags = RTLD_LAZY;
129 132
130 if(filename == NULL) 133 if (filename == NULL) {
131 { 134 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
132 DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME);
133 goto err; 135 goto err;
134 } 136 }
135 137
136 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS) 138 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
137 flags |= RTLD_GLOBAL; 139 flags |= RTLD_GLOBAL;
138 ptr = dlopen(filename, flags); 140 ptr = dlopen(filename, flags);
139 if(ptr == NULL) 141 if (ptr == NULL) {
140 { 142 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
141 DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED);
142 ERR_add_error_data(4, "filename(", filename, "): ", dlerror()); 143 ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
143 goto err; 144 goto err;
144 } 145 }
145 if(!sk_void_push(dso->meth_data, (char *)ptr)) 146 if (!sk_void_push(dso->meth_data, (char *)ptr)) {
146 { 147 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
147 DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR);
148 goto err; 148 goto err;
149 } 149 }
150 /* Success */ 150 /* Success */
151 dso->loaded_filename = filename; 151 dso->loaded_filename = filename;
152 return(1); 152 return (1);
153
153err: 154err:
154 /* Cleanup! */ 155 /* Cleanup! */
155 if(filename != NULL) 156 if (filename != NULL)
156 free(filename); 157 free(filename);
157 if(ptr != NULL) 158 if (ptr != NULL)
158 dlclose(ptr); 159 dlclose(ptr);
159 return(0); 160 return (0);
160} 161}
161 162
162static int dlfcn_unload(DSO *dso) 163static int
163 { 164dlfcn_unload(DSO *dso)
165{
164 void *ptr; 166 void *ptr;
165 if(dso == NULL) 167 if (dso == NULL) {
166 { 168 DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
167 DSOerr(DSO_F_DLFCN_UNLOAD,ERR_R_PASSED_NULL_PARAMETER); 169 return (0);
168 return(0); 170 }
169 } 171 if (sk_void_num(dso->meth_data) < 1)
170 if(sk_void_num(dso->meth_data) < 1) 172 return (1);
171 return(1);
172 ptr = sk_void_pop(dso->meth_data); 173 ptr = sk_void_pop(dso->meth_data);
173 if(ptr == NULL) 174 if (ptr == NULL) {
174 { 175 DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
175 DSOerr(DSO_F_DLFCN_UNLOAD,DSO_R_NULL_HANDLE);
176 /* Should push the value back onto the stack in 176 /* Should push the value back onto the stack in
177 * case of a retry. */ 177 * case of a retry. */
178 sk_void_push(dso->meth_data, ptr); 178 sk_void_push(dso->meth_data, ptr);
179 return(0); 179 return (0);
180 } 180 }
181 /* For now I'm not aware of any errors associated with dlclose() */ 181 /* For now I'm not aware of any errors associated with dlclose() */
182 dlclose(ptr); 182 dlclose(ptr);
183 return(1); 183 return (1);
184 } 184}
185 185
186static void *dlfcn_bind_var(DSO *dso, const char *symname) 186static void *
187 { 187dlfcn_bind_var(DSO *dso, const char *symname)
188{
188 void *ptr, *sym; 189 void *ptr, *sym;
189 190
190 if((dso == NULL) || (symname == NULL)) 191 if ((dso == NULL) || (symname == NULL)) {
191 { 192 DSOerr(DSO_F_DLFCN_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
192 DSOerr(DSO_F_DLFCN_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER); 193 return (NULL);
193 return(NULL); 194 }
194 } 195 if (sk_void_num(dso->meth_data) < 1) {
195 if(sk_void_num(dso->meth_data) < 1) 196 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_STACK_ERROR);
196 { 197 return (NULL);
197 DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_STACK_ERROR); 198 }
198 return(NULL);
199 }
200 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); 199 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
201 if(ptr == NULL) 200 if (ptr == NULL) {
202 { 201 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_NULL_HANDLE);
203 DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_NULL_HANDLE); 202 return (NULL);
204 return(NULL); 203 }
205 }
206 sym = dlsym(ptr, symname); 204 sym = dlsym(ptr, symname);
207 if(sym == NULL) 205 if (sym == NULL) {
208 { 206 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_SYM_FAILURE);
209 DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE);
210 ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); 207 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
211 return(NULL); 208 return (NULL);
212 }
213 return(sym);
214 } 209 }
210 return (sym);
211}
215 212
216static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) 213static DSO_FUNC_TYPE
217 { 214dlfcn_bind_func(DSO *dso, const char *symname)
215{
218 void *ptr; 216 void *ptr;
219 union { 217 union {
220 DSO_FUNC_TYPE sym; 218 DSO_FUNC_TYPE sym;
221 void *dlret; 219 void *dlret;
222 } u; 220 } u;
223 221
224 if((dso == NULL) || (symname == NULL)) 222 if ((dso == NULL) || (symname == NULL)) {
225 { 223 DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
226 DSOerr(DSO_F_DLFCN_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER); 224 return (NULL);
227 return(NULL); 225 }
228 } 226 if (sk_void_num(dso->meth_data) < 1) {
229 if(sk_void_num(dso->meth_data) < 1) 227 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
230 { 228 return (NULL);
231 DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_STACK_ERROR); 229 }
232 return(NULL);
233 }
234 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); 230 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
235 if(ptr == NULL) 231 if (ptr == NULL) {
236 { 232 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
237 DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_NULL_HANDLE); 233 return (NULL);
238 return(NULL); 234 }
239 }
240 u.dlret = dlsym(ptr, symname); 235 u.dlret = dlsym(ptr, symname);
241 if(u.dlret == NULL) 236 if (u.dlret == NULL) {
242 { 237 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
243 DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE);
244 ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); 238 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
245 return(NULL); 239 return (NULL);
246 }
247 return u.sym;
248 } 240 }
241 return u.sym;
242}
249 243
250static char *dlfcn_merger(DSO *dso, const char *filespec1, 244static char *
251 const char *filespec2) 245dlfcn_merger(DSO *dso, const char *filespec1, const char *filespec2)
252 { 246{
253 char *merged; 247 char *merged;
254 size_t len; 248 size_t len;
255 249
256 if(!filespec1 && !filespec2) 250 if (!filespec1 && !filespec2) {
257 {
258 DSOerr(DSO_F_DLFCN_MERGER, 251 DSOerr(DSO_F_DLFCN_MERGER,
259 ERR_R_PASSED_NULL_PARAMETER); 252 ERR_R_PASSED_NULL_PARAMETER);
260 return(NULL); 253 return (NULL);
261 } 254 }
262 /* If the first file specification is a rooted path, it rules. 255 /* If the first file specification is a rooted path, it rules.
263 same goes if the second file specification is missing. */ 256 same goes if the second file specification is missing. */
264 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) 257 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
265 {
266 len = strlen(filespec1) + 1; 258 len = strlen(filespec1) + 1;
267 merged = malloc(len); 259 merged = malloc(len);
268 if(!merged) 260 if (!merged) {
269 {
270 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE); 261 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
271 return(NULL); 262 return (NULL);
272 }
273 strlcpy(merged, filespec1, len);
274 } 263 }
264 strlcpy(merged, filespec1, len);
265 }
275 /* If the first file specification is missing, the second one rules. */ 266 /* If the first file specification is missing, the second one rules. */
276 else if (!filespec1) 267 else if (!filespec1) {
277 {
278 len = strlen(filespec2) + 1; 268 len = strlen(filespec2) + 1;
279 merged = malloc(strlen(filespec2) + 1); 269 merged = malloc(strlen(filespec2) + 1);
280 if(!merged) 270 if (!merged) {
281 { 271 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
282 DSOerr(DSO_F_DLFCN_MERGER, 272 return (NULL);
283 ERR_R_MALLOC_FAILURE);
284 return(NULL);
285 }
286 strlcpy(merged, filespec2, len);
287 } 273 }
288 else 274 strlcpy(merged, filespec2, len);
275 } else
289 /* This part isn't as trivial as it looks. It assumes that 276 /* This part isn't as trivial as it looks. It assumes that
290 the second file specification really is a directory, and 277 the second file specification really is a directory, and
291 makes no checks whatsoever. Therefore, the result becomes 278 makes no checks whatsoever. Therefore, the result becomes
292 the concatenation of filespec2 followed by a slash followed 279 the concatenation of filespec2 followed by a slash followed
293 by filespec1. */ 280 by filespec1. */
294 { 281 {
295 int spec2len, len; 282 int spec2len, len;
296 283
297 spec2len = strlen(filespec2); 284 spec2len = strlen(filespec2);
298 len = spec2len + (filespec1 ? strlen(filespec1) : 0); 285 len = spec2len + (filespec1 ? strlen(filespec1) : 0);
299 286
300 if(filespec2 && filespec2[spec2len - 1] == '/') 287 if (filespec2 && filespec2[spec2len - 1] == '/') {
301 {
302 spec2len--; 288 spec2len--;
303 len--; 289 len--;
304 } 290 }
305 merged = malloc(len + 2); 291 merged = malloc(len + 2);
306 if(!merged) 292 if (!merged) {
307 { 293 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
308 DSOerr(DSO_F_DLFCN_MERGER, 294 return (NULL);
309 ERR_R_MALLOC_FAILURE); 295 }
310 return(NULL);
311 }
312 strlcpy(merged, filespec2, len + 2); 296 strlcpy(merged, filespec2, len + 2);
313 merged[spec2len] = '/'; 297 merged[spec2len] = '/';
314 strlcpy(&merged[spec2len + 1], filespec1, len + 1 - spec2len); 298 strlcpy(&merged[spec2len + 1], filespec1, len + 1 - spec2len);
315 }
316 return(merged);
317 } 299 }
300 return (merged);
301}
318 302
319#define DSO_ext ".so" 303#define DSO_ext ".so"
320#define DSO_extlen 3 304#define DSO_extlen 3
321 305
322static char *dlfcn_name_converter(DSO *dso, const char *filename) 306static char *
323 { 307dlfcn_name_converter(DSO *dso, const char *filename)
308{
324 char *translated; 309 char *translated;
325 int len, rsize, transform; 310 int len, rsize, transform;
326 311
327 len = strlen(filename); 312 len = strlen(filename);
328 rsize = len + 1; 313 rsize = len + 1;
329 transform = (strstr(filename, "/") == NULL); 314 transform = (strstr(filename, "/") == NULL);
330 if(transform) 315 if (transform) {
331 {
332 /* We will convert this to "%s.so" or "lib%s.so" etc */ 316 /* We will convert this to "%s.so" or "lib%s.so" etc */
333 rsize += DSO_extlen; /* The length of ".so" */ 317 rsize += DSO_extlen; /* The length of ".so" */
334 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) 318 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
335 rsize += 3; /* The length of "lib" */ 319 rsize += 3; /* The length of "lib" */
336 } 320 }
337 translated = malloc(rsize); 321 translated = malloc(rsize);
338 if(translated == NULL) 322 if (translated == NULL) {
339 {
340 DSOerr(DSO_F_DLFCN_NAME_CONVERTER, 323 DSOerr(DSO_F_DLFCN_NAME_CONVERTER,
341 DSO_R_NAME_TRANSLATION_FAILED); 324 DSO_R_NAME_TRANSLATION_FAILED);
342 return(NULL); 325 return (NULL);
343 } 326 }
344 if(transform) 327 if (transform) {
345 {
346 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) 328 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
347 snprintf(translated, rsize, "lib%s" DSO_ext, filename); 329 snprintf(translated, rsize, "lib%s" DSO_ext, filename);
348 else 330 else
349 snprintf(translated, rsize, "%s" DSO_ext, filename); 331 snprintf(translated, rsize, "%s" DSO_ext, filename);
350 } 332 } else
351 else
352 snprintf(translated, rsize, "%s", filename); 333 snprintf(translated, rsize, "%s", filename);
353 return(translated); 334 return (translated);
354 } 335}
355 336
356static int dlfcn_pathbyaddr(void *addr,char *path,int sz) 337static int
357 { 338dlfcn_pathbyaddr(void *addr, char *path, int sz)
339{
358 Dl_info dli; 340 Dl_info dli;
359 int len; 341 int len;
360 342
361 if (addr == NULL) 343 if (addr == NULL) {
362 { 344 union{
363 union { int(*f)(void*,char*,int); void *p; } t = 345 int(*f)(void*, char*, int);
364 { dlfcn_pathbyaddr }; 346 void *p;
347 } t = { dlfcn_pathbyaddr };
365 addr = t.p; 348 addr = t.p;
366 } 349 }
367 350
368 if (dladdr(addr,&dli)) 351 if (dladdr(addr, &dli)) {
369 {
370 len = (int)strlen(dli.dli_fname); 352 len = (int)strlen(dli.dli_fname);
371 if (sz <= 0) return len+1; 353 if (sz <= 0)
372 if (len >= sz) len=sz-1; 354 return len + 1;
373 memcpy(path,dli.dli_fname,len); 355 if (len >= sz)
374 path[len++]=0; 356 len = sz - 1;
357 memcpy(path, dli.dli_fname, len);
358 path[len++] = 0;
375 return len; 359 return len;
376 } 360 }
377 361
378 ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror()); 362 ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror());
379 return -1; 363 return -1;
380 } 364}
381 365
382static void *dlfcn_globallookup(const char *name) 366static void *
383 { 367dlfcn_globallookup(const char *name)
384 void *ret = NULL,*handle = dlopen(NULL,RTLD_LAZY); 368{
385 369 void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
386 if (handle) 370
387 { 371 if (handle) {
388 ret = dlsym(handle,name); 372 ret = dlsym(handle, name);
389 dlclose(handle); 373 dlclose(handle);
390 } 374 }
391 375
392 return ret; 376 return ret;
393 } 377}
394#endif /* DSO_DLFCN */ 378#endif /* DSO_DLFCN */