[PATCH v6 11/16] crypto: iaa - Fix for "deflate_generic_tfm" global being accessed without locks.

From: Kanchana P Sridhar
Date: Thu Feb 06 2025 - 02:23:20 EST


The mainline implementation of "deflate_generic_decompress" has a bug in
the usage of this global variable:

static struct crypto_comp *deflate_generic_tfm;

The "deflate_generic_tfm" is allocated at module init time, and freed
during module cleanup. Any calls to software decompress, for instance, if
descriptor allocation fails or job submission fails, will trigger this bug
in the deflate_generic_decompress() procedure. The problem is the
unprotected access of "deflate_generic_tfm" in this procedure. While
stress testing workloads under high memory pressure, with 1 IAA device
and "deflate-iaa" as the compressor, the descriptor allocation times out
and the software fallback route is taken. With multiple processes calling:

ret = crypto_comp_decompress(deflate_generic_tfm,
src, req->slen, dst, &req->dlen);

we end up with data corruption, that results in req->dlen being larger
than PAGE_SIZE. zswap_decompress() subsequently raises a kernel bug.

This bug can manifest under high contention and memory pressure situations
with high likelihood. This has been resolved by adding a mutex, which is
locked before accessing "deflate_generic_tfm" and unlocked after the
crypto_comp call is done.

Signed-off-by: Kanchana P Sridhar <kanchana.p.sridhar@xxxxxxxxx>
---
drivers/crypto/intel/iaa/iaa_crypto_main.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
index 5292d8f7ebd6..6796c783dd16 100644
--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
+++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
@@ -105,6 +105,7 @@ static struct iaa_compression_mode *iaa_compression_modes[IAA_COMP_MODES_MAX];

LIST_HEAD(iaa_devices);
DEFINE_MUTEX(iaa_devices_lock);
+DEFINE_MUTEX(deflate_generic_tfm_lock);

/* If enabled, IAA hw crypto algos are registered, unavailable otherwise */
static bool iaa_crypto_enabled;
@@ -1407,6 +1408,9 @@ static int deflate_generic_decompress(struct acomp_req *req)
int ret;

req->dlen = PAGE_SIZE;
+
+ mutex_lock(&deflate_generic_tfm_lock);
+
src = kmap_local_page(sg_page(req->src)) + req->src->offset;
dst = kmap_local_page(sg_page(req->dst)) + req->dst->offset;

@@ -1416,6 +1420,8 @@ static int deflate_generic_decompress(struct acomp_req *req)
kunmap_local(src);
kunmap_local(dst);

+ mutex_unlock(&deflate_generic_tfm_lock);
+
update_total_sw_decomp_calls();

return ret;
--
2.27.0