Skip to content

Commit cf484d7

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 6e63a68 commit cf484d7

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

src/audio/module_adapter/module_adapter_ipc4.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,13 @@ 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+
*/
194+
dst->init_data = cfg;
195+
if (!config->ipc_extended_init || !dst->ext_data->module_data)
193196
dst->avail = true;
194-
}
195197

196198
return 0;
197199
}

0 commit comments

Comments
 (0)