Skip to content

Commit 3f91064

Browse files
committed
make payload pointer/length calculations in tcp_recv mask
1 parent 01c2e18 commit 3f91064

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

src/test/unit/unit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ Suite *wolf_suite(void)
611611
tcase_add_test(tc_utils, test_tcp_recv_overlapping_ooo_segments_coalesce_on_consume);
612612
tcase_add_test(tc_utils, test_tcp_input_syn_with_sack_option_enables_sack);
613613
tcase_add_test(tc_utils, test_tcp_input_ignores_reserved_bits_in_hlen);
614+
tcase_add_test(tc_utils, test_tcp_recv_ignores_reserved_bits_in_hlen);
614615
tcase_add_test(tc_utils, test_tcp_input_syn_with_sack_option_respects_local_sack_offer);
615616
tcase_add_test(tc_utils, test_tcp_input_iplen_too_big);
616617
tcase_add_test(tc_utils, test_tcp_checksum_valid_passes);

src/test/unit/unit_tests_tcp_flow.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,49 @@ START_TEST(test_tcp_recv_queues_payload_and_advances_ack)
30653065
}
30663066
END_TEST
30673067

3068+
START_TEST(test_tcp_recv_ignores_reserved_bits_in_hlen)
3069+
{
3070+
/* RFC 9293 3.1: the low nibble of the Data Offset byte is Rsrvd and MUST
3071+
* be ignored. tcp_recv must therefore base its payload pointer and length
3072+
* on the masked (high-nibble) header length, otherwise a peer that sets
3073+
* reserved bits would have its delivered bytes shifted by 4*Rsrvd octets. */
3074+
struct wolfIP s;
3075+
struct tsocket *ts;
3076+
uint8_t payload[8] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
3077+
uint8_t seg_buf[sizeof(struct wolfIP_tcp_seg) + sizeof(payload)];
3078+
struct wolfIP_tcp_seg *seg = (struct wolfIP_tcp_seg *)seg_buf;
3079+
uint32_t seq = 50;
3080+
uint8_t out[sizeof(payload) + 4];
3081+
int ret;
3082+
3083+
wolfIP_init(&s);
3084+
ts = &s.tcpsockets[0];
3085+
memset(ts, 0, sizeof(*ts));
3086+
ts->proto = WI_IPPROTO_TCP;
3087+
ts->S = &s;
3088+
ts->sock.tcp.state = TCP_ESTABLISHED;
3089+
ts->sock.tcp.ack = seq;
3090+
ts->sock.tcp.bytes_in_flight = 1;
3091+
queue_init(&ts->sock.tcp.rxbuf, ts->rxmem, RXBUF_SIZE, seq);
3092+
3093+
memset(seg, 0, sizeof(seg_buf));
3094+
seg->ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN + sizeof(payload));
3095+
/* No options (hdr is the bare 20 bytes), but flip every reserved bit on. */
3096+
seg->hlen = (uint8_t)((TCP_HEADER_LEN << 2) | 0x0F);
3097+
seg->seq = ee32(seq);
3098+
seg->flags = (TCP_FLAG_ACK | TCP_FLAG_PSH);
3099+
memcpy(seg->data, payload, sizeof(payload));
3100+
3101+
tcp_recv(ts, seg);
3102+
3103+
ck_assert_uint_eq(ts->sock.tcp.ack, seq + sizeof(payload));
3104+
memset(out, 0, sizeof(out));
3105+
ret = queue_pop(&ts->sock.tcp.rxbuf, out, sizeof(out));
3106+
ck_assert_int_eq(ret, (int)sizeof(payload));
3107+
ck_assert_mem_eq(out, payload, sizeof(payload));
3108+
}
3109+
END_TEST
3110+
30683111
START_TEST(test_tcp_recv_wrong_state_does_nothing)
30693112
{
30703113
struct wolfIP s;

src/wolfip.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,9 +3465,12 @@ static inline uint32_t tcp_seq_inc(uint32_t seq, uint32_t n)
34653465
/* Add a segment to the rx buffer for the application to consume */
34663466
static void tcp_recv(struct tsocket *t, struct wolfIP_tcp_seg *seg)
34673467
{
3468-
uint32_t seg_len = ee16(seg->ip.len) - (IP_HEADER_LEN + (seg->hlen >> 2));
3468+
/* RFC 9293 3.1: mask the reserved nibble before deriving header length so a
3469+
* peer that sets reserved bits cannot shift our payload pointer/length. */
3470+
uint32_t hdr_len = tcp_data_offset_bytes(seg->hlen);
3471+
uint32_t seg_len = ee16(seg->ip.len) - (IP_HEADER_LEN + hdr_len);
34693472
uint32_t seq = ee32(seg->seq);
3470-
const uint8_t *payload = (uint8_t *)seg->ip.data + (seg->hlen >> 2);
3473+
const uint8_t *payload = (uint8_t *)seg->ip.data + hdr_len;
34713474
if ((t->sock.tcp.state != TCP_ESTABLISHED) &&
34723475
(t->sock.tcp.state != TCP_CLOSE_WAIT) &&
34733476
(t->sock.tcp.state != TCP_FIN_WAIT_1) &&

0 commit comments

Comments
 (0)