Skip to content

Commit a82e562

Browse files
committed
Guard SYN enqueue state transitions
F/1777
1 parent 69e9a12 commit a82e562

3 files changed

Lines changed: 104 additions & 14 deletions

File tree

src/test/unit/unit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ Suite *wolf_suite(void)
253253
tcase_add_test(tc_utils, test_sock_connect_tcp_filter_drop);
254254
tcase_add_test(tc_utils, test_sock_connect_tcp_src_port_low);
255255
tcase_add_test(tc_utils, test_sock_connect_tcp_initial_seq_randomized);
256+
tcase_add_test(tc_utils, test_sock_connect_tcp_txbuf_full_does_not_enter_syn_sent);
256257
tcase_add_test(tc_utils, test_sock_sendto_more_error_paths);
257258
tcase_add_test(tc_utils, test_sock_sendto_udp_no_dest);
258259
tcase_add_test(tc_utils, test_sock_sendto_udp_sets_dest_and_assigns);
@@ -286,6 +287,7 @@ Suite *wolf_suite(void)
286287
tcase_add_test(tc_utils, test_sock_recvfrom_udp_payload_too_long);
287288
tcase_add_test(tc_utils, test_sock_recvfrom_icmp_payload_too_long);
288289
tcase_add_test(tc_utils, test_sock_accept_success);
290+
tcase_add_test(tc_utils, test_sock_accept_synack_rto_txbuf_full_does_not_consume_retry);
289291
tcase_add_test(tc_utils, test_sock_accept_ack_with_payload_completes_handshake);
290292
tcase_add_test(tc_utils, test_sock_accept_ack_at_snd_nxt_completes_handshake);
291293
tcase_add_test(tc_utils, test_sock_accept_ack_psh_with_payload_completes_handshake);

src/test/unit/unit_tests_api.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,38 @@ START_TEST(test_sock_connect_tcp_local_ip_from_primary)
19371937
}
19381938
END_TEST
19391939

1940+
START_TEST(test_sock_connect_tcp_txbuf_full_does_not_enter_syn_sent)
1941+
{
1942+
struct wolfIP s;
1943+
int tcp_sd;
1944+
struct tsocket *ts;
1945+
struct wolfIP_sockaddr_in sin;
1946+
uint8_t tiny_txbuf[32];
1947+
1948+
wolfIP_init(&s);
1949+
mock_link_init(&s);
1950+
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
1951+
1952+
tcp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
1953+
ck_assert_int_gt(tcp_sd, 0);
1954+
ts = &s.tcpsockets[SOCKET_UNMARK(tcp_sd)];
1955+
ts->sock.tcp.state = TCP_CLOSED;
1956+
fifo_init(&ts->sock.tcp.txbuf, tiny_txbuf, sizeof(tiny_txbuf));
1957+
1958+
memset(&sin, 0, sizeof(sin));
1959+
sin.sin_family = AF_INET;
1960+
sin.sin_port = ee16(80);
1961+
sin.sin_addr.s_addr = ee32(0x0A000002U);
1962+
1963+
ck_assert_int_eq(wolfIP_sock_connect(&s, tcp_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)),
1964+
-WOLFIP_EAGAIN);
1965+
ck_assert_int_eq(ts->sock.tcp.state, TCP_CLOSED);
1966+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_active, 0);
1967+
ck_assert_int_eq(ts->sock.tcp.tmr_rto, NO_TIMER);
1968+
ck_assert_ptr_null(fifo_peek(&ts->sock.tcp.txbuf));
1969+
}
1970+
END_TEST
1971+
19401972
START_TEST(test_sock_connect_tcp_primary_ip_fallback)
19411973
{
19421974
struct wolfIP s;
@@ -2413,6 +2445,48 @@ START_TEST(test_sock_accept_clones_half_open_state_and_queues_synack)
24132445
}
24142446
END_TEST
24152447

2448+
START_TEST(test_sock_accept_synack_rto_txbuf_full_does_not_consume_retry)
2449+
{
2450+
struct wolfIP s;
2451+
int listen_sd;
2452+
int client_sd;
2453+
struct tsocket *accepted;
2454+
struct wolfIP_sockaddr_in sin;
2455+
uint8_t tiny_txbuf[32];
2456+
2457+
wolfIP_init(&s);
2458+
mock_link_init(&s);
2459+
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
2460+
2461+
listen_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
2462+
ck_assert_int_gt(listen_sd, 0);
2463+
memset(&sin, 0, sizeof(sin));
2464+
sin.sin_family = AF_INET;
2465+
sin.sin_port = ee16(1234);
2466+
sin.sin_addr.s_addr = ee32(0x0A000001U);
2467+
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
2468+
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_sd, 1), 0);
2469+
2470+
inject_tcp_syn(&s, TEST_PRIMARY_IF, 0x0A000001U, 1234);
2471+
client_sd = wolfIP_sock_accept(&s, listen_sd, NULL, NULL);
2472+
ck_assert_int_gt(client_sd, 0);
2473+
2474+
accepted = &s.tcpsockets[SOCKET_UNMARK(client_sd)];
2475+
ck_assert_int_eq(accepted->sock.tcp.state, TCP_SYN_RCVD);
2476+
2477+
fifo_init(&accepted->sock.tcp.txbuf, tiny_txbuf, sizeof(tiny_txbuf));
2478+
accepted->sock.tcp.ctrl_rto_retries = 0;
2479+
s.last_tick = 10000;
2480+
2481+
tcp_rto_cb(accepted);
2482+
2483+
ck_assert_uint_eq(accepted->sock.tcp.ctrl_rto_retries, 0);
2484+
ck_assert_uint_eq(accepted->sock.tcp.ctrl_rto_active, 1);
2485+
ck_assert_int_ne(accepted->sock.tcp.tmr_rto, NO_TIMER);
2486+
ck_assert_ptr_null(fifo_peek(&accepted->sock.tcp.txbuf));
2487+
}
2488+
END_TEST
2489+
24162490
START_TEST(test_sock_accept_synack_retransmission)
24172491
{
24182492
struct wolfIP s;

src/wolfip.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,7 +2648,7 @@ static void tcp_send_finack(struct tsocket *t)
26482648
t->sock.tcp.last = t->sock.tcp.seq;
26492649
}
26502650

