Skip to content

usbh_edpt_control_open() allocates ep0_desc structure on the stack, which gets corrupted outside of the function #3083

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

Closed
1 task done
joelpmichael opened this issue Apr 16, 2025 · 2 comments
Labels

Comments

@joelpmichael
Copy link
Contributor

Operating System

Linux

Board

ch32v203c_r0_1v0

Firmware

examples/host/device_info

What happened ?

I'm writing USB host support for the CH32V203, and have identified ep_desc structures passed in to hcd_edpt_open() randomly being modified by observing ep_desc->wMaxPacketSize changing to nonsensical values due to the structure being allocated on the stack inside usbh_edpt_control_open():

static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) {
  TU_LOG_USBH("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size);
  tusb_desc_endpoint_t ep0_desc = {
      .bLength = sizeof(tusb_desc_endpoint_t),
      .bDescriptorType = TUSB_DESC_ENDPOINT,
      .bEndpointAddress = 0,
      .bmAttributes = {.xfer = TUSB_XFER_CONTROL},
      .wMaxPacketSize = max_packet_size,
      .bInterval = 0};
  TU_LOG_HEX(3, &ep0_desc);
  TU_LOG_INT(3, ep0_desc.wMaxPacketSize);

  return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc);
}

I've added some extra logging to usbh.c, and this is what I'm getting:

TinyUSB Device Info Example
USBH init on controller 1, speed = Full
sizeof(usbh_device_t) = 86
sizeof(hcd_event_t) = 12
sizeof(_ctrl_xfer) = 20
sizeof(tuh_xfer_t) = 28
sizeof(tu_fifo_t) = 12
sizeof(tu_edpt_stream_t) = 20
HUB init
[1:] USBH Device Attach
Full Speed
[1:0] Open EP0 with Size = 8
&ep0_desc = 0x20004E88
ep0_desc.wMaxPacketSize = 8
hcd_edpt_open: 498:
rhport=1 dev_addr=0
ep_desc = 0x20004E88
ep_desc->wMaxPacketSize = 8
Get 8 byte of Device Descriptor
[1:0] Get Descriptor: 80 06 00 01 00 00 08 00 
hcd_setup_send: 602:
rhport=1 dev_addr=0
usb_device_map[dev_addr].p_ep_desc = 0x20004E88
usb_device_map[dev_addr].p_ep_desc->wMaxPacketSize = 7
on EP 00 with 8 bytes: OK
hcd_edpt_xfer: 522:
rhport=1 dev_addr=0 ep_addr=128 buflen=8
usb_device_map[dev_addr].p_ep_desc = 0x20004E88
usb_device_map[dev_addr].p_ep_desc->wMaxPacketSize = 16622

According to the linker script, 0x20004E88 is inside the stack:

__stack_size = 2048;
MEMORY
{  
	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}
SECTIONS
{
...
    .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
    {
        PROVIDE( _heap_end = . );   
        . = ALIGN(4);
        PROVIDE(_susrstack = . );
        . = . + __stack_size;
        PROVIDE( _eusrstack = .);
    } >RAM 
}

Which means .stack starts at 0x20000000 + 0x5000 - 0x800 = 0x20004800

I'm not sure of the best way to fix this, because all other uses of tusb_desc_endpoint_t are in higher-level drivers.

For now, I'll fix EP0 wMaxPacketSize at 8 bytes to get it working.

How to reproduce ?

Reproduction in "What Happened"

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

Log in "What Happened"

Screenshots

No response

I have checked existing issues, dicussion and documentation

  • I confirm I have checked existing issues, dicussion and documentation.
@HiFiPhile
Copy link
Collaborator

Hi, it is by design, hcd driver need to maintain EP and transfer status internally since different HCDs behaves differently.
You can look at dwc2 example which has _hcd_data stuct.

bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* desc_ep) {

@joelpmichael
Copy link
Contributor Author

joelpmichael commented Apr 16, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants