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]

Reply via email to