mirror of
https://github.com/espressif/esp-lwip.git
synced 2026-09-13 04:30:09 +00:00
tcp/ooseq: do not accept empty fin seg
This commit is contained in:
+15
-5
@@ -1601,16 +1601,24 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
seqno = pcb->ooseq->tcphdr->seqno;
|
||||
#if ESP_LWIP
|
||||
if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
|
||||
struct tcp_seg trimmed = *cseg;
|
||||
trimmed.len = (u16_t)pcb->rcv_wnd;
|
||||
if((TCPH_FLAGS((cseg)->tcphdr) & TCP_SYN) || (TCPH_FLAGS((cseg)->tcphdr) & TCP_FIN)) {
|
||||
if (trimmed.len > 0) {
|
||||
trimmed.len--;
|
||||
}
|
||||
}
|
||||
if (pcb->rcv_wnd < TCP_TCPLEN(&trimmed)) {
|
||||
/* Cannot accept this segment yet (e.g. FIN/SYN with zero window) */
|
||||
break;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: OOSEQ packet out of wnd "
|
||||
"seqno=%"U32_F" wnd =%"TCPWNDSIZE_F" len=%"U16_F
|
||||
"snd_wl1=%"U32_F" snd_wl2 =%"U32_F" f = %"X16_F" tf=%"U16_F"\n",
|
||||
seqno,pcb->rcv_wnd,cseg->len,pcb->snd_wl1,pcb->snd_wl1,
|
||||
TCPH_FLAGS((cseg)->tcphdr),pcb->flags));
|
||||
cseg->len = pcb->rcv_wnd;
|
||||
if((TCPH_FLAGS((cseg)->tcphdr) & TCP_SYN) || (TCPH_FLAGS((cseg)->tcphdr) & TCP_FIN)) {
|
||||
cseg->len -= 1;
|
||||
}
|
||||
cseg->len = trimmed.len;
|
||||
pbuf_realloc(cseg->p, cseg->len);
|
||||
tcp_segs_free(cseg->next);
|
||||
cseg->next = NULL;
|
||||
@@ -1828,7 +1836,9 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
"snd_wl1=%"U32_F" snd_wl2 =%"U32_F" f = %"X16_F" tf=%"U16_F"\n",
|
||||
seqno,pcb->rcv_wnd,next->next->len,pcb->snd_wl1,pcb->snd_wl1,
|
||||
TCPH_FLAGS(next->next->tcphdr),pcb->flags));
|
||||
next->next->len -= 1;
|
||||
if (next->next->len > 0) {
|
||||
next->next->len -= 1;
|
||||
}
|
||||
}
|
||||
#endif /* ESP_LWIP */
|
||||
pbuf_realloc(next->next->p, next->next->len);
|
||||
|
||||
@@ -985,6 +985,62 @@ FIN_TEST(test_tcp_recv_ooseq_double_FIN_13, 13)
|
||||
FIN_TEST(test_tcp_recv_ooseq_double_FIN_14, 14)
|
||||
FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15)
|
||||
|
||||
#if ESP_LWIP
|
||||
/** Drain OOSEQ FIN when rcv_wnd is zero after accepting in-sequence data.
|
||||
* Regression test for u16 underflow in ESP_LWIP OOSEQ window clamp (SEC-242). */
|
||||
START_TEST(test_tcp_recv_ooseq_fin_zero_rcv_wnd)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *pinseq, *p_fin_ooseq;
|
||||
struct netif netif;
|
||||
char data[4] = {1, 2, 3, 4};
|
||||
char fin_data = 5;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
test_tcp_init_netif(&netif, NULL, &test_local_ip, &test_netmask);
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
counters.expected_data_len = sizeof(data);
|
||||
counters.expected_data = data;
|
||||
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
|
||||
|
||||
/* One data byte + FIN at seq 4 (not mergeable when only seq 0..3 are in-sequence). */
|
||||
p_fin_ooseq = tcp_create_rx_segment(pcb, &fin_data, 1, 4, 0, TCP_ACK | TCP_FIN);
|
||||
EXPECT_RET(p_fin_ooseq != NULL);
|
||||
test_tcp_input(p_fin_ooseq, &netif);
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||
|
||||
/* Shrink window so in-sequence data exactly fills it. */
|
||||
pcb->rcv_wnd = 4;
|
||||
pcb->rcv_ann_wnd = 4;
|
||||
|
||||
pinseq = tcp_create_rx_segment(pcb, data, sizeof(data), 0, 0, TCP_ACK);
|
||||
EXPECT_RET(pinseq != NULL);
|
||||
test_tcp_input(pinseq, &netif);
|
||||
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == 4);
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(pcb->rcv_nxt == 4);
|
||||
EXPECT(pcb->rcv_wnd == 0);
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||
|
||||
/* Free pcb before return so teardown does not invoke err callback with a
|
||||
* stale pointer to stack-local counters (ASan stack-use-after-return). */
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
tcp_abort(pcb);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
}
|
||||
END_TEST
|
||||
#endif /* ESP_LWIP */
|
||||
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
@@ -1012,7 +1068,10 @@ tcp_oos_suite(void)
|
||||
TESTFUNC(test_tcp_recv_ooseq_double_FIN_12),
|
||||
TESTFUNC(test_tcp_recv_ooseq_double_FIN_13),
|
||||
TESTFUNC(test_tcp_recv_ooseq_double_FIN_14),
|
||||
TESTFUNC(test_tcp_recv_ooseq_double_FIN_15)
|
||||
TESTFUNC(test_tcp_recv_ooseq_double_FIN_15),
|
||||
#if ESP_LWIP
|
||||
TESTFUNC(test_tcp_recv_ooseq_fin_zero_rcv_wnd),
|
||||
#endif /* ESP_LWIP */
|
||||
};
|
||||
return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(testfunc), tcp_oos_setup, tcp_oos_teardown);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user