-
Notifications
You must be signed in to change notification settings - Fork 349
module_adapter: generic: Fix use after free #10297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a use-after-free vulnerability in the module adapter's generic resource management by properly cleaning up free container lists and resetting resource accounting.
- Remove containers from the free container list before freeing container chunks to prevent dangling pointers
- Reset all resource lists and heap usage accounting to ensure clean state after freeing resources
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
53da97f to
01e4e87
Compare
tmleman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Fails in CI looks like env issue, lets wait for re-run.
lyakh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand it correctly, that this is addressing a case, when "chunks" of containers are freed, then they happen to be allocated again and the new owner finds old data in them? If that my understanding is correct, then I don't think this is a right approach. If we want to do this, then we'd have to memset(0) all memory buffers before freeing.
|
@lyakh No. Container chunks have allocated up to 16 containers. We store references to these containers in the free containers list. Then when we free a chunk, we free the memory for this 16 containers but we do not remove the references from the containers free list. This means that the containers list will contain some pointers to freed memory. Next time we allocate a container chunk we allocate again new 16 containers chunks and we place references to this new containers in the free containers list. But this list already has references to the older containers (because we never removed them from free container list). What happens is that at some point one of the older references is picked to be used and we access freed memory. using memset won't help. |
kv2019i
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent catch @dbaluta ! @jsarha is not today available to comment, but I think the original implementation did not expect the module to be used again after mod_free_all(). In module_adapter_free(), there's a call to mod_free_all() but afterwards the module resources are also freed. But I now see in cadence.c, mod_free_all() is called in multiple places, including cadence_codec_reset(). And yeah, mod_free_all() does not leave the containers in proper state.
| list_init(&res->res_list); | ||
| list_init(&res->free_cont_list); | ||
| list_init(&res->cont_chunk_list); | ||
| res->heap_usage = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe call to "mod_resource_init()" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, will send a new version asap.
|
@dbaluta @lgirdwood I think we need this fix in stable-v2.14 as well. |
01e4e87 to
68b7672
Compare
|
Changes since v1:
I will backport it to v2.14 once this is merged. |
68b7672 to
fb17ec9
Compare
@dbaluta right, yes, thanks for explaining. But usually |
Factor out resource initialization so that it can be reused. While at it get rid of md variable. Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Remove any containers from the free container list so that we don't keep pointers to containers that are no longer used and will be freed when container chunks are released below. Leaving those nodes in the free container list would cause use-after-free on subsequent allocations. While at it, make sure all resource lists are reset. Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some room for optimization, but looks good otherwise.
| struct module_resource *container = | ||
| container_of(list, struct module_resource, list); | ||
|
|
||
| list_item_del(&container->list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no need to do this anymore, after the mod_resource_init(mod) call was added. It will reinitialize &res->free_cont_list at the end of the function. No need to remove the containers one by one.
| container_of(list, struct module_resource, list); | ||
|
|
||
| free_contents(mod, container); | ||
| list_item_del(&container->list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually also this list_item_del()-call could be removed now that &res->res_list is also reinitialized at the end of the function when mod_resource_init() is called.
lgirdwood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack - this will be needed for v2.14
Remove any containers from the free container list so that we don't keep pointers to containers that are no longer used and will be freed when container chunks are released below.
Leaving those nodes in the free container list would cause use-after-free on subsequent allocations.
While at it, make sure all resource lists are reset.