diff options
| author | sakumisu <[email protected]> | 2026-10-22 12:41:45 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2026-10-22 17:14:30 +0800 |
| commit | d002406b9359af01fcfb601d88a2818b71856222 (patch) | |
| tree | 124b163bb743045ce7d16fc11500c39fb8c9f443 /class | |
| parent | 26b0feb09bb58ebb7a3161b5605f8e186b96db1f (diff) | |
fix(security): check array overflowdev
Signed-off-by: sakumisu <[email protected]>
Diffstat (limited to 'class')
| -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 |
10 files changed, 174 insertions, 40 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); |
