If a library containing a function which calls DH_new() followed by a
DH_free() is dlopen()ed, the function called and then dlclosed() memory
is leaked. The bug was found on Solaris and the following report uses
some Solaris specific tools (for memory leak searching, for example).
The following inline code example should demonstrate the issue:
$ cat test.c
#include <dlfcn.h>
#include <link.h>
#include <stdlib.h>
int main() {
void (*run)();
void *handle;
handle = dlopen("./run.so", RTLD_NOW);
run = (void (*)()) dlsym(handle, "run");
(*run)();
dlclose(handle);
abort();
}
$ cat run.c
#include <openssl/dh.h>
int run() {
DH *test;
test = DH_new();
DH_free(test);
}
$ cc run.c -shared -R/usr/sfw/lib -I/usr/sfw -lcrypto -o run.so
$ cc test.c -o test
$ echo $LD_PRELOAD $UMEM_DEBUG
libumem.so.1 default
$ ./test
zsh: IOT instruction (core dumped) ./test
$ echo ::findleaks | mdb ./core
CACHE LEAKED BUFCTL CALLER
08067c10 1 08082998 main+0x31
08067c10 1 08082a10 main+0x31
08067e10 1 08086048 main+0x31
0806a810 1 0807ea70 main+0x31
0806ac10 1 0807bea0 main+0x31
08067c10 1 08082920 main+0x31
------------------------------------------------------------------------
Total 6 buffers, 296 bytes
Playing a bit with mdb (and using a slightly different version of the
above inline example) here are the various stacks associated with the
allocations:
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`sk_new+0x40
libcrypto.so.0.9.8`sk_new_null+0x1d
libcrypto.so.0.9.8`def_get_class+0xb8
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`lh_insert+0x80
libcrypto.so.0.9.8`def_get_class+0xcf
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
_start+0x80
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`sk_new+0x24
libcrypto.so.0.9.8`sk_new_null+0x1d
libcrypto.so.0.9.8`def_get_class+0xb8
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`def_get_class+0x9c
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
_start+0x80
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`lh_new+0x4a
libcrypto.so.0.9.8`ex_data_check+0x4d
libcrypto.so.0.9.8`def_get_class+0x29
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
libumem.so.1`umem_cache_alloc_debug+0x144
libumem.so.1`umem_cache_alloc+0x19a
libumem.so.1`umem_alloc+0xcd
libumem.so.1`malloc+0x2a
libcrypto.so.0.9.8`default_malloc_ex+0x21
libcrypto.so.0.9.8`CRYPTO_malloc+0x5d
libcrypto.so.0.9.8`lh_new+0x28
libcrypto.so.0.9.8`ex_data_check+0x4d
libcrypto.so.0.9.8`def_get_class+0x29
libcrypto.so.0.9.8`int_new_ex_data+0x20
libcrypto.so.0.9.8`CRYPTO_new_ex_data+0x38
libcrypto.so.0.9.8`DH_new_method+0xcc
libcrypto.so.0.9.8`DH_new+0x1d
openssl_test.so`run+0x2c
main+0x7d
In order to actually find the symbols corresponding to the addresses in
the stack we must ran the program twice:
1) Get the stack of the leaks (::bufctl_audit)
2) Run the program in mdb putting a breakpoint on the dlclose call in
main. Because the library is mapped (always?) in the same place the
symbols for the addresses can be found by using ::dis on each address,
thus rebuilding the stack.
--
Jan Pechanec
http://blogs.sun.com/janp
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]