PR #11155 fixed an out-of-bounds heap write (#11153) in the IPC4 SET_LARGE_CONFIG multi-fragment reassembly path. That fix closes the memory-safety hole, but the review raised several robustness, DoS, and specification gaps that were left for a separate change. This issue tracks that hardening work and the matching tests.
Current behavior
In module_set_configuration() (src/audio/module_adapter/module/generic.c), the runtime_params buffer is allocated on the FIRST/SINGLE fragment and freed only when a LAST/SINGLE fragment reaches the module_load_config() tail. Any error return in between (bounds check, memcpy_s failure) leaves runtime_params allocated and new_cfg_size set.
module_set_large_config() and module_get_large_config() (src/audio/module_adapter/module_adapter_ipc4.c) keep no per-sequence state beyond runtime_params and new_cfg_size.
Items to fix
- Roll back on mid-sequence error. After FIRST allocates the buffer, a failing fragment leaves the instance stuck at -EBUSY and leaks the buffer until module_free(). On any error during a sequence, free runtime_params and reset new_cfg_size to 0 so the module returns to idle.
- Enforce sequence integrity. Nothing forces later IPCs to correctly continue an in-progress sequence. Offsets are only range-checked, param_id is not matched across fragments, and unrelated IPCs can interleave. Track sequence state (in-progress, param_id, expected size, received bytes) and reject or terminate any IPC that does not correctly continue the active sequence.
- Reject FIRST-without-LAST for small configs. A config that fits in one mailbox fragment should arrive as SINGLE. A FIRST-only message with total size that fits in one fragment only opens a reassembly that never completes.
- Bound global resource use. -EBUSY only guards one module instance. A host can open reassembly on many instances at once (each up to CONFIG_MODULE_MAX_BLOB_SIZE) with no global cap and no timeout. Add an aggregate cap and/or a timeout that tears down stale sequences.
- Review the GET path. module_get_large_config() validates the host-supplied data_offset_size against cfg.size only on the last_block branch. Confirm the first/middle branches cannot be driven out of bounds.
- Document the protocol. Describe valid position sequences (SINGLE, or FIRST -> MIDDLE* -> LAST), the meaning of data_offset_size per position, size limits, and required FW behavior for malformed input. Add Doxygen to the affected functions.
Testing
Add FW-side negative tests for:
- second FIRST mid-sequence returns -EBUSY, and a fresh sequence works afterwards
- MIDDLE/LAST offset or size beyond the buffer returns -EINVAL with no leak
- LAST data_offset_size greater than the declared total size
- out-of-order or overlapping fragment offsets
- FIRST-without-LAST small config
PR #11155 fixed an out-of-bounds heap write (#11153) in the IPC4 SET_LARGE_CONFIG multi-fragment reassembly path. That fix closes the memory-safety hole, but the review raised several robustness, DoS, and specification gaps that were left for a separate change. This issue tracks that hardening work and the matching tests.
Current behavior
In module_set_configuration() (src/audio/module_adapter/module/generic.c), the runtime_params buffer is allocated on the FIRST/SINGLE fragment and freed only when a LAST/SINGLE fragment reaches the module_load_config() tail. Any error return in between (bounds check, memcpy_s failure) leaves runtime_params allocated and new_cfg_size set.
module_set_large_config() and module_get_large_config() (src/audio/module_adapter/module_adapter_ipc4.c) keep no per-sequence state beyond runtime_params and new_cfg_size.
Items to fix
Testing
Add FW-side negative tests for: