diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c index 4a132c97a8e..d5163068270 100644 --- a/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c @@ -1008,6 +1008,28 @@ TEST_CASE("esp32 l2tap - time stamping", "[ethernet]") TEST_ASSERT_EQUAL(exp_n, n); TEST_ASSERT_EQUAL(exp_sequence_id, ((test_eth_ptp_msg_t *)in_buffer)->ptp_msg.ptp_hdr.sequence_id); + ESP_LOGI(TAG, "Verify read IREC walk terminates when truncated record overlays a 0/0 timestamp"); + ts_info->type = L2TAP_IREC_TIME_STAMP; + ts_info->len = L2TAP_IREC_LEN(sizeof(struct timespec)); + test_ptp_msg.ptp_msg.ptp_hdr.sequence_id++; + exp_sequence_id++; + ptp_msg_ext_buff.buff = &test_ptp_msg; + ptp_msg_ext_buff.buff_len = sizeof(test_ptp_msg); + n = write(eth_tap_fd, &ptp_msg_ext_buff, 0); + TEST_ASSERT_EQUAL(sizeof(test_ptp_msg), n); + // 0/0 is an invalid timestamp. Reusing this IREC buffer with a truncated len makes + // L2TAP_IREC_NEXT land on tv_nsec==0 (a zero-length pseudo-header) and must not hang. + struct timespec *stale_ts = (struct timespec *)ts_info->data; + stale_ts->tv_sec = 0; + stale_ts->tv_nsec = 0; + ts_info->type = 0xFF; + ts_info->len = L2TAP_IREC_LEN(1); + ptp_msg_ext_buff.buff = in_buffer; + ptp_msg_ext_buff.buff_len = IN_BUFFER_SIZE; + n = read(eth_tap_fd, &ptp_msg_ext_buff, 0); + exp_n = sizeof(test_ptp_msg) < 60 ? 60 : sizeof(test_ptp_msg); + TEST_ASSERT_EQUAL(exp_n, n); + TEST_ASSERT_EQUAL(exp_sequence_id, ((test_eth_ptp_msg_t *)in_buffer)->ptp_msg.ptp_hdr.sequence_id); ESP_LOGI(TAG, "Verify response to invalid record len for read (first we need write correctly)"); ts_info->type = L2TAP_IREC_TIME_STAMP; diff --git a/components/esp_netif/vfs_l2tap/esp_vfs_l2tap.c b/components/esp_netif/vfs_l2tap/esp_vfs_l2tap.c index 003fb36d499..76c18107a99 100644 --- a/components/esp_netif/vfs_l2tap/esp_vfs_l2tap.c +++ b/components/esp_netif/vfs_l2tap/esp_vfs_l2tap.c @@ -183,11 +183,22 @@ static esp_err_t pop_rx_queue(l2tap_context_t *l2tap_socket, void *buff, size_t if (l2tap_socket->flags & L2TAP_FLAG_TS) { // find the record allocated for the time stamp info l2tap_irec_hdr_t *info_rec = L2TAP_IREC_FIRST(ext_buff); - while(info_rec != NULL) { + while (info_rec != NULL) { + /* rec->len is the NEXT stride. A truncated/invalid record (or leftover + * payload interpreted as a header) can have len < header size, */ + if (info_rec->len < sizeof(l2tap_irec_hdr_t)) { + info_rec = NULL; + break; + } if (info_rec->type == L2TAP_IREC_TIME_STAMP) { break; } - info_rec = L2TAP_IREC_NEXT(ext_buff, info_rec); + l2tap_irec_hdr_t *info_rec_next = L2TAP_IREC_NEXT(ext_buff, info_rec); + if (info_rec_next == NULL || (uint8_t *)info_rec_next <= (uint8_t *)info_rec) { + info_rec = NULL; + break; + } + info_rec = info_rec_next; } if (info_rec != NULL) { // check if there is enough space to store TS