summaryrefslogtreecommitdiff
path: root/class
diff options
context:
space:
mode:
Diffstat (limited to 'class')
-rw-r--r--class/adb/usbd_adb_sync.c23
-rw-r--r--class/audio/usbh_audio.c9
-rw-r--r--class/cdc/usbh_cdc_ncm.c33
-rw-r--r--class/msc/usbd_msc.c37
-rw-r--r--class/tmc/usbd_tmc.c22
-rw-r--r--class/vendor/net/usbh_asix.c10
-rw-r--r--class/vendor/net/usbh_rtl8152.c15
-rw-r--r--class/video/usbh_video.c42
-rw-r--r--class/wireless/usbd_rndis.c13
-rw-r--r--class/wireless/usbh_rndis.c10
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);