CVE-2026-46081
Description
In the Linux kernel, the following vulnerability has been resolved:
crypto: acomp - fix wrong pointer stored by acomp_save_req()
acomp_save_req() stores &req->chain in req->base.data. When acomp_reqchain_done() is invoked on asynchronous completion, it receives &req->chain as the data argument but casts it directly to struct acomp_req. Since data points to the chain member, all subsequent field accesses are at a wrong offset, resulting in memory corruption.
The issue occurs when an asynchronous hardware implementation, such as the QAT driver, completes a request that uses the DMA virtual address interface (e.g. acomp_request_set_src_dma()). This combination causes crypto_acomp_compress() to enter the acomp_do_req_chain() path, which sets acomp_reqchain_done() as the completion callback via acomp_save_req().
With KASAN enabled, this manifests as a general protection fault in acomp_reqchain_done():
general protection fault, probably for non-canonical address 0xe000040000000000 KASAN: probably user-memory-access in range [0x0000400000000000-0x0000400000000007] RIP: 0010:acomp_reqchain_done+0x15b/0x4e0 Call Trace:
qat_comp_alg_callback+0x5d/0xa0 [intel_qat] adf_ring_response_handler+0x376/0x8b0 [intel_qat] adf_response_handler+0x60/0x170 [intel_qat] tasklet_action_common+0x223/0x820 handle_softirqs+0x1ab/0x640
Fix this by storing the request itself in req->base.data instead of &req->chain, so that acomp_reqchain_done() receives the correct pointer. Simplify acomp_restore_req() accordingly to access req->chain directly.
Affected products
2Patches
6343a5bf68a8fcrypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index be28cbfd22e32d..25af7697d6bb96 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -171,15 +171,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
1a2785e59856crypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index 1f9cb04b447f59..6025c1acce4910 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -169,15 +169,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
d7e20b9bd6c9crypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index 1f9cb04b447f59..6025c1acce4910 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -169,15 +169,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
1a2785e59856crypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index 1f9cb04b447f59..6025c1acce4910 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -169,15 +169,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
343a5bf68a8fcrypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index be28cbfd22e32d..25af7697d6bb96 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -171,15 +171,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
d7e20b9bd6c9crypto: acomp - fix wrong pointer stored by acomp_save_req()
1 file changed · +3 −6
crypto/acompress.c+3 −6 modifieddiff --git a/crypto/acompress.c b/crypto/acompress.c index 1f9cb04b447f59..6025c1acce4910 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -169,15 +169,13 @@ static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) state->compl = req->base.complete; state->data = req->base.data; req->base.complete = cplt; - req->base.data = state; + req->base.data = req; } static void acomp_restore_req(struct acomp_req *req) { - struct acomp_req_chain *state = req->base.data; - - req->base.complete = state->compl; - req->base.data = state->data; + req->base.complete = req->chain.compl; + req->base.data = req->chain.data; } static void acomp_reqchain_virt(struct acomp_req *req) -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Pointer type confusion in acomp_save_req(): the address of the chain member (&req->chain) is stored in req->base.data, but acomp_reqchain_done() casts that pointer directly to struct acomp_req, causing all subsequent field accesses to read from the wrong offset."
Attack vector
An attacker triggers the bug by submitting an asynchronous compression request through the DMA virtual address interface (e.g. acomp_request_set_src_dma()) to a hardware accelerator such as the Intel QAT driver [patch_id=2659863]. This causes crypto_acomp_compress() to enter the acomp_do_req_chain() path, which calls acomp_save_req() to set acomp_reqchain_done() as the completion callback. When the hardware completes the request asynchronously, acomp_reqchain_done() receives &req->chain (stored in req->base.data) but casts it to struct acomp_req, reading fields at the wrong offset and corrupting memory. No special privileges are required beyond the ability to submit acomp requests to an affected hardware crypto backend.
Affected code
The bug is in crypto/acompress.c within the static functions acomp_save_req() and acomp_restore_req() [patch_id=2659865]. acomp_save_req() incorrectly stores &req->chain (the address of the chain member) into req->base.data, and acomp_restore_req() reads back from req->base.data treating it as a struct acomp_req_chain pointer.
What the fix does
The patch changes acomp_save_req() to store the request pointer itself (req) in req->base.data instead of the address of the chain member (&req->chain) [patch_id=2659865]. Correspondingly, acomp_restore_req() is simplified to read the saved completion and data directly from req->chain.compl and req->chain.data rather than dereferencing req->base.data as a struct acomp_req_chain pointer. This ensures that when acomp_reqchain_done() receives the data argument, it gets a valid struct acomp_req pointer, eliminating the offset mismatch and the resulting memory corruption.
Preconditions
- configThe system must have an asynchronous hardware compression accelerator (e.g., Intel QAT driver) loaded and configured.
- inputThe attacker must be able to submit acomp requests using the DMA virtual address interface (e.g., acomp_request_set_src_dma()).
- configThe kernel must be built with CONFIG_CRYPTO_ACOMP and the relevant hardware driver enabled.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.