2651-
static void tcp_send_syn(struct tsocket *t, uint8_t flags)
2651+
static int tcp_send_syn(struct tsocket *t, uint8_t flags)
26522652
{
26532653
struct wolfIP_tcp_seg *tcp;
26542654
struct tcp_opt_ts *ts;
@@ -2731,7 +2731,7 @@ static void tcp_send_syn(struct tsocket *t, uint8_t flags)
27312731
opt_len++;
27322732
}
27332733
tcp->hlen = ((20 + opt_len) << 2) & 0xF0;
2734-
fifo_push(&t->sock.tcp.txbuf, tcp, sizeof(struct wolfIP_tcp_seg) + opt_len);
2734+
return fifo_push(&t->sock.tcp.txbuf, tcp, sizeof(struct wolfIP_tcp_seg) + opt_len);
27352735
}
27362736

27372737
/* Returns true when handshake/teardown control traffic is outstanding and
@@ -4169,16 +4169,24 @@ static void tcp_rto_cb(void *arg)
41694169
close_socket(ts);
41704170
return;
41714171
}
4172-
ts->sock.tcp.ctrl_rto_retries++;
4173-
if (ts->sock.tcp.state == TCP_SYN_SENT) {
4174-
tcp_send_syn(ts, TCP_FLAG_SYN);
4175-
} else if (ts->sock.tcp.state == TCP_SYN_RCVD) {
4176-
tcp_send_syn(ts, TCP_FLAG_SYN | TCP_FLAG_ACK);
4177-
} else if (ts->sock.tcp.state == TCP_FIN_WAIT_1 || ts->sock.tcp.state == TCP_LAST_ACK) {
4178-
tcp_send_finack(ts);
4172+
{
4173+
int queued = 0;
4174+
4175+
if (ts->sock.tcp.state == TCP_SYN_SENT) {
4176+
queued = (tcp_send_syn(ts, TCP_FLAG_SYN) == 0);
4177+
} else if (ts->sock.tcp.state == TCP_SYN_RCVD) {
4178+
queued = (tcp_send_syn(ts, TCP_FLAG_SYN | TCP_FLAG_ACK) == 0);
4179+
} else if (ts->sock.tcp.state == TCP_FIN_WAIT_1 || ts->sock.tcp.state == TCP_LAST_ACK) {
4180+
ts->sock.tcp.ctrl_rto_retries++;
4181+
tcp_send_finack(ts);
4182+
tcp_ctrl_rto_start(ts, ts->S->last_tick);
4183+
return;
4184+
}
4185+
if (queued)
4186+
ts->sock.tcp.ctrl_rto_retries++;
4187+
tcp_ctrl_rto_start(ts, ts->S->last_tick);
4188+
return;
41794189
}
4180-
tcp_ctrl_rto_start(ts, ts->S->last_tick);
4181-
return;
41824190
}
41834191
if (ts->sock.tcp.state != TCP_ESTABLISHED &&
41844192
ts->sock.tcp.state != TCP_FIN_WAIT_1)
@@ -4548,7 +4556,10 @@ int wolfIP_sock_connect(struct wolfIP *s, int sockfd, const struct wolfIP_sockad
45484556
return -1;
45494557
}
45504558
ts->sock.tcp.ctrl_rto_retries = 0;
4551-
tcp_send_syn(ts, TCP_FLAG_SYN);
4559+
if (tcp_send_syn(ts, TCP_FLAG_SYN) < 0) {
4560+
ts->sock.tcp.state = TCP_CLOSED;
4561+
return -WOLFIP_EAGAIN;
4562+
}
45524563
tcp_ctrl_rto_start(ts, s->last_tick);
45534564
return -WOLFIP_EAGAIN;
45544565
}
@@ -4581,7 +4592,6 @@ int wolfIP_sock_accept(struct wolfIP *s, int sockfd, struct wolfIP_sockaddr *add
45814592
newts = tcp_new_socket(s);
45824593
if (!newts)
45834594
return -1;
4584-
ts->events &= ~CB_EVENT_READABLE;
45854595
/* Don't signal writable until connection fully established */
45864596
newts->events &= ~CB_EVENT_WRITABLE;
45874597
newts->callback = ts->callback;
@@ -4616,7 +4626,11 @@ int wolfIP_sock_accept(struct wolfIP *s, int sockfd, struct wolfIP_sockaddr *add
46164626
* the caller could still close the listening socket
46174627
* while we're still accepting.
46184628
*/
4619-
tcp_send_syn(newts, TCP_FLAG_SYN | TCP_FLAG_ACK);
4629+
if (tcp_send_syn(newts, TCP_FLAG_SYN | TCP_FLAG_ACK) < 0) {
4630+
close_socket(newts);
4631+
return -WOLFIP_EAGAIN;
4632+
}
4633+
ts->events &= ~CB_EVENT_READABLE;
46204634
newts->sock.tcp.seq++;
46214635
newts->sock.tcp.ctrl_rto_retries = 0;
46224636
tcp_ctrl_rto_start(newts, s->last_tick);

0 commit comments

Comments
 (0)