Skip to content
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

usb: endpoint buffer leak upon SET_CONFIGURATION, SET_INTERFACE #23178

Closed
jmgao opened this issue Feb 29, 2020 · 8 comments · Fixed by #26288
Closed

usb: endpoint buffer leak upon SET_CONFIGURATION, SET_INTERFACE #23178

jmgao opened this issue Feb 29, 2020 · 8 comments · Fixed by #26288
Assignees
Labels
area: Drivers area: USB Universal Serial Bus bug The issue is a bug, or the PR is fixing a bug platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM) priority: low Low impact/importance bug

Comments

@jmgao
Copy link
Contributor

jmgao commented Feb 29, 2020

Describe the bug
Some platforms don't use a real allocator to allocate endpoint packet buffers, and just bump a pointer into a buffer (stm32, sam0), which results in the buffer getting leaked every time an endpoint is configured as a result of SET_CONFIGURATION or SET_INTERFACE, which quickly leads to configuration failing. It looks like sam0 can be switched over to using a mempool pretty trivially, but stm32 has a dedicated region of memory for USB packets, which makes things harder. It seems to me that the simplest solution would be to add something along the lines of usb_dc_reconfigure to let the driver know it can throw away all of the endpoint buffers.

To Reproduce
Steps to reproduce the behavior:
Build any USB sample, pip3 install pyusb and then run this python script:

import usb.core
import usb.util
dev = usb.core.find(idVendor=0x2FE3)
dev.detach_kernel_driver(0)
while True:
    dev.set_configuration()

and you'll see logs that are something along the lines of the following (along with a broken USB device):

[00:00:00.374,000] <inf> hid: USB_DC_RESET
[00:00:00.476,000] <inf> hid: USB_DC_CONFIGURED
[00:00:03.344,000] <inf> hid: USB_DC_CONFIGURED
[00:00:03.345,000] <inf> hid: USB_DC_CONFIGURED
[00:00:03.345,000] <err> usb_device: Failed to configure endpoint 0x81
[00:00:03.345,000] <err> usb_device: Failed to configure endpoint 0x01
[00:00:03.345,000] <inf> hid: USB_DC_CONFIGURED
@jmgao jmgao added the bug The issue is a bug, or the PR is fixing a bug label Feb 29, 2020
jmgao added a commit to passinglink/zephyr that referenced this issue Mar 1, 2020
Previously, endpoint configuration would reserve memory in the packet
memory area which would never be reclaimed. After this patch, the leak
still exists on SET_CONFIGURATION/SET_INTERFACE, but we will at least
reclaim the memory upon reset, so disconnect/reconnect gets us back
into a working state.

Bug: zephyrproject-rtos#23178
Signed-off-by: Josh Gao <josh@jmgao.dev>
@jfischer-no jfischer-no added area: Drivers area: USB Universal Serial Bus priority: low Low impact/importance bug platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM) platform: STM32 ST Micro STM32 labels Mar 2, 2020
@jfischer-no
Copy link
Collaborator

It looks like sam0 can be switched over to using a mempool pretty trivially,but stm32 has a dedicated region of memory for USB packets, which makes things harder. It seems to me that the simplest solution would be to add something along the lines of usb_dc_reconfigure to let the driver know it can throw away all of the endpoint buffers.

No need for usb_dc_reconfigure as we have usb_dc_ep_disable(). Independent of the issues in the drivers, usb_set_configuration() could rather also call reset_endpoint() as just set_endpoint(). But as I can remember, we tolerate this because the stack supports only one configuration. It is also up to the driver to check if a endpoint is already configured and not allocate the buffer if not necessary. usb_dc_stm32.c does not track the status of the endpoints, but that could probably done by using ep_mps variable or a new bool enabled in usb_dc_stm32_ep_state.

jmgao added a commit to jmgao/zephyr that referenced this issue Mar 3, 2020
Previously, endpoint configuration would reserve memory in the packet
memory area which would never be reclaimed. After this patch, endpoints
will reuse previously allocated memory when possible. We still leak
memory when reconfiguration increases the max packet size for a given
endpoint number, but this fixes the common case.

