Skip to content

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

Closed
@joelpmichael

Description

@joelpmichael

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions