[PATCH 1/2] crypto: qat - validate migration section header is in bounds

From: Michael Bommarito

Date: Sun Jun 14 2026 - 09:07:07 EST


adf_mstate_mgr_init_from_remote() sets the section-walk cursor to
mgr->buf + preh_len from the remote migration preamble. The default
preamble checker only rejects preh_len > mgr->size, so preh_len ==
mgr->size (the 4096-byte QAT VF state buffer) puts mgr->state one
region past the allocation while n_sects is still honoured.
adf_mstate_sect_validate() then reads sect->size from that cursor
before proving the section header is in the buffer. The remote stream
reaches this parser from the destination-host VFIO migration path
(qat_vf_resume_write), so a malformed import reads out of bounds.

Reject section headers not fully contained in the state buffer before
dereferencing any of their fields.

Reproduced under KASAN on QEMU via the KUnit case in patch 2; the
slab-out-of-bounds read is gone after this change.

Fixes: f0bbfc391aa7 ("crypto: qat - implement interface for live migration")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@xxxxxxxxx>
---
The patch 2 KUnit case drives the real parser on a kmalloc(4096) buffer
under KASAN on QEMU x86_64. Trigger {preh_len=4096, n_sects=1}: stock
tree reports

BUG: KASAN: slab-out-of-bounds in qat_mstate_remote_run

reading sect->size 8 bytes past the allocation; patched it returns
-EINVAL and KASAN is silent. Two benign controls (empty preamble,
in-bounds section header) drive the same path with no OOB and pass on
both trees. No in-tree selftest exercises adf_mstate_mgr.c; patch 2 is
the coverage offered. KASAN build of the touched object is warning clean.

.../crypto/intel/qat/qat_common/adf_mstate_mgr.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
index f9017e03ec0f2..7370b87f72a2f 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
@@ -231,8 +231,18 @@ static int adf_mstate_sect_validate(struct adf_mstate_mgr *mgr)

end = (uintptr_t)mgr->buf + mgr->size;
for (i = 0; i < mgr->n_sects; i++) {
- uintptr_t s_start = (uintptr_t)sect->state;
- uintptr_t s_end = s_start + sect->size;
+ uintptr_t s_start, s_end;
+
+ /* The section header must be in the buffer before it is read. */
+ if ((uintptr_t)sect < (uintptr_t)mgr->buf ||
+ (uintptr_t)sect > end - sizeof(*sect)) {
+ pr_debug("QAT: LM - Section header out of bounds (index=%u) in state_mgr (size=%u, secs=%u)\n",
+ i, mgr->size, mgr->n_sects);
+ return -EINVAL;
+ }
+
+ s_start = (uintptr_t)sect->state;
+ s_end = s_start + sect->size;

if (s_end < s_start || s_end > end) {
pr_debug("QAT: LM - Corrupted state section (index=%u, size=%u) in state_mgr (size=%u, secs=%u)\n",
--
2.53.0