summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-12-18 05:47:28 +0000
committerNick Mathewson <nickm@torproject.org>2008-12-18 05:47:28 +0000
commit9b72e96f95d3048bb1fb83caa03f45b7e6170f93 (patch)
treeb7a053c7630832bfb4fc9cadf5102d0d4b184a11
parent5efd2b2fa7bf61dfb6edb1b7f142b8d3c7641ed2 (diff)
downloadtor-9b72e96f95d3048bb1fb83caa03f45b7e6170f93.tar.gz
tor-9b72e96f95d3048bb1fb83caa03f45b7e6170f93.zip
Backport: Fix bug 889: share deep-copied keys between threads to avoid races in reference counts. Bugfix on 0.1.0.1-rc.
svn:r17674
-rw-r--r--ChangeLog3
-rw-r--r--src/common/crypto.c17
-rw-r--r--src/common/crypto.h1
-rw-r--r--src/or/router.c8
4 files changed, 25 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index beb02549e7..0a06f09a0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -46,6 +46,9 @@ Changes in version 0.2.0.33 - 200?-??-??
- Fix a memory leak when we decline to add a v2 rendezvous descriptor to
the cache because we already had a v0 descriptor with the same ID.
Bugfix on 0.2.0.18-alpha.
+ - Fix a race condition when freeing keys shared between main thread
+ and CPU workers that could result in a memory leak. Bugfix on
+ 0.1.0.1-rc. Fixes bug 889.
o Minor features:
- Report the case where all signatures in a detached set are rejected
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 16f5afef3e..275a8988f7 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -631,6 +631,23 @@ crypto_pk_dup_key(crypto_pk_env_t *env)
return env;
}
+/** Make a real honest-to-goodness copy of <b>env</b>, and return it. */
+crypto_pk_env_t *
+crypto_pk_copy_full(crypto_pk_env_t *env)
+{
+ RSA *new_key;
+ tor_assert(env);
+ tor_assert(env->key);
+
+ if (PRIVATE_KEY_OK(env)) {
+ new_key = RSAPrivateKey_dup(env->key);
+ } else {
+ new_key = RSAPublicKey_dup(env->key);
+ }
+
+ return _crypto_new_pk_env_rsa(new_key);
+}
+
/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
* in <b>env</b>, using the padding method <b>padding</b>. On success,
* write the result to <b>to</b>, and return the number of bytes
diff --git a/src/common/crypto.h b/src/common/crypto.h
index e51c0777a9..b45bc85852 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -88,6 +88,7 @@ int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
size_t crypto_pk_keysize(crypto_pk_env_t *env);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
+crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to,
const char *from, size_t fromlen, int padding);
diff --git a/src/or/router.c b/src/or/router.c
index 6d0428cdd9..d684745907 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -75,8 +75,8 @@ get_onion_key(void)
return onionkey;
}
-/** Store a copy of the current onion key into *<b>key</b>, and a copy
- * of the most recent onion key into *<b>last</b>.
+/** Store a full copy of the current onion key into *<b>key</b>, and a full
+ * copy of the most recent onion key into *<b>last</b>.
*/
void
dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last)
@@ -85,9 +85,9 @@ dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last)
tor_assert(last);
tor_mutex_acquire(key_lock);
tor_assert(onionkey);
- *key = crypto_pk_dup_key(onionkey);
+ *key = crypto_pk_copy_full(onionkey);
if (lastonionkey)
- *last = crypto_pk_dup_key(lastonionkey);
+ *last = crypto_pk_copy_full(lastonionkey);
else
*last = NULL;
tor_mutex_release(key_lock);