diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index e55af1c66ec5..df243fa6ff58 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -441,6 +441,21 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) if (state.extension.r.multi_ppl) { ppl_count = ppl_data->pipelines_count; + /* + * pipelines_count is read straight from the host-provided + * mailbox payload, so cap it at what the mailbox can + * physically hold. Anything larger means the host promised + * more ppl_id[] entries than fit in MAILBOX_HOSTBOX, and + * dereferencing the flex array would read out of bounds. + */ + if (ppl_count > (MAILBOX_HOSTBOX_SIZE - + sizeof(struct ipc4_pipeline_set_state_data)) / + sizeof(uint32_t)) { + ipc_cmd_err(&ipc_tr, + "ipc: pipelines_count %u exceeds mailbox bound", + ppl_count); + return IPC4_ERROR_INVALID_PARAM; + } ppl_id = ppl_data->ppl_id; dcache_invalidate_region((__sparse_force void __sparse_cache *)ppl_id, sizeof(int) * ppl_count); diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 892e704eb2e4..8e3073ab7797 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -271,6 +271,7 @@ __cold static int ipc4_create_pipeline_payload_decode(char *data, if (size > MAILBOX_HOSTBOX_SIZE) { tr_err(&ipc_tr, "Payload size too large: %u : %#x", hdr->payload_words, *((uint32_t *)hdr)); + return -EINVAL; } tr_info(&ipc_tr, "payload size %u array %u: %#x", hdr->payload_words, hdr->data_obj_array, *((uint32_t *)hdr)); diff --git a/src/platform/posix/fuzz.c b/src/platform/posix/fuzz.c index 555a22d40578..e5c515c15a45 100644 --- a/src/platform/posix/fuzz.c +++ b/src/platform/posix/fuzz.c @@ -32,9 +32,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) } /* Provide the fuzz data to the embedded OS as an interrupt, with - * "DMA-like" data placed into native_fuzz_buf/sz + * "DMA-like" data placed into posix_fuzz_buf/sz. */ - posix_fuzz_buf = (void *)data; + posix_fuzz_buf = data; posix_fuzz_sz = sz; hw_irq_ctrl_set_irq(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); diff --git a/src/platform/posix/include/platform/lib/memory.h b/src/platform/posix/include/platform/lib/memory.h index e15e5f370aec..7782ab55048b 100644 --- a/src/platform/posix/include/platform/lib/memory.h +++ b/src/platform/posix/include/platform/lib/memory.h @@ -6,25 +6,38 @@ #define PLATFORM_HOST_PLATFORM_MEMORY_H #include +#include #define PLATFORM_DCACHE_ALIGN 64 #define uncache_to_cache(addr) (addr) #define cache_to_uncache(addr) (addr) +/* + * Mailbox base macros must yield byte-pointer arithmetic so that the + * generic mailbox API in `sof/src/include/sof/lib/mailbox.h` + * (`MAILBOX_HOSTBOX_BASE + offset`, etc., where `offset` is a byte + * offset) addresses the intended byte. The backing storage is + * declared as `uint32_t[]` only for natural-alignment; addressing is + * done through a `uint8_t *` cast so byte offsets do not get scaled + * by `sizeof(uint32_t)`. Every other SOF platform defines these + * bases as plain byte addresses (integer literals or + * `SRAM_INBOX_BASE`), so the cast keeps POSIX consistent with that + * ABI. + */ extern uint32_t posix_hostbox[]; -#define MAILBOX_HOSTBOX_SIZE 1024 -#define MAILBOX_HOSTBOX_BASE (&posix_hostbox[0]) +#define MAILBOX_HOSTBOX_SIZE SOF_IPC_MSG_MAX_SIZE +#define MAILBOX_HOSTBOX_BASE ((uint8_t *)&posix_hostbox[0]) extern uint32_t posix_dspbox[]; #define MAILBOX_DSPBOX_SIZE 4096 -#define MAILBOX_DSPBOX_BASE (&posix_dspbox[0]) +#define MAILBOX_DSPBOX_BASE ((uint8_t *)&posix_dspbox[0]) extern uint32_t posix_stream[]; #define MAILBOX_STREAM_SIZE 4096 -#define MAILBOX_STREAM_BASE (&posix_stream[0]) +#define MAILBOX_STREAM_BASE ((uint8_t *)&posix_stream[0]) extern uint32_t posix_trace[]; -#define MAILBOX_TRACE_BASE (&posix_trace[0]) +#define MAILBOX_TRACE_BASE ((uint8_t *)&posix_trace[0]) #define MAILBOX_TRACE_SIZE 4096 #define PLATFORM_HEAP_SYSTEM 1 diff --git a/src/platform/posix/ipc.c b/src/platform/posix/ipc.c index 701686e6ff97..35e203c2d468 100644 --- a/src/platform/posix/ipc.c +++ b/src/platform/posix/ipc.c @@ -22,8 +22,9 @@ static void posix_ipc_isr(void *arg) ipc_schedule_process(global_ipc); } -// External symbols set up by the fuzzing layer -extern uint8_t *posix_fuzz_buf, posix_fuzz_sz; +// External symbols set up by the fuzzing layer in fuzz.c. +extern const uint8_t *posix_fuzz_buf; +extern size_t posix_fuzz_sz; // Lots of space. Should really synchronize with the -max_len // parameter to libFuzzer (defaults to 4096), but that requires @@ -145,11 +146,38 @@ static void fuzz_isr(const void *arg) // ipc_platform_compact_read_msg(), writing 8 bytes unconditionally on // the header object it receives, which is then returned here, and // then passed to ipc_cmd(). +// +// The harness also mirrors the framed message into MAILBOX_HOSTBOX so +// that handlers reading payload directly from the hostbox region +// (large_config_set/get, set_dx, set_pipeline_state, vendor_config and +// friends in ipc4/handler-user.c and ipc4/handler-kernel.c) observe +// the fuzz bytes rather than stale or zero-filled memory. +// +// The two IPC majors split header and payload differently: +// +// * IPC3 carries the header in-band at the start of the message, and +// mailbox_validate() walks the full message starting from offset 0 +// of the hostbox. The full message is mirrored as-is. +// +// * IPC4 splits the 8-byte compact header (consumed via +// ipc_compact_read_msg()) from the payload, which on real hardware +// lives in HOSTBOX. The harness therefore mirrors only the +// post-header bytes, so the first dword of MAILBOX_HOSTBOX matches +// the first dword of the IPC4 payload (e.g. pipelines_count for +// SET_PIPELINE_STATE) instead of header bits. +// +// posix_hostbox is sized to SOF_IPC_MSG_MAX_SIZE (see +// platform/lib/memory.h), so the copy is always in bounds for both +// IPC3 and IPC4 message envelopes. enum task_state ipc_platform_do_cmd(struct ipc *ipc) { struct ipc_cmd_hdr *hdr; #ifdef CONFIG_IPC_MAJOR_4 + memset(posix_hostbox, 0, SOF_IPC_MSG_MAX_SIZE); + memcpy(posix_hostbox, + (const uint8_t *)global_ipc->comp_data + sizeof(struct ipc_cmd_hdr), + SOF_IPC_MSG_MAX_SIZE - sizeof(struct ipc_cmd_hdr)); hdr = ipc_compact_read_msg(); #else memcpy(posix_hostbox, global_ipc->comp_data, SOF_IPC_MSG_MAX_SIZE);