Automated semantic analysis via Coccinelle uncovered a use-after-free vulnerability in gbcodec_hw_params() caused by accessing a list iterator variable outside the loop boundary.
The routine walks through the codec module list using 'list_for_each_entry' to locate a matching data connection. After the loop exits, the iterator pointer 'module' becomes out-of-bounds. Attempting to pass this unmapped reference into 'to_gb_bundle()' down the line triggers a critical kernel panic.
Fix this flaw by introducing a dedicated copy 'allocated_module'. Cache the matched pointer inside the loop block only when 'find_data()' returns a valid reference, and route the subsequent power management execution steps safely through this verified object tracking reference.
Assisted-by: Gemini Signed-off-by: Marinela Tatiana Selseth marinela.selseth@firmwaredesign.org --- drivers/staging/greybus/audio_codec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 6daa4e706792..a0645bf83097 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -396,6 +396,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, u8 sig_bits, channels; u32 format, rate; struct gbaudio_module_info *module; + struct gbaudio_module_info *allocated_module = NULL; struct gbaudio_data_connection *data; struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); @@ -439,8 +440,10 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, /* find the data connection */ list_for_each_entry(module, &codec->module_list, list) { data = find_data(module, dai->id); - if (data) + if (data) { + allocated_module = module; break; + } }
if (!data) { @@ -456,7 +459,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, return -EINVAL; }
- bundle = to_gb_bundle(module->dev); + bundle = to_gb_bundle(allocated_module->dev); ret = gb_pm_runtime_get_sync(bundle); if (ret) { mutex_unlock(&codec->lock);