summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2021-09-10 00:16:15 +0000
committerYann Ylavic <ylavic@apache.org>2021-09-10 00:16:15 +0000
commit398fc32f2930640777aa1afc3417d73c4f3afc48 (patch)
tree5a00164a03ea14ddf45e1fdbf201fd37093cc91a /crypto
parent90a2a773220abffeaf00ffd4562abd8db8b400f3 (diff)
downloadapr-398fc32f2930640777aa1afc3417d73c4f3afc48.tar.gz
apr_crypto: fix potential memory leaks of cprng_stream_ctx_t.
This can happen in cprng_stream_ctx_make() on error paths, or at thread exit with APR_CRYPTO_PRNG_PER_THREAD like the below. Direct leak of 64 byte(s) in 8 object(s) allocated from: #0 0x7efd954c7628 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107628) #1 0x7efd921db6ca (<unknown module>) #2 0x7efd952937a2 in apr_crypto_prng_create crypto/apr_crypto_prng.c:367 #3 0x7efd95292c1e in apr_crypto_random_thread_bytes crypto/apr_crypto_prng.c:218 #4 0x5611dbbb9440 in thread_func /home/yle/src/apache/apr/trunk.ro/test/testcrypto.c:2597 #5 0x7efd9537dd86 in dummy_worker threadproc/unix/thread.c:148 #6 0x7efd951efea6 in start_thread nptl/pthread_create.c:477 git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1893201 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'crypto')
-rw-r--r--crypto/apr_crypto_openssl.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c
index e7a1cfb47..6ec4a474d 100644
--- a/crypto/apr_crypto_openssl.c
+++ b/crypto/apr_crypto_openssl.c
@@ -112,6 +112,7 @@ struct apr_crypto_digest_t {
struct cprng_stream_ctx_t {
EVP_CIPHER_CTX *ctx;
+ int malloced;
};
static struct apr_crypto_block_key_digest_t key_digests[] =
@@ -1537,6 +1538,16 @@ static apr_status_t crypto_digest(
return status;
}
+static void cprng_stream_ctx_free(cprng_stream_ctx_t *sctx)
+{
+ if (sctx->ctx) {
+ EVP_CIPHER_CTX_free(sctx->ctx);
+ }
+ if (sctx->malloced) {
+ free(sctx);
+ }
+}
+
static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
apr_crypto_t *f, apr_crypto_cipher_e cipher, apr_pool_t *pool)
{
@@ -1554,8 +1565,10 @@ static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
return APR_ENOMEM;
}
+ sctx->malloced = !pool;
sctx->ctx = ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
+ cprng_stream_ctx_free(sctx);
return APR_ENOMEM;
}
@@ -1573,6 +1586,7 @@ static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
#elif defined(NID_aes_256_ctr)
ecipher = EVP_aes_256_ctr();
#else
+ cprng_stream_ctx_free(sctx);
return APR_ENOCIPHER;
#endif
}
@@ -1581,6 +1595,7 @@ static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
ecipher = EVP_aes_256_ctr();
break;
#else
+ cprng_stream_ctx_free(sctx);
return APR_ENOCIPHER;
#endif
}
@@ -1589,27 +1604,24 @@ static apr_status_t cprng_stream_ctx_make(cprng_stream_ctx_t **psctx,
ecipher = EVP_chacha20();
break;
#else
+ cprng_stream_ctx_free(sctx);
return APR_ENOCIPHER;
#endif
}
default: {
+ cprng_stream_ctx_free(sctx);
return APR_ENOCIPHER;
}
}
if (EVP_EncryptInit_ex(ctx, ecipher, f->config->engine, NULL, NULL) <= 0) {
- EVP_CIPHER_CTX_free(ctx);
+ cprng_stream_ctx_free(sctx);
return APR_ENOMEM;
}
return APR_SUCCESS;
}
-static void cprng_stream_ctx_free(cprng_stream_ctx_t *sctx)
-{
- EVP_CIPHER_CTX_free(sctx->ctx);
-}
-
static APR_INLINE
void cprng_stream_setkey(cprng_stream_ctx_t *sctx,
const unsigned char *key,