diff options
author | Yann Ylavic <ylavic@apache.org> | 2021-09-10 00:16:15 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2021-09-10 00:16:15 +0000 |
commit | 398fc32f2930640777aa1afc3417d73c4f3afc48 (patch) | |
tree | 5a00164a03ea14ddf45e1fdbf201fd37093cc91a /crypto | |
parent | 90a2a773220abffeaf00ffd4562abd8db8b400f3 (diff) | |
download | apr-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.c | 24 |
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, |