Skip to content

[FEATURE] audio: module_adapter: harden SET/GET_LARGE_CONFIG multi-fragment reassembly #11169

Description

@tmleman

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions