1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /*
6  * Allow freebl and softoken to be loaded without util or NSPR.
7  *
8  * These symbols are overridden once real NSPR, and libutil are attached.
9  */
10 #define _GNU_SOURCE 1
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <fcntl.h>
15 #include <time.h>
16 #include <unistd.h>
17 #include <sys/time.h>
18 #include <dlfcn.h>
19 #include <prio.h>
20 #include <prlink.h>
21 #include <prlog.h>
22 #include <prthread.h>
23 #include <plstr.h>
24 #include <prinit.h>
25 #include <prlock.h>
26 #include <prmem.h>
27 #include <prerror.h>
28 #include <prmon.h>
29 #include <pratom.h>
30 #include <prsystem.h>
31 #include <prinrval.h>
32 #include <prtime.h>
33 #include <prcvar.h>
34 #include <secasn1.h>
35 #include <secdig.h>
36 #include <secport.h>
37 #include <secitem.h>
38 #include <blapi.h>
39 #include <assert.h>
40 #include <private/pprio.h>
41 
42 /* Android API < 21 doesn't define RTLD_NOLOAD */
43 #ifndef RTLD_NOLOAD
44 #define RTLD_NOLOAD 0
45 #endif
46 
47 #define FREEBL_NO_WEAK 1
48 
49 #define WEAK __attribute__((weak))
50 
51 #ifdef FREEBL_NO_WEAK
52 
53 /*
54  * This uses function pointers.
55  *
56  * CONS:  A separate function is needed to
57  * fill in the function pointers.
58  *
59  * PROS: it works on all platforms.
60  *  it allows for dynamically finding nspr and libutil, even once
61  *  softoken is loaded and running. (NOTE: this may be a problem if
62  *  we switch between the stubs and real NSPR on the fly. NSPR will
63  *  do bad things if passed an _FakeArena to free or allocate from).
64  */
65 #define STUB_DECLARE(ret, fn, args) \
66     typedef ret(*type_##fn) args;   \
67     static type_##fn ptr_##fn = NULL
68 
69 #define STUB_SAFE_CALL0(fn) \
70     if (ptr_##fn) {         \
71         return ptr_##fn();  \
72     }
73 #define STUB_SAFE_CALL1(fn, a1) \
74     if (ptr_##fn) {             \
75         return ptr_##fn(a1);    \
76     }
77 #define STUB_SAFE_CALL2(fn, a1, a2) \
78     if (ptr_##fn) {                 \
79         return ptr_##fn(a1, a2);    \
80     }
81 #define STUB_SAFE_CALL3(fn, a1, a2, a3) \
82     if (ptr_##fn) {                     \
83         return ptr_##fn(a1, a2, a3);    \
84     }
85 #define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
86     if (ptr_##fn) {                         \
87         return ptr_##fn(a1, a2, a3, a4);    \
88     }
89 #define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
90     if (ptr_##fn) {                                 \
91         return ptr_##fn(a1, a2, a3, a4, a5, a6);    \
92     }
93 
94 #define STUB_FETCH_FUNCTION(fn)            \
95     ptr_##fn = (type_##fn)dlsym(lib, #fn); \
96     if (ptr_##fn == NULL) {                \
97         return SECFailure;                 \
98     }
99 
100 #else
101 /*
102  * this uses the loader weak attribute. it works automatically, but once
103  * freebl is loaded, the symbols are 'fixed' (later loading of NSPR or
104  * libutil will not resolve these symbols).
105  */
106 
107 #define STUB_DECLARE(ret, fn, args) \
108     WEAK extern ret fn args
109 
110 #define STUB_SAFE_CALL0(fn) \
111     if (fn) {               \
112         return fn();        \
113     }
114 #define STUB_SAFE_CALL1(fn, a1) \
115     if (fn) {                   \
116         return fn(a1);          \
117     }
118 #define STUB_SAFE_CALL2(fn, a1, a2) \
119     if (fn) {                       \
120         return fn(a1, a2);          \
121     }
122 #define STUB_SAFE_CALL3(fn, a1, a2, a3) \
123     if (fn) {                           \
124         return fn(a1, a2, a3);          \
125     }
126 #define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
127     if (fn) {                               \
128         return fn(a1, a2, a3, a4);          \
129     }
130 #define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
131     if (fn) {                                       \
132         return fn(a1, a2, a3, a4, a5, a6);          \
133     }
134 #endif
135 
136 STUB_DECLARE(void *, PORT_Alloc_Util, (size_t len));
137 STUB_DECLARE(void *, PORT_ArenaAlloc_Util, (PLArenaPool * arena, size_t size));
138 STUB_DECLARE(void *, PORT_ArenaZAlloc_Util, (PLArenaPool * arena, size_t size));
139 STUB_DECLARE(void, PORT_Free_Util, (void *ptr));
140 STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero));
141 STUB_DECLARE(int, PORT_GetError_Util, (void));
142 STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
143 STUB_DECLARE(void, PORT_SetError_Util, (int value));
144 STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
145 STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment,
146                                                void **mem));
147 STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes,
148                                                      size_t alignment,
149                                                      size_t offset));
150 STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
151 
152 STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
153 STUB_DECLARE(PRStatus, PR_Access, (const char *name, PRAccessHow how));
154 STUB_DECLARE(PRStatus, PR_CallOnce, (PRCallOnceType * once, PRCallOnceFN func));
155 STUB_DECLARE(PRStatus, PR_Close, (PRFileDesc * fd));
156 STUB_DECLARE(void, PR_DestroyLock, (PRLock * lock));
157 STUB_DECLARE(void, PR_DestroyCondVar, (PRCondVar * cvar));
158 STUB_DECLARE(void, PR_Free, (void *ptr));
159 STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name,
160                                                  PRFuncPtr addr));
161 STUB_DECLARE(PRFileDesc *, PR_ImportPipe, (PROsfd osfd));
162 STUB_DECLARE(void, PR_Lock, (PRLock * lock));
163 STUB_DECLARE(PRCondVar *, PR_NewCondVar, (PRLock * lock));
164 STUB_DECLARE(PRLock *, PR_NewLock, (void));
165 STUB_DECLARE(PRStatus, PR_NotifyCondVar, (PRCondVar * cvar));
166 STUB_DECLARE(PRStatus, PR_NotifyAllCondVar, (PRCondVar * cvar));
167 STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags,
168                                      PRIntn mode));
169 STUB_DECLARE(PRInt32, PR_Read, (PRFileDesc * fd, void *buf, PRInt32 amount));
170 STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset,
171                                    PRSeekWhence whence));
172 STUB_DECLARE(PRStatus, PR_Sleep, (PRIntervalTime ticks));
173 STUB_DECLARE(PRStatus, PR_Unlock, (PRLock * lock));
174 STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar,
175                                         PRIntervalTime timeout));
176 STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
177 
178 STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena,
179                                                  SECItem *item, unsigned int len));
180 STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a,
181                                                        const SECItem *b));
182 STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena,
183                                                 SECItem *to, const SECItem *from));
184 STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
185 STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
186 STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
187 STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
188 STUB_DECLARE(unsigned int, NSS_SecureMemcmpZero, (const void *mem, size_t n));
189 
190 #define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
191 #define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
192 #define PORT_ZNewArray_stub(type, num) \
193     (type *)PORT_ZAlloc_stub(sizeof(type) * (num))
194 #define PORT_ZNewAligned_stub(type, alignment, mem) \
195     (type *)PORT_ZAllocAlignedOffset_stub(sizeof(type), alignment, offsetof(type, mem))
196 
197 /*
198  * NOTE: in order to support hashing only the memory allocation stubs,
199  * the get library name stubs, and the file io stubs are needed (the latter
200  * two are for the library verification). The remaining stubs are simply to
201  * compile. Attempts to use the library for other operations without NSPR
202  * will most likely fail.
203  */
204 
205 /* memory */
206 extern void *
PORT_Alloc_stub(size_t len)207 PORT_Alloc_stub(size_t len)
208 {
209     STUB_SAFE_CALL1(PORT_Alloc_Util, len);
210     return malloc(len);
211 }
212 
213 extern void
PORT_Free_stub(void * ptr)214 PORT_Free_stub(void *ptr)
215 {
216     STUB_SAFE_CALL1(PORT_Free_Util, ptr);
217     return free(ptr);
218 }
219 
220 extern void *
PORT_ZAlloc_stub(size_t len)221 PORT_ZAlloc_stub(size_t len)
222 {
223     STUB_SAFE_CALL1(PORT_ZAlloc_Util, len);
224     void *ptr = malloc(len);
225     if (ptr) {
226         memset(ptr, 0, len);
227     }
228     return ptr;
229 }
230 
231 /* aligned_alloc is C11. This is an alternative to get aligned memory. */
232 extern void *
PORT_ZAllocAligned_stub(size_t bytes,size_t alignment,void ** mem)233 PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem)
234 {
235     STUB_SAFE_CALL3(PORT_ZAllocAligned_Util, bytes, alignment, mem);
236 
237     /* This only works if alignement is a power of 2. */
238     if ((alignment == 0) || (alignment & (alignment - 1))) {
239         return NULL;
240     }
241 
242     size_t x = alignment - 1;
243     size_t len = (bytes ? bytes : 1) + x;
244 
245     if (!mem) {
246         return NULL;
247     }
248 
249     /* Always allocate a non-zero amount of bytes */
250     *mem = malloc(len);
251     if (!*mem) {
252         return NULL;
253     }
254 
255     memset(*mem, 0, len);
256 
257     /* We're pretty sure this is non-zero, but let's assure scan-build too. */
258     void *ret = (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
259     assert(ret);
260 
261     return ret;
262 }
263 
264 extern void *
PORT_ZAllocAlignedOffset_stub(size_t size,size_t alignment,size_t offset)265 PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
266 {
267     STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
268     if (offset > size) {
269         return NULL;
270     }
271 
272     void *mem = NULL;
273     void *v = PORT_ZAllocAligned_stub(size, alignment, &mem);
274     if (!v) {
275         return NULL;
276     }
277 
278     *((void **)((uintptr_t)v + offset)) = mem;
279     return v;
280 }
281 
282 extern void
PORT_ZFree_stub(void * ptr,size_t len)283 PORT_ZFree_stub(void *ptr, size_t len)
284 {
285     STUB_SAFE_CALL2(PORT_ZFree_Util, ptr, len);
286     memset(ptr, 0, len);
287     return free(ptr);
288 }
289 
290 extern void
PR_Free_stub(void * ptr)291 PR_Free_stub(void *ptr)
292 {
293     STUB_SAFE_CALL1(PR_Free, ptr);
294     return free(ptr);
295 }
296 
297 /*
298  * arenas
299  *
300  */
301 extern PLArenaPool *
PORT_NewArena_stub(unsigned long chunksize)302 PORT_NewArena_stub(unsigned long chunksize)
303 {
304     STUB_SAFE_CALL1(PORT_NewArena_Util, chunksize);
305     abort();
306     return NULL;
307 }
308 
309 extern void *
PORT_ArenaAlloc_stub(PLArenaPool * arena,size_t size)310 PORT_ArenaAlloc_stub(PLArenaPool *arena, size_t size)
311 {
312 
313     STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
314     abort();
315     return NULL;
316 }
317 
318 extern void *
PORT_ArenaZAlloc_stub(PLArenaPool * arena,size_t size)319 PORT_ArenaZAlloc_stub(PLArenaPool *arena, size_t size)
320 {
321 
322     STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
323     abort();
324     return NULL;
325 }
326 
327 extern void
PORT_FreeArena_stub(PLArenaPool * arena,PRBool zero)328 PORT_FreeArena_stub(PLArenaPool *arena, PRBool zero)
329 {
330 
331     STUB_SAFE_CALL2(PORT_FreeArena_Util, arena, zero);
332     abort();
333 }
334 
335 /* io */
336 extern PRFileDesc *
PR_Open_stub(const char * name,PRIntn flags,PRIntn mode)337 PR_Open_stub(const char *name, PRIntn flags, PRIntn mode)
338 {
339     int *lfd = NULL;
340     int fd;
341     int lflags = 0;
342 
343     STUB_SAFE_CALL3(PR_Open, name, flags, mode);
344 
345     if (flags & PR_RDWR) {
346         lflags = O_RDWR;
347     } else if (flags & PR_WRONLY) {
348         lflags = O_WRONLY;
349     } else {
350         lflags = O_RDONLY;
351     }
352 
353     if (flags & PR_EXCL)
354         lflags |= O_EXCL;
355     if (flags & PR_APPEND)
356         lflags |= O_APPEND;
357     if (flags & PR_TRUNCATE)
358         lflags |= O_TRUNC;
359 
360     fd = open(name, lflags, mode);
361     if (fd >= 0) {
362         lfd = PORT_New_stub(int);
363         if (lfd != NULL) {
364             *lfd = fd;
365         } else {
366             close(fd);
367         }
368     }
369     return (PRFileDesc *)lfd;
370 }
371 
372 extern PRFileDesc *
PR_ImportPipe_stub(PROsfd fd)373 PR_ImportPipe_stub(PROsfd fd)
374 {
375     int *lfd = NULL;
376 
377     STUB_SAFE_CALL1(PR_ImportPipe, fd);
378 
379     lfd = PORT_New_stub(int);
380     if (lfd != NULL) {
381         *lfd = fd;
382     }
383     return (PRFileDesc *)lfd;
384 }
385 
386 extern PRStatus
PR_Close_stub(PRFileDesc * fd)387 PR_Close_stub(PRFileDesc *fd)
388 {
389     int *lfd;
390     STUB_SAFE_CALL1(PR_Close, fd);
391 
392     lfd = (int *)fd;
393     close(*lfd);
394     PORT_Free_stub(lfd);
395 
396     return PR_SUCCESS;
397 }
398 
399 extern PRInt32
PR_Read_stub(PRFileDesc * fd,void * buf,PRInt32 amount)400 PR_Read_stub(PRFileDesc *fd, void *buf, PRInt32 amount)
401 {
402     int *lfd;
403     STUB_SAFE_CALL3(PR_Read, fd, buf, amount);
404 
405     lfd = (int *)fd;
406     return read(*lfd, buf, amount);
407 }
408 
409 extern PROffset32
PR_Seek_stub(PRFileDesc * fd,PROffset32 offset,PRSeekWhence whence)410 PR_Seek_stub(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
411 {
412     int *lfd;
413     int lwhence = SEEK_SET;
414     STUB_SAFE_CALL3(PR_Seek, fd, offset, whence);
415     lfd = (int *)fd;
416     switch (whence) {
417         case PR_SEEK_CUR:
418             lwhence = SEEK_CUR;
419             break;
420         case PR_SEEK_END:
421             lwhence = SEEK_END;
422             break;
423         case PR_SEEK_SET:
424             break;
425     }
426 
427     return lseek(*lfd, offset, lwhence);
428 }
429 
430 PRStatus
PR_Access_stub(const char * name,PRAccessHow how)431 PR_Access_stub(const char *name, PRAccessHow how)
432 {
433     int mode = F_OK;
434     int rv;
435     STUB_SAFE_CALL2(PR_Access, name, how);
436     switch (how) {
437         case PR_ACCESS_WRITE_OK:
438             mode = W_OK;
439             break;
440         case PR_ACCESS_READ_OK:
441             mode = R_OK;
442             break;
443         /* assume F_OK for all others */
444         default:
445             break;
446     }
447     rv = access(name, mode);
448     if (rv == 0) {
449         return PR_SUCCESS;
450     }
451     return PR_FAILURE;
452 }
453 
454 /*
455  * library
456  */
457 extern char *
PR_GetLibraryFilePathname_stub(const char * name,PRFuncPtr addr)458 PR_GetLibraryFilePathname_stub(const char *name, PRFuncPtr addr)
459 {
460     Dl_info dli;
461     char *result;
462 
463     STUB_SAFE_CALL2(PR_GetLibraryFilePathname, name, addr);
464 
465     if (dladdr((void *)addr, &dli) == 0) {
466         return NULL;
467     }
468     result = PORT_Alloc_stub(strlen(dli.dli_fname) + 1);
469     if (result != NULL) {
470         strcpy(result, dli.dli_fname);
471     }
472     return result;
473 }
474 
475 #include <errno.h>
476 
477 /* errors */
478 extern int
PORT_GetError_stub(void)479 PORT_GetError_stub(void)
480 {
481     STUB_SAFE_CALL0(PORT_GetError_Util);
482     return errno;
483 }
484 
485 extern void
PORT_SetError_stub(int value)486 PORT_SetError_stub(int value)
487 {
488     STUB_SAFE_CALL1(PORT_SetError_Util, value);
489     errno = value;
490 }
491 
492 /* misc */
493 extern void
PR_Assert_stub(const char * s,const char * file,PRIntn ln)494 PR_Assert_stub(const char *s, const char *file, PRIntn ln)
495 {
496     STUB_SAFE_CALL3(PR_Assert, s, file, ln);
497     fprintf(stderr, "%s line %d: %s\n", file, ln, s);
498     abort();
499 }
500 
501 /* time */
502 extern PRStatus
PR_Sleep_stub(PRIntervalTime ticks)503 PR_Sleep_stub(PRIntervalTime ticks)
504 {
505     STUB_SAFE_CALL1(PR_Sleep, ticks);
506     usleep(ticks * 1000);
507     return PR_SUCCESS;
508 }
509 
510 /* locking */
511 extern PRLock *
PR_NewLock_stub(void)512 PR_NewLock_stub(void)
513 {
514     STUB_SAFE_CALL0(PR_NewLock);
515     abort();
516     return NULL;
517 }
518 
519 extern PRStatus
PR_Unlock_stub(PRLock * lock)520 PR_Unlock_stub(PRLock *lock)
521 {
522     STUB_SAFE_CALL1(PR_Unlock, lock);
523     abort();
524     return PR_FAILURE;
525 }
526 
527 extern void
PR_Lock_stub(PRLock * lock)528 PR_Lock_stub(PRLock *lock)
529 {
530     STUB_SAFE_CALL1(PR_Lock, lock);
531     abort();
532     return;
533 }
534 
535 extern void
PR_DestroyLock_stub(PRLock * lock)536 PR_DestroyLock_stub(PRLock *lock)
537 {
538     STUB_SAFE_CALL1(PR_DestroyLock, lock);
539     abort();
540     return;
541 }
542 
543 extern PRCondVar *
PR_NewCondVar_stub(PRLock * lock)544 PR_NewCondVar_stub(PRLock *lock)
545 {
546     STUB_SAFE_CALL1(PR_NewCondVar, lock);
547     abort();
548     return NULL;
549 }
550 
551 extern PRStatus
PR_NotifyCondVar_stub(PRCondVar * cvar)552 PR_NotifyCondVar_stub(PRCondVar *cvar)
553 {
554     STUB_SAFE_CALL1(PR_NotifyCondVar, cvar);
555     abort();
556     return PR_FAILURE;
557 }
558 
559 extern PRStatus
PR_NotifyAllCondVar_stub(PRCondVar * cvar)560 PR_NotifyAllCondVar_stub(PRCondVar *cvar)
561 {
562     STUB_SAFE_CALL1(PR_NotifyAllCondVar, cvar);
563     abort();
564     return PR_FAILURE;
565 }
566 
567 extern PRStatus
PR_WaitCondVar_stub(PRCondVar * cvar,PRIntervalTime timeout)568 PR_WaitCondVar_stub(PRCondVar *cvar, PRIntervalTime timeout)
569 {
570     STUB_SAFE_CALL2(PR_WaitCondVar, cvar, timeout);
571     abort();
572     return PR_FAILURE;
573 }
574 
575 extern char *
PR_GetEnvSecure_stub(const char * var)576 PR_GetEnvSecure_stub(const char *var)
577 {
578     STUB_SAFE_CALL1(PR_GetEnvSecure, var);
579     abort();
580     return NULL;
581 }
582 
583 extern void
PR_DestroyCondVar_stub(PRCondVar * cvar)584 PR_DestroyCondVar_stub(PRCondVar *cvar)
585 {
586     STUB_SAFE_CALL1(PR_DestroyCondVar, cvar);
587     abort();
588     return;
589 }
590 
591 /*
592  * NOTE: this presupposes GCC 4.1
593  */
594 extern PRStatus
PR_CallOnce_stub(PRCallOnceType * once,PRCallOnceFN func)595 PR_CallOnce_stub(PRCallOnceType *once, PRCallOnceFN func)
596 {
597     STUB_SAFE_CALL2(PR_CallOnce, once, func);
598     abort();
599     return PR_FAILURE;
600 }
601 
602 /*
603  * SECITEMS implement Item Utilities
604  */
605 extern void
SECITEM_FreeItem_stub(SECItem * zap,PRBool freeit)606 SECITEM_FreeItem_stub(SECItem *zap, PRBool freeit)
607 {
608     STUB_SAFE_CALL2(SECITEM_FreeItem_Util, zap, freeit);
609     abort();
610 }
611 
612 extern SECItem *
SECITEM_AllocItem_stub(PLArenaPool * arena,SECItem * item,unsigned int len)613 SECITEM_AllocItem_stub(PLArenaPool *arena, SECItem *item, unsigned int len)
614 {
615     STUB_SAFE_CALL3(SECITEM_AllocItem_Util, arena, item, len);
616     abort();
617     return NULL;
618 }
619 
620 extern SECComparison
SECITEM_CompareItem_stub(const SECItem * a,const SECItem * b)621 SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
622 {
623     STUB_SAFE_CALL2(SECITEM_CompareItem_Util, a, b);
624     abort();
625     return SECEqual;
626 }
627 
628 extern SECStatus
SECITEM_CopyItem_stub(PLArenaPool * arena,SECItem * to,const SECItem * from)629 SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
630 {
631     STUB_SAFE_CALL3(SECITEM_CopyItem_Util, arena, to, from);
632     abort();
633     return SECFailure;
634 }
635 
636 extern SECOidTag
SECOID_FindOIDTag_stub(const SECItem * oid)637 SECOID_FindOIDTag_stub(const SECItem *oid)
638 {
639     STUB_SAFE_CALL1(SECOID_FindOIDTag_Util, oid);
640     abort();
641     return SEC_OID_UNKNOWN;
642 }
643 
644 extern void
SECITEM_ZfreeItem_stub(SECItem * zap,PRBool freeit)645 SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
646 {
647     STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
648     abort();
649 }
650 
651 extern int
NSS_SecureMemcmp_stub(const void * a,const void * b,size_t n)652 NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
653 {
654     STUB_SAFE_CALL3(NSS_SecureMemcmp, a, b, n);
655     abort();
656 }
657 
658 extern unsigned int
NSS_SecureMemcmpZero_stub(const void * mem,size_t n)659 NSS_SecureMemcmpZero_stub(const void *mem, size_t n)
660 {
661     STUB_SAFE_CALL2(NSS_SecureMemcmpZero, mem, n);
662     abort();
663 }
664 
665 #ifdef FREEBL_NO_WEAK
666 
667 static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
668 static const char *nssutilLibName = SHLIB_PREFIX "nssutil3." SHLIB_SUFFIX;
669 
670 static SECStatus
freebl_InitNSPR(void * lib)671 freebl_InitNSPR(void *lib)
672 {
673     STUB_FETCH_FUNCTION(PR_Free);
674     STUB_FETCH_FUNCTION(PR_Open);
675     STUB_FETCH_FUNCTION(PR_ImportPipe);
676     STUB_FETCH_FUNCTION(PR_Close);
677     STUB_FETCH_FUNCTION(PR_Read);
678     STUB_FETCH_FUNCTION(PR_Seek);
679     STUB_FETCH_FUNCTION(PR_GetLibraryFilePathname);
680     STUB_FETCH_FUNCTION(PR_Assert);
681     STUB_FETCH_FUNCTION(PR_Access);
682     STUB_FETCH_FUNCTION(PR_Sleep);
683     STUB_FETCH_FUNCTION(PR_CallOnce);
684     STUB_FETCH_FUNCTION(PR_NewCondVar);
685     STUB_FETCH_FUNCTION(PR_NotifyCondVar);
686     STUB_FETCH_FUNCTION(PR_NotifyAllCondVar);
687     STUB_FETCH_FUNCTION(PR_WaitCondVar);
688     STUB_FETCH_FUNCTION(PR_DestroyCondVar);
689     STUB_FETCH_FUNCTION(PR_NewLock);
690     STUB_FETCH_FUNCTION(PR_Unlock);
691     STUB_FETCH_FUNCTION(PR_Lock);
692     STUB_FETCH_FUNCTION(PR_DestroyLock);
693     STUB_FETCH_FUNCTION(PR_GetEnvSecure);
694     return SECSuccess;
695 }
696 
697 static SECStatus
freebl_InitNSSUtil(void * lib)698 freebl_InitNSSUtil(void *lib)
699 {
700     STUB_FETCH_FUNCTION(PORT_Alloc_Util);
701     STUB_FETCH_FUNCTION(PORT_Free_Util);
702     STUB_FETCH_FUNCTION(PORT_ZAlloc_Util);
703     STUB_FETCH_FUNCTION(PORT_ZFree_Util);
704     STUB_FETCH_FUNCTION(PORT_NewArena_Util);
705     STUB_FETCH_FUNCTION(PORT_ArenaAlloc_Util);
706     STUB_FETCH_FUNCTION(PORT_ArenaZAlloc_Util);
707     STUB_FETCH_FUNCTION(PORT_FreeArena_Util);
708     STUB_FETCH_FUNCTION(PORT_GetError_Util);
709     STUB_FETCH_FUNCTION(PORT_SetError_Util);
710     STUB_FETCH_FUNCTION(SECITEM_FreeItem_Util);
711     STUB_FETCH_FUNCTION(SECITEM_AllocItem_Util);
712     STUB_FETCH_FUNCTION(SECITEM_CompareItem_Util);
713     STUB_FETCH_FUNCTION(SECITEM_CopyItem_Util);
714     STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
715     STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
716     STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
717     STUB_FETCH_FUNCTION(NSS_SecureMemcmpZero);
718     return SECSuccess;
719 }
720 
721 /*
722  * fetch the library if it's loaded. For NSS it should already be loaded
723  */
724 #define freebl_getLibrary(libName) \
725     dlopen(libName, RTLD_LAZY | RTLD_NOLOAD)
726 
727 #define freebl_releaseLibrary(lib) \
728     if (lib)                       \
729     dlclose(lib)
730 
731 static void *FREEBLnsprGlobalLib = NULL;
732 static void *FREEBLnssutilGlobalLib = NULL;
733 
FREEBL_unload()734 void __attribute((destructor)) FREEBL_unload()
735 {
736     freebl_releaseLibrary(FREEBLnsprGlobalLib);
737     freebl_releaseLibrary(FREEBLnssutilGlobalLib);
738 }
739 #endif
740 
741 /*
742  * load the symbols from the real libraries if available.
743  *
744  * if force is set, explicitly load the libraries if they are not already
745  * loaded. If we could not use the real libraries, return failure.
746  */
747 extern SECStatus
FREEBL_InitStubs()748 FREEBL_InitStubs()
749 {
750     SECStatus rv = SECSuccess;
751 #ifdef FREEBL_NO_WEAK
752     void *nspr = NULL;
753     void *nssutil = NULL;
754 
755     /* NSPR should be first */
756     if (!FREEBLnsprGlobalLib) {
757         nspr = freebl_getLibrary(nsprLibName);
758         if (!nspr) {
759             return SECFailure;
760         }
761         rv = freebl_InitNSPR(nspr);
762         if (rv != SECSuccess) {
763             freebl_releaseLibrary(nspr);
764             return rv;
765         }
766         FREEBLnsprGlobalLib = nspr; /* adopt */
767     }
768     /* now load NSSUTIL */
769     if (!FREEBLnssutilGlobalLib) {
770         nssutil = freebl_getLibrary(nssutilLibName);
771         if (!nssutil) {
772             return SECFailure;
773         }
774         rv = freebl_InitNSSUtil(nssutil);
775         if (rv != SECSuccess) {
776             freebl_releaseLibrary(nssutil);
777             return rv;
778         }
779         FREEBLnssutilGlobalLib = nssutil; /* adopt */
780     }
781 #endif
782 
783     return rv;
784 }
785