From 607e39d9844c2f44171fb4a4b2464b03d3b4b2a8 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 13:07:36 +0100 Subject: [PATCH 1/2] ipc3: bound host page count before page table DMA and parsing The host-supplied ring->pages drives both the page table DMA transfer length (20 bits per page) and the DSP-side descriptor allocations, but only ring->size was sanity checked. A large page count could overflow the fixed-size page table buffer and wrap the page-count multiplication. Reject a zero or too-large page count at the single entry point before any use. Signed-off-by: Liam Girdwood --- src/ipc/ipc3/host-page-table.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/ipc/ipc3/host-page-table.c b/src/ipc/ipc3/host-page-table.c index e90203a79dce..dbd0fd0fe030 100644 --- a/src/ipc/ipc3/host-page-table.c +++ b/src/ipc/ipc3/host-page-table.c @@ -16,6 +16,25 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); +/* + * Size in bytes of the DSP-side buffer that receives the compressed host page + * table. DSP targets define PLATFORM_PAGE_TABLE_SIZE; the host/library builds + * (e.g. testbench, fuzzer) allocate it as HOST_PAGE_SIZE in drivers/host/ipc.c + * and do not define PLATFORM_PAGE_TABLE_SIZE, so fall back to that. + */ +#ifndef PLATFORM_PAGE_TABLE_SIZE +#define PLATFORM_PAGE_TABLE_SIZE HOST_PAGE_SIZE +#endif + +/* + * The compressed page table stores one 20-bit entry per host page, so the + * number of pages whose entries fit in the page table buffer is + * (buffer bytes * 8 bits/byte) / 20 bits/page. + */ +#define HOST_PAGE_TABLE_BITS_PER_PAGE 20 +#define HOST_PAGE_TABLE_MAX_PAGES \ + (PLATFORM_PAGE_TABLE_SIZE * 8 / HOST_PAGE_TABLE_BITS_PER_PAGE) + /* * Parse the host page tables and create the audio DMA SG configuration * for host audio DMA buffer. This involves creating a dma_sg_elem for each @@ -216,6 +235,19 @@ int ipc_process_host_buffer(struct ipc *ipc, struct ipc_data_host_buffer *data_host_buffer; int err; + /* + * The host-supplied page count is used both to size DSP-side + * allocations and to compute the DMA transfer length for the + * compressed page table. Reject a count that would not fit in the + * page table buffer before doing any arithmetic that could overflow + * (ring->pages * 20). pages == 0 is also invalid and would underflow + * the ring->size sanity check in ipc_parse_page_descriptors(). + */ + if (ring->pages == 0 || ring->pages > HOST_PAGE_TABLE_MAX_PAGES) { + tr_err(&ipc_tr, "ipc: invalid page count %u", ring->pages); + return -EINVAL; + } + data_host_buffer = ipc_platform_get_host_buffer(ipc); dma_sg_init(elem_array); From 92a92235c752d28aa0aa4d5d443c7ddb361ee766 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:31:03 +0100 Subject: [PATCH 2/2] ipc3: avoid overflow in the process size bounds check The bounds check added two host-supplied 32-bit sizes, which could wrap and let an oversized value pass. Compare without adding by subtracting from the maximum instead. Signed-off-by: Liam Girdwood --- src/ipc/ipc3/helper.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 4d87f042dd1d..37d00b9eb912 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -302,7 +302,11 @@ static int comp_specific_builder(struct sof_ipc_comp *comp, if (IPC_TAIL_IS_SIZE_INVALID(*proc)) return -EBADMSG; - if (proc->comp.hdr.size + proc->size > SOF_IPC_MSG_MAX_SIZE) + /* compare without adding the two host-supplied uint32_t values, + * which could wrap and let an oversized proc->size pass + */ + if (proc->comp.hdr.size > SOF_IPC_MSG_MAX_SIZE || + proc->size > SOF_IPC_MSG_MAX_SIZE - proc->comp.hdr.size) return -EBADMSG; config->process.type = proc->type;