diff options
| -rw-r--r-- | class/adb/usbd_adb_sync.c | 23 | ||||
| -rw-r--r-- | class/audio/usbh_audio.c | 9 | ||||
| -rw-r--r-- | class/cdc/usbh_cdc_ncm.c | 33 | ||||
| -rw-r--r-- | class/msc/usbd_msc.c | 37 | ||||
| -rw-r--r-- | class/tmc/usbd_tmc.c | 22 | ||||
| -rw-r--r-- | class/vendor/net/usbh_asix.c | 10 | ||||
| -rw-r--r-- | class/vendor/net/usbh_rtl8152.c | 15 | ||||
| -rw-r--r-- | class/video/usbh_video.c | 42 | ||||
| -rw-r--r-- | class/wireless/usbd_rndis.c | 13 | ||||
| -rw-r--r-- | class/wireless/usbh_rndis.c | 10 | ||||
| -rw-r--r-- | common/usb_def.h | 1 | ||||
| -rw-r--r-- | common/usb_log.h | 17 | ||||
| -rw-r--r-- | core/usbd_core.c | 57 | ||||
| -rw-r--r-- | core/usbh_core.c | 133 | ||||
| -rw-r--r-- | demo/adb_template.c | 1 | ||||
| -rw-r--r-- | demo/gs_usb_template.c | 1 | ||||
| -rw-r--r-- | demo/mtp_template.c | 1 | ||||
| -rw-r--r-- | demo/winusb1.0_template.c | 1 | ||||
| -rw-r--r-- | tools/test_srcipts/libusb_winusb_device_for_speed.c | 1 |
19 files changed, 330 insertions, 97 deletions
diff --git a/class/adb/usbd_adb_sync.c b/class/adb/usbd_adb_sync.c index b18e2b09..9ab0a95b 100644 --- a/class/adb/usbd_adb_sync.c +++ b/class/adb/usbd_adb_sync.c @@ -234,36 +234,28 @@ static bool adb_sync_name_is_dir(const char *path) * "/sdc/.\output/...". FatFs takes both separators alike, so the backslashes * are folded into forward ones before any component is looked at - otherwise * ".\output" stays a single, unmakable name and the push dies on the first - * file. The checks above run first, so this never turns a relative path into - * something that looks absolute. */ -static bool adb_sync_build_full_path(const char *root, char *path, bool *wants_dir) + * file. After folding separators, the path must start with '/'. */ +static bool adb_sync_build_full_path(char *path, bool *wants_dir) { char *dst0; char *dst; char *src; size_t len; - size_t root_len; size_t i; *wants_dir = false; - root_len = strlen(root); len = strlen(path); - if ((root_len == 0u) || (len < root_len) || (strncmp(path, root, root_len) != 0)) { - return false; - } - - if ((len > root_len) && (root[root_len - 1u] != '/') && (path[root_len] != '/')) { - return false; - } - for (i = 0u; i < len; i++) { if (path[i] == '\\') { path[i] = '/'; } } + if (path[0] != '/') { + return false; + } *wants_dir = (len > 1u) && (path[len - 1u] == '/'); dst0 = path; @@ -754,9 +746,8 @@ static void adb_sync_dispatch(uint32_t id, char *body) len = strlen(body); memcpy(g_adb_sync.path, body, len + 1u); - if (adb_sync_build_full_path(vfs_get_fs_root_path(), g_adb_sync.path, &wants_dir) == false) { - adb_sync_fail("the path has to be absolute, starting with '%s', not '%s'", - vfs_get_fs_root_path(), g_adb_sync.path); + if (adb_sync_build_full_path(g_adb_sync.path, &wants_dir) == false) { + adb_sync_fail("the path has to be absolute, starting with '/', not '%s'", g_adb_sync.path); return; } diff --git a/class/audio/usbh_audio.c b/class/audio/usbh_audio.c index 5ef08c90..3fcae863 100644 --- a/class/audio/usbh_audio.c +++ b/class/audio/usbh_audio.c @@ -672,6 +672,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) case USB_DESCRIPTOR_TYPE_ENDPOINT: if (cur_iface == audio_class->ctrl_intf) { } else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) { + if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) { + return -USB_ERR_INVAL; + } struct usb_endpoint_descriptor *ep_desc = (struct usb_endpoint_descriptor *)p; if (ep_desc->bEndpointAddress & 0x80) { audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].is_tx = false; @@ -702,6 +705,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) break; } } else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) { + if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) { + return -USB_ERR_INVAL; + } switch (p[DESC_bDescriptorSubType]) { case AUDIO_STREAMING_GENERAL: { struct audio_cs_if_as_general_descriptor *desc = (struct audio_cs_if_as_general_descriptor *)p; @@ -727,6 +733,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) break; case AUDIO_ENDPOINT_DESCRIPTOR_TYPE: if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) { + if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) { + return -USB_ERR_INVAL; + } if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) { struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p; diff --git a/class/cdc/usbh_cdc_ncm.c b/class/cdc/usbh_cdc_ncm.c index 83310e09..04e330b8 100644 --- a/class/cdc/usbh_cdc_ncm.c +++ b/class/cdc/usbh_cdc_ncm.c @@ -296,6 +296,9 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) if (g_cdc_ncm_rx_length < CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) { USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length); + if (g_cdc_ncm_rx_length < sizeof(struct cdc_ncm_nth16)) { + continue; + } struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0]; if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) || (nth16->wHeaderLength != 12) || @@ -305,6 +308,12 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) continue; } + if (nth16->wNdpIndex < sizeof(struct cdc_ncm_nth16) || + (nth16->wNdpIndex & 3) || + nth16->wNdpIndex > g_cdc_ncm_rx_length - sizeof(struct cdc_ncm_ndp16)) { + USB_LOG_ERR("invalid rx ndp16 index\r\n"); + continue; + } struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex]; if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) { USB_LOG_ERR("invalid rx ndp16\r\n"); @@ -312,17 +321,31 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) continue; } + if (ndp16->wLength < sizeof(struct cdc_ncm_ndp16) + sizeof(struct cdc_ncm_ndp16_datagram) || + (ndp16->wLength & 3) || + ndp16->wLength > g_cdc_ncm_rx_length - nth16->wNdpIndex) { + USB_LOG_ERR("invalid rx ndp16 length\r\n"); + continue; + } uint16_t datagram_num = (ndp16->wLength - 8) / 4; USB_LOG_DBG("datagram num:%02x\r\n", datagram_num); for (uint16_t i = 0; i < datagram_num; i++) { struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i]; - if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) { - USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength); - - uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex]; - usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength); + if (!ndp16_datagram->wDatagramIndex && !ndp16_datagram->wDatagramLength) { + break; } + if (ndp16_datagram->wDatagramIndex < sizeof(struct cdc_ncm_nth16) || + ndp16_datagram->wDatagramIndex > g_cdc_ncm_rx_length || + !ndp16_datagram->wDatagramLength || + ndp16_datagram->wDatagramLength > g_cdc_ncm_rx_length - ndp16_datagram->wDatagramIndex) { + USB_LOG_ERR("invalid rx datagram range\r\n"); + break; + } + USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength); + + uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex]; + usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength); } g_cdc_ncm_rx_length = 0; diff --git a/class/msc/usbd_msc.c b/class/msc/usbd_msc.c index d21051f0..cd3fc4f7 100644 --- a/class/msc/usbd_msc.c +++ b/class/msc/usbd_msc.c @@ -538,6 +538,26 @@ static bool SCSI_readCapacity16(uint8_t busid, uint8_t **data, uint32_t *len) return true; } +/* Check the range before adding LBAs or multiplying the transfer size. */ +static bool SCSI_checkReadWriteRange(uint8_t busid) +{ + uint8_t lun = g_usbd_msc[busid].cbw.bLUN; + uint32_t capacity = g_usbd_msc[busid].scsi_blk_nbr[lun]; + uint32_t block_size = g_usbd_msc[busid].scsi_blk_size[lun]; + + if (g_usbd_msc[busid].start_sector >= capacity || + g_usbd_msc[busid].nsectors > capacity - g_usbd_msc[busid].start_sector) { + SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + return false; + } + if (block_size == 0 || g_usbd_msc[busid].nsectors == 0 || + g_usbd_msc[busid].nsectors > UINT32_MAX / block_size) { + SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA); + return false; + } + return true; +} + static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len) { (void)data; @@ -551,8 +571,7 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */ - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { - SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + if (!SCSI_checkReadWriteRange(busid)) { return false; } @@ -584,8 +603,7 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */ - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { - SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE); + if (!SCSI_checkReadWriteRange(busid)) { return false; } @@ -619,10 +637,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */ - data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { + if (!SCSI_checkReadWriteRange(busid)) { return false; } + data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; if (g_usbd_msc[busid].cbw.dDataLength != data_len) { return false; @@ -648,10 +666,10 @@ static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len) g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */ g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */ - data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; - if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) { + if (!SCSI_checkReadWriteRange(busid)) { return false; } + data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]; if (g_usbd_msc[busid].cbw.dDataLength != data_len) { return false; @@ -736,6 +754,9 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes) if ((g_usbd_msc[busid].cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc[busid].cbw.bCBLength < 1) || (g_usbd_msc[busid].cbw.bCBLength > 16)) { SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND); return false; + } else if (g_usbd_msc[busid].cbw.bLUN > g_usbd_msc[busid].max_lun) { + SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDLUN); + return false; } else { USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]); switch (g_usbd_msc[busid].cbw.CB[0]) { diff --git a/class/tmc/usbd_tmc.c b/class/tmc/usbd_tmc.c index 7f351e99..e3d9a0fc 100644 --- a/class/tmc/usbd_tmc.c +++ b/class/tmc/usbd_tmc.c @@ -166,13 +166,23 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) struct tmc_bulk_header *out_header = (struct tmc_bulk_header *)tmc_read_buffer; struct tmc_bulk_header *in_header = (struct tmc_bulk_header *)tmc_write_buffer; + if (g_tmc_read_offset > sizeof(tmc_read_buffer) || + nbytes > sizeof(tmc_read_buffer) - g_tmc_read_offset) { + goto reset_read; + } g_tmc_read_offset += nbytes; if (g_tmc_read_total == 0) { - USB_ASSERT_MSG(nbytes >= sizeof(struct tmc_bulk_header), "tmc header size error\r\n"); + if (nbytes < sizeof(struct tmc_bulk_header)) { + goto reset_read; + } switch (out_header->MsgID) { case TMC_MSGID_OUT_DEV_DEP_MSG_OUT: + if (out_header->msg_specific.dev_dep_msg_out.transferSize > + ((sizeof(tmc_read_buffer) - sizeof(struct tmc_bulk_header)) & ~3u)) { + goto reset_read; + } g_tmc_read_total = ((out_header->msg_specific.dev_dep_msg_out.transferSize + 3u) & ~3u) + sizeof(struct tmc_bulk_header); break; case TMC_MSGID_OUT_REQUEST_DEV_DEP_MSG_IN: @@ -182,9 +192,14 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) USB_LOG_WRN("Unhandled TMC MsgID 0x%02x\r\n", out_header->MsgID); break; } - USB_ASSERT_MSG(g_tmc_read_total <= CONFIG_USBDEV_TMC_MAX_BUFSIZE, "tmc read buffer overflow\r\n"); + if (g_tmc_read_total == 0 || g_tmc_read_total > sizeof(tmc_read_buffer)) { + goto reset_read; + } } + if (g_tmc_read_offset > g_tmc_read_total) { + goto reset_read; + } if (g_tmc_read_offset < g_tmc_read_total) { usbd_ep_start_read(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr, tmc_read_buffer + g_tmc_read_offset, usbd_get_ep_mps(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr)); return; @@ -194,7 +209,7 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) case TMC_MSGID_OUT_DEV_DEP_MSG_OUT: SCPI_Input(&scpi_context, (const char *)(tmc_read_buffer + sizeof(struct tmc_bulk_header)), - g_tmc_read_total); + out_header->msg_specific.dev_dep_msg_out.transferSize); break; case TMC_MSGID_OUT_REQUEST_DEV_DEP_MSG_IN: @@ -211,6 +226,7 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) break; } +reset_read: g_tmc_read_offset = 0; g_tmc_read_total = 0; usbd_ep_start_read(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr, tmc_read_buffer + g_tmc_read_offset, usbd_get_ep_mps(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr)); diff --git a/class/vendor/net/usbh_asix.c b/class/vendor/net/usbh_asix.c index e63b274b..706b5c9c 100644 --- a/class/vendor/net/usbh_asix.c +++ b/class/vendor/net/usbh_asix.c @@ -718,10 +718,13 @@ void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) data_offset = 0; while (g_asix_rx_length > 0) { + if (g_asix_rx_length < 4) { + break; + } len = ((uint16_t)g_asix_rx_buffer[data_offset + 0] | ((uint16_t)(g_asix_rx_buffer[data_offset + 1]) << 8)) & 0x7ff; len_crc = g_asix_rx_buffer[data_offset + 2] | ((uint16_t)(g_asix_rx_buffer[data_offset + 3]) << 8); - if (len != (~len_crc & 0x7ff)) { + if (len != (~len_crc & 0x7ff) || len == 0 || (len > g_asix_rx_length - 4)) { USB_LOG_ERR("rx header error\r\n"); g_asix_rx_length = 0; continue; @@ -732,8 +735,9 @@ void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) g_asix_rx_length -= (len + 4); data_offset += (len + 4); - if (g_asix_rx_length < 4) { - g_asix_rx_length = 0; + if ((len & 1) && g_asix_rx_length > 0) { + g_asix_rx_length--; + data_offset++; } } } else { diff --git a/class/vendor/net/usbh_rtl8152.c b/class/vendor/net/usbh_rtl8152.c index 16393ab1..df5f3d3b 100644 --- a/class/vendor/net/usbh_rtl8152.c +++ b/class/vendor/net/usbh_rtl8152.c @@ -2186,9 +2186,16 @@ void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) USB_LOG_DBG("rxlen:%d\r\n", g_rtl8152_rx_length); while (g_rtl8152_rx_length > 0) { + if (g_rtl8152_rx_length < sizeof(struct rx_desc)) { + break; + } struct rx_desc *rx_desc = (struct rx_desc *)&g_rtl8152_rx_buffer[data_offset]; len = rx_desc->opts1 & RX_LEN_MASK; + if (len == 0 || len > g_rtl8152_rx_length - sizeof(struct rx_desc)) { + USB_LOG_ERR("invalid rtl8152 rx length\r\n"); + break; + } USB_LOG_DBG("data_offset:%d, eth len:%d\r\n", data_offset, len); @@ -2199,8 +2206,12 @@ void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) g_rtl8152_rx_length -= (len + sizeof(struct rx_desc)); if (len & (RX_ALIGN - 1)) { - data_offset += (RX_ALIGN - (len & (RX_ALIGN - 1))); - g_rtl8152_rx_length -= (RX_ALIGN - (len & (RX_ALIGN - 1))); + uint32_t padding = RX_ALIGN - (len & (RX_ALIGN - 1)); + if (padding > g_rtl8152_rx_length) { + break; + } + data_offset += padding; + g_rtl8152_rx_length -= padding; } } } else { diff --git a/class/video/usbh_video.c b/class/video/usbh_video.c index 8e782e20..2c479740 100644 --- a/class/video/usbh_video.c +++ b/class/video/usbh_video.c @@ -367,7 +367,8 @@ void usbh_video_list_info(struct usbh_video *video_class) USB_LOG_RAW(" wWidth: %d, wHeight: %d, fps: %d\r\n", video_class->format[i].frame[j].wWidth, video_class->format[i].frame[j].wHeight, - (1000 / (video_class->format[i].frame[j].dwDefaultFrameInterval / 10000))); + (video_class->format[i].frame[j].dwDefaultFrameInterval ? + 10000000U / video_class->format[i].frame[j].dwDefaultFrameInterval : 0U)); } } @@ -418,6 +419,9 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) if (cur_iface == video_class->ctrl_intf) { switch (p[DESC_bDescriptorSubType]) { case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < 5) { + return -USB_ERR_INVAL; + } video_class->bcdVDC = ((uint16_t)p[4] << 8) | (uint16_t)p[3]; break; case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE: @@ -433,11 +437,22 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) } else if (cur_iface == video_class->data_intf) { switch (p[DESC_bDescriptorSubType]) { case VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < 4 || p[DESC_bNumFormats] == 0 || + p[DESC_bNumFormats] > CONFIG_USBHOST_VIDEO_MAX_FORMATS) { + return -USB_ERR_INVAL; + } video_class->num_of_formats = p[DESC_bNumFormats]; break; case VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < 5) { + return -USB_ERR_INVAL; + } format_index = p[DESC_bFormatIndex]; num_of_frames = p[DESC_bNumFrameDescriptors]; + if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS || + num_of_frames == 0 || num_of_frames > CONFIG_USBHOST_VIDEO_MAX_FRAMES) { + return -USB_ERR_INVAL; + } USB_ASSERT(format_index != 0); USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS); @@ -446,8 +461,15 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_UNCOMPRESSED; break; case VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < 5) { + return -USB_ERR_INVAL; + } format_index = p[DESC_bFormatIndex]; num_of_frames = p[DESC_bNumFrameDescriptors]; + if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS || + num_of_frames == 0 || num_of_frames > CONFIG_USBHOST_VIDEO_MAX_FRAMES) { + return -USB_ERR_INVAL; + } USB_ASSERT(format_index != 0); USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS); @@ -456,7 +478,16 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_MJPEG; break; case VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < sizeof(struct video_cs_if_vs_frame_uncompressed_descriptor)) { + return -USB_ERR_INVAL; + } frame_index = p[DESC_bFrameIndex]; + if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS || + frame_index == 0 || frame_index > CONFIG_USBHOST_VIDEO_MAX_FRAMES || + frame_index > video_class->format[format_index - 1].num_of_frames || + ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval == 0) { + return -USB_ERR_INVAL; + } USB_ASSERT(format_index != 0); USB_ASSERT(frame_index != 0); @@ -468,7 +499,16 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval; break; case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE: + if (p[DESC_bLength] < sizeof(struct video_cs_if_vs_frame_mjpeg_descriptor)) { + return -USB_ERR_INVAL; + } frame_index = p[DESC_bFrameIndex]; + if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS || + frame_index == 0 || frame_index > CONFIG_USBHOST_VIDEO_MAX_FRAMES || + frame_index > video_class->format[format_index - 1].num_of_frames || + ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->dwDefaultFrameInterval == 0) { + return -USB_ERR_INVAL; + } USB_ASSERT(format_index != 0); USB_ASSERT(frame_index != 0); diff --git a/class/wireless/usbd_rndis.c b/class/wireless/usbd_rndis.c index ea62c50e..08366250 100644 --- a/class/wireless/usbd_rndis.c +++ b/class/wireless/usbd_rndis.c @@ -477,8 +477,18 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) (void)busid; (void)ep; + if (nbytes < sizeof(rndis_data_packet_t)) { + usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length); + return; + } + hdr = (rndis_data_packet_t *)g_rndis_rx_data_buffer; - if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) { + if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || + (hdr->MessageLength < sizeof(rndis_data_packet_t)) || + (hdr->MessageLength > nbytes) || + (hdr->DataOffset < sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t)) || + (hdr->DataOffset > hdr->MessageLength - sizeof(rndis_generic_msg_t)) || + (hdr->DataLength > hdr->MessageLength - sizeof(rndis_generic_msg_t) - hdr->DataOffset)) { usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length); return; } @@ -555,6 +565,7 @@ struct pbuf *usbd_rndis_eth_rx(void) usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer)); return NULL; } + usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length); p->len = g_rndis_rx_data_length; diff --git a/class/wireless/usbh_rndis.c b/class/wireless/usbh_rndis.c index 22f0e369..d6354d5a 100644 --- a/class/wireless/usbh_rndis.c +++ b/class/wireless/usbh_rndis.c @@ -544,6 +544,9 @@ void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) while (g_rndis_rx_length > 0) { USB_LOG_DBG("rxlen:%u\r\n", (unsigned int)g_rndis_rx_length); + if (g_rndis_rx_length < sizeof(rndis_data_packet_t)) { + break; + } pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset); /* Not word-aligned case */ @@ -552,7 +555,12 @@ void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) pmsg = &temp; } - if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) { + if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG && + pmsg->MessageLength >= sizeof(rndis_data_packet_t) && + pmsg->MessageLength <= g_rndis_rx_length && + pmsg->DataOffset >= sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t) && + pmsg->DataOffset <= pmsg->MessageLength - sizeof(rndis_generic_msg_t) && + pmsg->DataLength <= pmsg->MessageLength - sizeof(rndis_generic_msg_t) - pmsg->DataOffset) { uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset); usbh_rndis_eth_input(buf, pmsg->DataLength); diff --git a/common/usb_def.h b/common/usb_def.h index 73d2b800..cf0cb089 100644 --- a/common/usb_def.h +++ b/common/usb_def.h @@ -513,6 +513,7 @@ struct usb_msosv1_descriptor { uint8_t vendor_code; const uint8_t *compat_id; const uint8_t **comp_id_property; + uint16_t comp_id_property_count; /* Number of entries; zero disables property requests. */ }; /* MS OS 2.0 Header descriptor */ diff --git a/common/usb_log.h b/common/usb_log.h index ca03af5b..a1bc501c 100644 --- a/common/usb_log.h +++ b/common/usb_log.h @@ -95,8 +95,21 @@ } \ } while (false) #else -#define USB_ASSERT(f) {} -#define USB_ASSERT_MSG(f, fmt, ...) {} +#define USB_ASSERT(f) \ + do { \ + if (!(f)) { \ + while (1) { \ + } \ + } \ + } while (false) + +#define USB_ASSERT_MSG(f, fmt, ...) \ + do { \ + if (!(f)) { \ + while (1) { \ + } \ + } \ + } while (false) #endif #define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') diff --git a/core/usbd_core.c b/core/usbd_core.c index b023fefc..c7850e67 100644 --- a/core/usbd_core.c +++ b/core/usbd_core.c @@ -29,6 +29,9 @@ #define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */ #define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */ +#define CONFIG_USBDEV_MAX_EPS 16 +#define CONFIG_USBDEV_MAX_INTERFACES 16 + struct usbd_tx_rx_msg { uint8_t ep; uint8_t ep_type; @@ -78,12 +81,12 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv { usb_osal_mq_t usbd_ep0_mq; usb_osal_thread_t usbd_ep0_thread; #endif - struct usbd_interface *intf[16]; - uint8_t intf_altsetting[16]; + struct usbd_interface *intf[CONFIG_USBDEV_MAX_INTERFACES]; + uint8_t intf_altsetting[CONFIG_USBDEV_MAX_INTERFACES]; uint8_t intf_offset; - struct usbd_tx_rx_msg tx_msg[16]; - struct usbd_tx_rx_msg rx_msg[16]; + struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_MAX_EPS]; + struct usbd_tx_rx_msg rx_msg[CONFIG_USBDEV_MAX_EPS]; void (*event_handler)(uint8_t busid, uint8_t event); } g_usbd_core[CONFIG_USBDEV_MAX_BUS]; @@ -532,13 +535,19 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting break; case USB_DESCRIPTOR_TYPE_ENDPOINT: - if (cur_iface == iface) { + if (cur_iface == iface && if_desc != NULL) { ep_desc = (struct usb_endpoint_descriptor *)p; if (alt_setting == 0) { ret = usbd_reset_endpoint(busid, ep_desc); + if (ret == false) { + return ret; + } } else if (cur_alt_setting == alt_setting) { ret = usbd_set_endpoint(busid, ep_desc); + if (ret == false) { + return ret; + } if (g_usbd_core[busid].speed >= USB_SPEED_SUPER) { const uint8_t *ep_comp_desc; @@ -570,7 +579,9 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting } } - usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc); + if (if_desc) { + usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc); + } return ret; } @@ -687,9 +698,11 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet * ret = false; break; case USB_REQUEST_SET_SEL: + *len = 0; break; case USB_REQUEST_SET_ISOCH_DLY: g_usbd_core[busid].isoch_delay = value; + *len = 0; break; default: @@ -720,6 +733,10 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe uint32_t current_desc_len = 0; uint8_t cur_iface = 0xFF; + if (intf_num >= g_usbd_core[busid].intf_offset) { + return false; + } + p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed); /* Only when device is configured, then interface requests can be valid. */ @@ -791,8 +808,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe break; case USB_REQUEST_SET_INTERFACE: + ret = usbd_set_interface(busid, intf_num, setup->wValue); + if (ret == false) { + break; + } g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue); - usbd_set_interface(busid, setup->wIndex, setup->wValue); + *len = 0; break; @@ -825,6 +846,10 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet return false; } + if ((ep & 0x7f) >= CONFIG_USBDEV_MAX_EPS) { + return false; + } + switch (setup->bRequest) { case USB_REQUEST_GET_STATUS: usbd_ep_is_stalled(busid, ep, &stalled); @@ -963,21 +988,19 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s if (setup->bRequest == g_usbd_core[busid].descriptors->msosv1_descriptor->vendor_code) { switch (setup->wIndex) { case 0x04: - desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[0] + - (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[1] << 8) + - (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[2] << 16) + - (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[3] << 24); - + desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id); *data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id; //memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id, desclen); *len = desclen; return 0; case 0x05: - desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][0] + - (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][1] << 8) + - (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][2] << 16) + - (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][3] << 24); + if (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property == NULL || + setup->wValue >= g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property_count || + g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue] == NULL) { + return -1; + } + desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue]); *data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue]; //memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen); *len = desclen; @@ -1367,6 +1390,8 @@ void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc) void usbd_add_interface(uint8_t busid, struct usbd_interface *intf) { + USB_ASSERT_MSG(g_usbd_core[busid].intf_offset < CONFIG_USBDEV_MAX_INTERFACES, "Too many interfaces\r\n"); + intf->intf_num = g_usbd_core[busid].intf_offset; g_usbd_core[busid].intf[g_usbd_core[busid].intf_offset] = intf; g_usbd_core[busid].intf_offset++; diff --git a/core/usbh_core.c b/core/usbh_core.c index ba00d8f8..0457a7c5 100644 --- a/core/usbh_core.c +++ b/core/usbh_core.c @@ -27,6 +27,7 @@ struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS]; #define DESC_bLength 0 /** Length offset */ #define DESC_bDescriptorType 1 /** Descriptor type offset */ +#define USB_DEV_ADDR_MIN 2 #define USB_DEV_ADDR_MAX 0x7f #define USB_DEV_ADDR_MARK_OFFSET 5 #define USB_DEV_ADDR_MARK_MASK 0x1f @@ -43,17 +44,19 @@ static void dummy_event_handler(uint8_t busid, uint8_t hub_index, uint8_t hub_po static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen) { uint8_t lastaddr = devgen->last; - uint8_t devaddr = lastaddr; + uint8_t devaddr; int index; int bitno; + if (lastaddr < USB_DEV_ADDR_MIN || lastaddr > USB_DEV_ADDR_MAX) { + lastaddr = USB_DEV_ADDR_MAX; + } + devaddr = lastaddr; + for (;;) { devaddr++; - if (devaddr > 0x7f) { - devaddr = 2; - } - if (devaddr == lastaddr) { - return -USB_ERR_NOMEM; + if (devaddr > USB_DEV_ADDR_MAX) { + devaddr = USB_DEV_ADDR_MIN; } index = devaddr >> 5; @@ -63,6 +66,10 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen) devgen->last = devaddr; return (int)devaddr; } + + if (devaddr == lastaddr) { + return -USB_ERR_NOMEM; + } } } @@ -71,7 +78,7 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr) int index; int bitno; - if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) { + if ((devaddr > 0) && (devaddr <= USB_DEV_ADDR_MAX)) { index = devaddr >> USB_DEV_ADDR_MARK_OFFSET; bitno = devaddr & USB_DEV_ADDR_MARK_MASK; @@ -132,6 +139,10 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length) { + if (length < 8) { + return -USB_ERR_INVAL; + } + if (desc->bLength != USB_SIZEOF_DEVICE_DESC) { USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength); return -USB_ERR_INVAL; @@ -139,6 +150,16 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType); return -USB_ERR_INVAL; } else { + if ((hport->speed >= USB_SPEED_SUPER && desc->bMaxPacketSize0 != 9) || + (hport->speed == USB_SPEED_HIGH && desc->bMaxPacketSize0 != 64) || + (hport->speed == USB_SPEED_LOW && desc->bMaxPacketSize0 != 8) || + (hport->speed == USB_SPEED_FULL && + desc->bMaxPacketSize0 != 8 && desc->bMaxPacketSize0 != 16 && + desc->bMaxPacketSize0 != 32 && desc->bMaxPacketSize0 != 64)) { + USB_LOG_ERR("invalid bMaxPacketSize0 %d\r\n", desc->bMaxPacketSize0); + return -USB_ERR_INVAL; + } + if (length <= 8) { return 0; } @@ -188,6 +209,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config uint32_t desc_len = 0; uint8_t *p; + if (length < USB_SIZEOF_CONFIG_DESC) { + return -USB_ERR_INVAL; + } if (desc->bLength != USB_SIZEOF_CONFIG_DESC) { USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength); return -USB_ERR_INVAL; @@ -195,9 +219,17 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType); return -USB_ERR_INVAL; } else { + if (desc->bNumInterfaces > CONFIG_USBHOST_MAX_INTERFACES) { + return -USB_ERR_NOMEM; + } + if (length <= USB_SIZEOF_CONFIG_DESC) { return 0; } + + if (desc->wTotalLength != length) { + return -USB_ERR_INVAL; + } #if 0 USB_LOG_DBG("Config Descriptor:\r\n"); USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength); @@ -225,9 +257,14 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES); - while (p[DESC_bLength]) { + while ((desc_len < length) && + (p[DESC_bLength] >= 2) && + (p[DESC_bLength] <= length - desc_len)) { switch (p[DESC_bDescriptorType]) { case USB_DESCRIPTOR_TYPE_INTERFACE: + if (cur_ep != cur_ep_num) { + return -USB_ERR_INVAL; + } if (p[DESC_bLength] < USB_SIZEOF_INTERFACE_DESC) { return -USB_ERR_INVAL; } @@ -242,16 +279,19 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config return -USB_ERR_NOMEM; } - if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) { - USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num); + if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) { + USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting); return -USB_ERR_NOMEM; } - if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) { - USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting); + if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) { + USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num); return -USB_ERR_NOMEM; } + if (cur_alt_setting != hport->config.intf[cur_iface].altsetting_num) { + return -USB_ERR_INVAL; + } #if 0 USB_LOG_DBG("Interface Descriptor:\r\n"); USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength); @@ -264,8 +304,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol); USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface); #endif - memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9); - hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1; + + memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, USB_SIZEOF_INTERFACE_DESC); + hport->config.intf[cur_iface].altsetting_num++; break; case USB_DESCRIPTOR_TYPE_ENDPOINT: if (p[DESC_bLength] < USB_SIZEOF_ENDPOINT_DESC) { @@ -273,12 +314,29 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config } ep_desc = (struct usb_endpoint_descriptor *)p; - if (cur_ep >= CONFIG_USBHOST_MAX_ENDPOINTS) { + if (USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize) == 0) { + return -USB_ERR_INVAL; + } + + if ((ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT || + (ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS) { + if (ep_desc->bInterval == 0 || + (hport->speed >= USB_SPEED_HIGH && ep_desc->bInterval > 16)) { + return -USB_ERR_INVAL; + } + } + + if (cur_iface >= CONFIG_USBHOST_MAX_INTERFACES) { + USB_LOG_ERR("Interface num %d overflow\r\n", cur_iface); + return -USB_ERR_NOMEM; + } + + if (cur_ep >= cur_ep_num) { USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep); return -USB_ERR_NOMEM; } - memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7); + memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, USB_SIZEOF_ENDPOINT_DESC); cur_ep++; break; @@ -288,10 +346,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config /* skip to next descriptor */ desc_len += p[DESC_bLength]; p += p[DESC_bLength]; + } - if (desc_len > length) { - return -USB_ERR_INVAL; - } + if (cur_ep != cur_ep_num) { + return -USB_ERR_INVAL; } if (desc_len != length) { @@ -379,8 +437,8 @@ int usbh_enumerate(struct usbh_hubport *hport) /* Extract the correct max packetsize from the device descriptor */ dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid]; - if (dev_desc->bcdUSB >= USB_3_0) { - ep_mps = 1 << dev_desc->bMaxPacketSize0; + if (hport->speed >= USB_SPEED_SUPER) { + ep_mps = 1U << dev_desc->bMaxPacketSize0; } else { ep_mps = dev_desc->bMaxPacketSize0; } @@ -395,6 +453,7 @@ int usbh_enumerate(struct usbh_hubport *hport) /* Assign a function address to the device connected to this port */ dev_addr = usbh_allocate_devaddr(&hport->bus->devgen); if (dev_addr < 0) { + ret = dev_addr; USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret); goto errout; } @@ -409,6 +468,7 @@ int usbh_enumerate(struct usbh_hubport *hport) ret = usbh_control_transfer(hport, setup, NULL); if (ret < 0) { USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret); + __usbh_free_devaddr(&hport->bus->devgen, (uint8_t)dev_addr); goto errout; } @@ -431,7 +491,12 @@ int usbh_enumerate(struct usbh_hubport *hport) goto errout; } - parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC); + ret = parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC); + if (ret < 0) { + USB_LOG_ERR("Parse full device descriptor fail\r\n"); + goto errout; + } + USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n", ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor, ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct, @@ -748,17 +813,14 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out struct usb_setup_packet *setup = hport->setup; int ret; uint8_t *src; - uint8_t *dst; uint16_t len; - uint16_t i = 2; - uint16_t j = 0; /* Get Manufacturer string */ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index); setup->wIndex = 0x0409; - setup->wLength = 255; + setup->wLength = MIN(255, CONFIG_USBHOST_REQUEST_BUFFER_LEN); ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]); if (ret < 0) { @@ -766,26 +828,19 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out } src = ep0_request_buffer[hport->bus->busid]; - dst = output; - len = src[0]; - - if (ret != len) { - USB_LOG_ERR("Get string descriptor failed, expect %d, actual %d\r\n", len, ret); + if (ret < 2 || src[1] != USB_DESCRIPTOR_TYPE_STRING || src[0] != ret || (src[0] & 1)) { return -USB_ERR_IO; } - memset(output, 0, output_len); - - if (((len - 2) / 2) > output_len) { + len = (src[0] - 2) / 2; + if (len > output_len) { return -USB_ERR_NOMEM; } - while (i < len) { - dst[j] = src[i]; - i += 2; - j++; + memset(output, 0, output_len); + for (uint16_t i = 0; i < len; i++) { + output[i] = src[2 + 2 * i]; } - return 0; } diff --git a/demo/adb_template.c b/demo/adb_template.c index 871d41a7..34715509 100644 --- a/demo/adb_template.c +++ b/demo/adb_template.c @@ -100,6 +100,7 @@ struct usb_msosv1_descriptor msosv1_desc = { .vendor_code = WCID_VENDOR_CODE, .compat_id = WINUSB_WCIDDescriptor, .comp_id_property = WINUSB_IFx_WCIDProperties, + .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]), }; static const uint8_t device_descriptor[] = { diff --git a/demo/gs_usb_template.c b/demo/gs_usb_template.c index b82c41c8..d6b533c1 100644 --- a/demo/gs_usb_template.c +++ b/demo/gs_usb_template.c @@ -74,6 +74,7 @@ struct usb_msosv1_descriptor linux_msosv1_desc = { .vendor_code = LINUX_USBD_GS_CAN_VENDOR_CODE, .compat_id = linux_WINUSB_WCIDDescriptor, .comp_id_property = linux_WINUSB_IFx_WCIDProperties, + .comp_id_property_count = sizeof(linux_WINUSB_IFx_WCIDProperties) / sizeof(linux_WINUSB_IFx_WCIDProperties[0]), }; static const uint8_t linux_device_descriptor[] = { diff --git a/demo/mtp_template.c b/demo/mtp_template.c index 11950d26..f42a3a57 100644 --- a/demo/mtp_template.c +++ b/demo/mtp_template.c @@ -194,6 +194,7 @@ struct usb_msosv1_descriptor msosv1_desc = { .vendor_code = WCID_VENDOR_CODE, .compat_id = WINUSB_WCIDDescriptor, .comp_id_property = WINUSB_IFx_WCIDProperties, + .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]), }; const struct usb_bos_descriptor bos_desc = { diff --git a/demo/winusb1.0_template.c b/demo/winusb1.0_template.c index 692bddc5..3fafe59e 100644 --- a/demo/winusb1.0_template.c +++ b/demo/winusb1.0_template.c @@ -106,6 +106,7 @@ struct usb_msosv1_descriptor msosv1_desc = { .vendor_code = WINUSB_VENDOR_CODE, .compat_id = WINUSB_WCIDDescriptor, .comp_id_property = WINUSB_IFx_WCIDProperties, + .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]), }; #define WINUSB_IN_EP 0x81 diff --git a/tools/test_srcipts/libusb_winusb_device_for_speed.c b/tools/test_srcipts/libusb_winusb_device_for_speed.c index bcd02a03..d3ed01a5 100644 --- a/tools/test_srcipts/libusb_winusb_device_for_speed.c +++ b/tools/test_srcipts/libusb_winusb_device_for_speed.c @@ -72,6 +72,7 @@ struct usb_msosv1_descriptor msosv1_desc = { .vendor_code = WCID_VENDOR_CODE, .compat_id = WINUSB_WCIDDescriptor, .comp_id_property = WINUSB_IFx_WCIDProperties, + .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]), }; static const uint8_t device_descriptor[] = { |
