diff -ru openssl-0.9.8h/crypto/cryptlib.c openssl-0.9.8h-patched/crypto/cryptlib.c --- openssl-0.9.8h/crypto/cryptlib.c 2007-09-06 12:43:46.000000000 +0000 +++ openssl-0.9.8h-patched/crypto/cryptlib.c 2008-09-11 18:21:33.000000000 +0000 @@ -166,7 +166,8 @@ "ec_pre_comp", "store", "comp", -#if CRYPTO_NUM_LOCKS != 39 + "names_lh", +#if CRYPTO_NUM_LOCKS != 40 # error "Inconsistency between crypto.h and cryptlib.c" #endif }; diff -ru openssl-0.9.8h/crypto/crypto.h openssl-0.9.8h-patched/crypto/crypto.h --- openssl-0.9.8h/crypto/crypto.h 2005-05-08 19:54:33.000000000 +0000 +++ openssl-0.9.8h-patched/crypto/crypto.h 2008-09-11 18:20:59.000000000 +0000 @@ -219,7 +219,8 @@ #define CRYPTO_LOCK_EC_PRE_COMP 36 #define CRYPTO_LOCK_STORE 37 #define CRYPTO_LOCK_COMP 38 -#define CRYPTO_NUM_LOCKS 39 +#define CRYPTO_LOCK_NAMES_LH 39 +#define CRYPTO_NUM_LOCKS 40 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff -ru openssl-0.9.8h/crypto/objects/o_names.c openssl-0.9.8h-patched/crypto/objects/o_names.c --- openssl-0.9.8h/crypto/objects/o_names.c 2005-04-05 10:29:42.000000000 +0000 +++ openssl-0.9.8h-patched/crypto/objects/o_names.c 2008-09-11 18:35:12.000000000 +0000 @@ -48,11 +48,19 @@ int OBJ_NAME_init(void) { - if (names_lh != NULL) return(1); + int ret; + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); + if (names_lh != NULL) + { + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); + return(1); + } MemCheck_off(); names_lh=lh_new(obj_name_hash, obj_name_cmp); MemCheck_on(); - return(names_lh != NULL); + ret = (names_lh != NULL); + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); + return(ret); } int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), @@ -164,7 +172,9 @@ for (;;) { + CRYPTO_r_lock(CRYPTO_LOCK_NAMES_LH); ret=(OBJ_NAME *)lh_retrieve(names_lh,&on); + CRYPTO_r_unlock(CRYPTO_LOCK_NAMES_LH); if (ret == NULL) return(NULL); if ((ret->alias) && !alias) { @@ -200,7 +210,9 @@ onp->type=type; onp->data=data; + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); ret=(OBJ_NAME *)lh_insert(names_lh,onp); + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); if (ret != NULL) { /* free things */ @@ -217,7 +229,11 @@ } else { - if (lh_error(names_lh)) + int names_lh_error; + CRYPTO_r_lock(CRYPTO_LOCK_NAMES_LH); + names_lh_error = lh_error(names_lh); + CRYPTO_r_unlock(CRYPTO_LOCK_NAMES_LH); + if (names_lh_error) { /* ERROR */ return(0); @@ -235,7 +251,9 @@ type&= ~OBJ_NAME_ALIAS; on.name=name; on.type=type; + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); ret=(OBJ_NAME *)lh_delete(names_lh,&on); + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); if (ret != NULL) { /* free things */ @@ -278,7 +296,9 @@ d.fn=fn; d.arg=arg; + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d); + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); } struct doall_sorted @@ -313,7 +333,9 @@ int n; d.type=type; + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names); + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); d.n=0; OBJ_NAME_do_all(type,do_all_sorted_fn,&d); @@ -352,6 +374,9 @@ if (names_lh == NULL) return; free_type=type; + + CRYPTO_w_lock(CRYPTO_LOCK_NAMES_LH); + down_load=names_lh->down_load; names_lh->down_load=0; @@ -365,5 +390,6 @@ } else names_lh->down_load=down_load; - } + CRYPTO_w_unlock(CRYPTO_LOCK_NAMES_LH); + }
OpenSSL version: openssl-0.9.8h To reproduce more than one thread must call SSL_library_init or other functions that modify names_lh at approximiately the same time. The stack traces will look something like: #0 0x0097aa52 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2 #1 0x001503ae in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67 #2 0x001518f8 in *__GI_abort () at ../sysdeps/generic/abort.c:88 #3 0x0017ecf9 in __libc_message (do_abort=2, fmt=0x220da0 "*** glibc detected *** %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:145 #4 0x00183e1a in malloc_printerr (action=2, str=0x220e0c "double free or corruption (fasttop)", ptr=0xb7401fb8) at malloc.c:5525 #5 0x001857d5 in _int_realloc (av=0xb7400010, oldmem=0xb7401fb8, bytes=0) at malloc.c:4668 #6 0x00186684 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3487 #7 0x00186c9c in realloc_hook_ini (ptr=0xb7401fb8, sz=128, caller=0x81cced6) at hooks.c:54 #8 0x001865d1 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3425 #9 0x081cced6 in default_realloc_ex (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:86 #10 0x081cd4ff in CRYPTO_realloc (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:331 #11 0x081e851a in expand (lh=0xb7401f50) at lhash.c:341 #12 0x081e81a0 in lh_insert (lh=0xb7401f50, data=0xb7402280) at lhash.c:187 #13 0x081cfbd8 in OBJ_NAME_add (name=0x828ef27 "ssl2-md5", type=1, data=0x828ef23 "MD5") at o_names.c:203 #14 0x081cc5a4 in SSL_library_init () at ssl_algs.c:100 See attached patch file for fix. This doesn't appear to be an exploitable security vulnerability as far as I can tell. This bug appears to have existed as far back as 1999 based on looking at http://cvs.openssl.org/rlog?f=openssl/crypto/objects/o_names.c
OpenSSL version: openssl-0.9.8h
To reproduce more than one thread must call
SSL_library_init or other functions that modify names_lh at approximiately the
same time.
The stack traces will look something
like:
#0 0x0097aa52 in _dl_sysinfo_int80 () from
/lib/ld-linux.so.2
#1 0x001503ae in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
#2 0x001518f8 in *__GI_abort () at ../sysdeps/generic/abort.c:88
#3 0x0017ecf9 in __libc_message (do_abort=2, fmt=0x220da0 "*** glibc detected *** %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:145
#4 0x00183e1a in malloc_printerr (action="" str=0x220e0c "double free or corruption (fasttop)", ptr=0xb7401fb8) at malloc.c:5525
#5 0x001857d5 in _int_realloc (av=0xb7400010, oldmem=0xb7401fb8, bytes=0) at malloc.c:4668
#6 0x00186684 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3487
#7 0x00186c9c in realloc_hook_ini (ptr=0xb7401fb8, sz=128, caller=0x81cced6) at hooks.c:54
#8 0x001865d1 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3425
#9 0x081cced6 in default_realloc_ex (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:86
#10 0x081cd4ff in CRYPTO_realloc (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:331
#11 0x081e851a in expand (lh=0xb7401f50) at lhash.c:341
#12 0x081e81a0 in lh_insert (lh=0xb7401f50, data="" at lhash.c:187
#13 0x081cfbd8 in OBJ_NAME_add (name=0x828ef27 "ssl2-md5", type=1, data="" "MD5") at o_names.c:203
#14 0x081cc5a4 in SSL_library_init () at ssl_algs.c:100
#1 0x001503ae in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
#2 0x001518f8 in *__GI_abort () at ../sysdeps/generic/abort.c:88
#3 0x0017ecf9 in __libc_message (do_abort=2, fmt=0x220da0 "*** glibc detected *** %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:145
#4 0x00183e1a in malloc_printerr (action="" str=0x220e0c "double free or corruption (fasttop)", ptr=0xb7401fb8) at malloc.c:5525
#5 0x001857d5 in _int_realloc (av=0xb7400010, oldmem=0xb7401fb8, bytes=0) at malloc.c:4668
#6 0x00186684 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3487
#7 0x00186c9c in realloc_hook_ini (ptr=0xb7401fb8, sz=128, caller=0x81cced6) at hooks.c:54
#8 0x001865d1 in *__GI___libc_realloc (oldmem=0xb7401fb8, bytes=128) at malloc.c:3425
#9 0x081cced6 in default_realloc_ex (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:86
#10 0x081cd4ff in CRYPTO_realloc (str=0xb7401fb8, num=128, file=0x829df09 "lhash.c", line=342) at mem.c:331
#11 0x081e851a in expand (lh=0xb7401f50) at lhash.c:341
#12 0x081e81a0 in lh_insert (lh=0xb7401f50, data="" at lhash.c:187
#13 0x081cfbd8 in OBJ_NAME_add (name=0x828ef27 "ssl2-md5", type=1, data="" "MD5") at o_names.c:203
#14 0x081cc5a4 in SSL_library_init () at ssl_algs.c:100
See attached patch file for
fix.
This doesn't appear to be an
exploitable security vulnerability as far as I can tell. This bug
appears to have existed as far back as 1999 based on looking
at http://cvs.openssl.org/rlog?f=openssl/crypto/objects/o_names.c