Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions src/audio/module_adapter/module_adapter_ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/pipeline.h>
#include <sof/common.h>
#include <sof/lib/mailbox.h>
#include <sof/platform.h>
#include <sof/ut.h>
#include <rtos/interrupt.h>
Expand All @@ -28,17 +29,22 @@ LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL);
int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init_data *ext_data,
struct ipc_config_process *spec)
{
const struct ipc4_module_init_ext_init *ext_init =
(const struct ipc4_module_init_ext_init *)spec->data;
bool last_object = !ext_init->data_obj_array;
const struct ipc4_module_init_ext_init *ext_init;
const struct ipc4_module_init_ext_object *obj;
bool last_object;
size_t consumed;

assert(drv->type == SOF_COMP_MODULE_ADAPTER);
if (spec->size < sizeof(ext_init)) {
comp_cl_err(drv, "Size too small for ext init %zu < %zu",
spec->size, sizeof(ext_init));

/* Validate size before dereferencing ext_init pointer */
if (spec->size < sizeof(*ext_init)) {
comp_cl_err(drv, "Size too small for ext init %u < %zu",
spec->size, sizeof(*ext_init));
Comment thread
tmleman marked this conversation as resolved.
return -EINVAL;
}

ext_init = (const struct ipc4_module_init_ext_init *)spec->data;
last_object = !ext_init->data_obj_array;
/* TODO: Handle ext_init->gna_used and ext_init->rtos_domain here */
/* Get the first obj struct right after ext_init struct */
obj = (const struct ipc4_module_init_ext_object *)(ext_init + 1);
Expand All @@ -47,15 +53,15 @@ int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init

/* Check if there is space for the object header */
if ((unsigned char *)(obj + 1) - spec->data > spec->size) {
comp_cl_err(drv, "ext init obj overflow, %u > %zu",
comp_cl_err(drv, "ext init obj overflow, %u > %u",
(unsigned char *)(obj + 1) - spec->data, spec->size);
return -EINVAL;
}
/* Calculate would be next object position and check if current object fits */
next_obj = (const struct ipc4_module_init_ext_object *)
(((uint32_t *) (obj + 1)) + obj->object_words);
if ((unsigned char *)next_obj - spec->data > spec->size) {
comp_cl_err(drv, "ext init object array overflow, %u > %zu",
comp_cl_err(drv, "ext init object array overflow, %u > %u",
(unsigned char *)obj - spec->data, spec->size);
return -EINVAL;
}
Expand Down Expand Up @@ -103,7 +109,15 @@ int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init
}

/* Remove decoded ext_init payload from spec */
spec->size -= (unsigned char *)obj - spec->data;
consumed = (unsigned char *)obj - spec->data;

if (consumed > spec->size) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is already checked in the loop when processing that last object in lines 55-67 (with the patch applied), isn't it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, with the sizeof fix in place this check is technically redundant. The no-loop path can't underflow because we already validated spec->size >= sizeof(*ext_init), and when the loop runs the bounds checks on lines 55-67 cover it.

I kept it as a defense-in-depth catch-all right before the subtraction. It's one comparison and it makes the function self-contained. If someone refactors the loop bounds logic later, this still prevents the underflow. Happy to drop it if you feel it's unnecessary noise.

comp_cl_err(drv, "ext_init consumed more than spec->size (%zu > %u)",
consumed, spec->size);
return -EINVAL;
Comment thread
tmleman marked this conversation as resolved.
}

spec->size -= consumed;
spec->data = (const unsigned char *)obj;

return 0;
Expand Down Expand Up @@ -132,8 +146,10 @@ int module_adapter_init_data(struct comp_dev *dev,

if (cfg == NULL)
return -EINVAL;
if (cfgsz < sizeof(cfg->base_cfg))
if (cfgsz > MAILBOX_HOSTBOX_SIZE || cfgsz < sizeof(cfg->base_cfg)) {
comp_err(dev, "invalid config size %zu", cfgsz);
return -EINVAL;
}

dst->base_cfg = cfg->base_cfg;
dst->size = cfgsz;
Expand Down
Loading