Skip to content

Commit e7666c1

Browse files
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 da43fd6 commit e7666c1

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

‎src/audio/module_adapter/module_adapter_ipc4.c‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,16 @@ int module_adapter_init_data(struct comp_dev *dev,
187187
}
188188
}
189189

190-
/* Assume legacy API if module data was not found in ext_init payload */
191-
if (!config->ipc_extended_init || !dst->ext_data->module_data) {
192-
dst->init_data = cfg; /* legacy API */
190+
/* Always provide init_data so legacy modules have a valid pointer.
191+
* Extended-init-aware modules (e.g. cadence) read
192+
* ext_data->module_data directly and never dereference init_data.
193+
* Note: cfg points into the IPC mailbox and must not be used
194+
* persistently; it is reset to NULL by module_adapter_reset_data()
195+
* in module_adapter_new_ext() after module_init() returns.
196+
*/
197+
dst->init_data = cfg;
198+
if (!config->ipc_extended_init || !dst->ext_data->module_data)
193199
dst->avail = true;
194-
}
195200

196201
return 0;
197202
}

0 commit comments

Comments
 (0)