Bug: zephyrproject-rtos#23178
Signed-off-by: Josh Gao <josh@jmgao.dev>
@jmgao
Copy link
Contributor Author

jmgao commented Mar 3, 2020

But as I can remember, we tolerate this because the stack supports only one configuration.

That's true of configuration right now, but interface alt setting seems to be supported today (and support for multiple configurations is something that probably needs be implemented at some point?)

I switched my stm32 patch over to tracking the size of the buffer allocated and leaking/reallocating if the mps increases, which probably covers the common case?

@eobalski
Copy link
Collaborator

eobalski commented Mar 4, 2020

It seems to me that the simplest solution would be to add something along the lines of usb_dc_reconfigure to let the driver know it can throw away all of the endpoint buffers.

I dont think this is good approach as it will make an exception for those drivers which does not track the internal configurations. The case is st driver does not free the buffer which was previously allocated here.

I see 2 solutions (st):

  • Check if the endpoint has already configured the space for the buffer here If yes return -EALREADY.

  • Free memory in usb_dc_ep_disable and add something like
    reset_endpoints() to usb_set_configuration() as @jfischer-phytec-iot mentioned.

I think the 2nd option is not the greatest as it will impact all drivers with additional reset_eps() call.

But as I can remember, we tolerate this because the stack supports only one configuration.

That's true of configuration right now, but interface alt setting seems to be supported today (and support for multiple configurations is something that probably needs be implemented at some point?)

To make it usefull we would first have to have multiple configuration support in the descriptors and we do not support that (and probably would never have ) so there is no need for that at all.

@eobalski
Copy link
Collaborator

eobalski commented Mar 4, 2020

nvm, I hadn't noticed You have already posted a pr for this.

@jfischer-no
Copy link
Collaborator

and support for multiple configurations is something that probably needs be implemented at some point?

Disagree, that is disproportionate effort compared to the use case.

jhedberg pushed a commit that referenced this issue Mar 10, 2020
Previously, endpoint configuration would reserve memory in the packet
memory area which would never be reclaimed. After this patch, endpoints
will reuse previously allocated memory when possible. We still leak
memory when reconfiguration increases the max packet size for a given
endpoint number, but this fixes the common case.

Bug: #23178
Signed-off-by: Josh Gao <josh@jmgao.dev>
hakehuang pushed a commit to hakehuang/zephyr that referenced this issue Mar 18, 2020
Previously, endpoint configuration would reserve memory in the packet
memory area which would never be reclaimed. After this patch, endpoints
will reuse previously allocated memory when possible. We still leak
memory when reconfiguration increases the max packet size for a given
endpoint number, but this fixes the common case.

Bug: zephyrproject-rtos#23178
Signed-off-by: Josh Gao <josh@jmgao.dev>
@erwango
Copy link
Member

erwango commented May 13, 2020

@jmgao @jfischer-phytec-iot, issue is still open, but PR has been merged.
Can we close it ?

@carlescufi
Copy link
Member

@jmgao @jfischer-phytec-iot, issue is still open, but PR has been merged.
Can we close it ?

Yes, let's close it. If there are any unresolved issue this can be reopened.

@jfischer-no jfischer-no removed the platform: STM32 ST Micro STM32 label May 15, 2020
@jfischer-no
Copy link
Collaborator

Reopen as it still an issue on usb_dc_sam0

nzmichaelh added a commit to nzmichaelh/zephyr that referenced this issue Jun 25, 2020
Also automatically enable the heap if the USB device is selected.

Part of zephyrproject-rtos#23178

Signed-off-by: Michael Hope <mlhx@google.com>
nashif pushed a commit that referenced this issue Jul 6, 2020
Also automatically enable the heap if the USB device is selected.

Part of #23178

Signed-off-by: Michael Hope <mlhx@google.com>
nzmichaelh added a commit to nzmichaelh/zephyr that referenced this issue Jul 12, 2020
Also automatically enable the heap if the USB device is selected.

Part of zephyrproject-rtos#23178

Signed-off-by: Michael Hope <mlhx@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Drivers area: USB Universal Serial Bus bug The issue is a bug, or the PR is fixing a bug platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM) priority: low Low impact/importance bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants