Commit cf484d7
committed
audio: module_adapter: always set init_data in module_adapter_init_data
Fix a NULL pointer dereference found by the IPC4 libFuzzer harness
(native_sim/x86, ASAN-enabled build). The fuzzer discovered two
crash inputs (87 and 241 bytes) that trigger SEGV at address 0x28
in volume_init(), crashing on:
vol->config[0].channel_id == IPC4_ALL_CHANNELS_MASK
where vol (cfg->init_data) is NULL and offset 0x28 (40) matches
offsetof(ipc4_peak_volume_module_cfg, config[0].channel_id).
Root cause
----------
module_adapter_init_data() only assigned dst->init_data when the
legacy IPC path was active:
if (!config->ipc_extended_init || !dst->ext_data->module_data) {
dst->init_data = cfg;
dst->avail = true;
}
The fuzzer crafted a payload with the extended_init bit set in the
IPC4 extension word and a well-formed MODULE_DATA typed object in
the payload. This satisfied both conditions to skip the assignment,
leaving init_data as NULL (from struct zero-initialization). Any
subsequent module_init() that dereferences cfg->init_data without a
NULL check would crash. Affected modules include volume (confirmed
crash), selector, and mux (latent NULL derefs); only src_ipc4 and
smart_amp had pre-existing guards.
Fix
---
Move the init_data assignment outside the conditional so it is
always set:
dst->init_data = cfg;
if (!config->ipc_extended_init || !dst->ext_data->module_data)
dst->avail = true;
This is safe because module_ext_init_decode() strips the extended
init header and typed objects from the spec before
module_adapter_init_data() is called (lines 118-122 of the same
file advance spec->data past the consumed objects). Therefore cfg
always points to the same [base_module_cfg + module-specific data]
layout regardless of whether extended_init was set.
The avail flag remains conditional: extended-init-aware modules
(cadence_ipc4) set cfg.avail = false during their init and read
ext_data->module_data directly, never dereferencing init_data.
Alternatives considered
-----------------------
1. Adding a NULL check (if (!vol) return -EINVAL) in each affected
module (volume_init, selector_init, mux_init). Rejected because
it treats the symptom per-module rather than fixing the framework
invariant, and would need to be replicated in every future module
that reads init_data.
2. Rejecting extended_init messages for modules that do not support
it (capability flag per module). This would be architecturally
cleaner but requires a larger refactor and a new per-module
capability declaration. The current fix is pragmatic and safe
without that infrastructure.
Verification
------------
- Both crash artifacts execute cleanly (no SEGV, graceful -EINVAL).
- Smoke test (1500 fuzzer runs, 12 seconds) passes with normal
coverage growth and no new crashes.
- cadence_ipc4 (the only extended-init-aware module) is unaffected:
it reads ext_data->module_data directly and never uses init_data.
Found-by: IPC4 libFuzzer (ASAN, native_sim)
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>1 parent 6e63a68 commit cf484d7
1 file changed
Lines changed: 6 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
190 | | - | |
191 | | - | |
192 | | - | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
193 | 196 | | |
194 | | - | |
195 | 197 | | |
196 | 198 | | |
197 | 199 | | |
| |||
0 commit comments