Skip to content

Commit 309e7aa

Browse files
fix vulnerablilities:NULL pointer dereference and Heap OOB read and Stack OOB read when copying a string for logs, and limit crypto stream frame data buffer and unack packets send buffer (#468)
1 parent 6ba26c9 commit 309e7aa

File tree

5 files changed

+38
-9
lines changed

5 files changed

+38
-9
lines changed

src/http3/xqc_h3_stream.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1687,8 +1687,10 @@ xqc_h3_stream_process_data(xqc_stream_t *stream, xqc_h3_stream_t *h3s, xqc_bool_
16871687

16881688
} else if (h3s->type == XQC_H3_STREAM_TYPE_BYTESTEAM) {
16891689
//TODO: mark the fin flag of the bytestream and record time
1690-
xqc_h3_ext_bytestream_fin_rcvd(h3s->h3_ext_bs);
1691-
xqc_h3_ext_bytestream_set_fin_rcvd_flag(h3s->h3_ext_bs);
1690+
if (h3s->h3_ext_bs) {
1691+
xqc_h3_ext_bytestream_fin_rcvd(h3s->h3_ext_bs);
1692+
xqc_h3_ext_bytestream_set_fin_rcvd_flag(h3s->h3_ext_bs);
1693+
}
16921694
}
16931695
}
16941696

@@ -1882,6 +1884,7 @@ xqc_h3_stream_read_notify(xqc_stream_t *stream, void *user_data)
18821884

18831885
/* TODO: BYTESTRAM: notify DATA to application ASAP */
18841886
if (h3s->type == XQC_H3_STREAM_TYPE_BYTESTEAM
1887+
&& h3s->h3_ext_bs
18851888
&& xqc_h3_ext_bytestream_should_notify_read(h3s->h3_ext_bs))
18861889
{
18871890
ret = xqc_h3_ext_bytestream_notify_read(h3s->h3_ext_bs);

src/transport/xqc_frame.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -619,13 +619,29 @@ xqc_process_stream_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in)
619619
return ret;
620620
}
621621

622+
xqc_int_t
623+
xqc_check_crypto_frame_data_buffer_exceed(xqc_stream_t *stream, xqc_stream_frame_t *stream_frame, uint64_t threshold)
624+
{
625+
if (stream_frame->data_offset + stream_frame->data_length > stream->stream_data_in.next_read_offset + threshold) {
626+
return -XQC_ELIMIT;
627+
}
628+
return XQC_OK;
629+
}
622630

623631
xqc_int_t
624632
xqc_insert_crypto_frame(xqc_connection_t *conn, xqc_stream_t *stream, xqc_stream_frame_t *stream_frame)
625633
{
626634
unsigned char inserted = 0;
627635
xqc_list_head_t *pos;
628636
xqc_stream_frame_t *frame;
637+
xqc_int_t ret;
638+
ret = xqc_check_crypto_frame_data_buffer_exceed(stream, stream_frame, XQC_CONN_MAX_CRYPTO_DATA_TOTAL_LEN);
639+
if (ret != XQC_OK) {
640+
XQC_CONN_ERR(conn, TRA_CRYPTO_BUFFER_EXCEEDED);
641+
xqc_log(conn->log, XQC_LOG_ERROR,
642+
"|crypto frame data buffer exceed|");
643+
return ret;
644+
}
629645
xqc_list_for_each_reverse(pos, &stream->stream_data_in.frames_tailq) {
630646
frame = xqc_list_entry(pos, xqc_stream_frame_t, sf_list);
631647

@@ -697,7 +713,7 @@ xqc_process_crypto_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in)
697713
if (ret != XQC_OK) {
698714
xqc_log(conn->log, XQC_LOG_ERROR, "|xqc_insert_crypto_frame error|");
699715
xqc_destroy_stream_frame(stream_frame);
700-
return -1;
716+
return ret;
701717
}
702718

703719
ret = xqc_read_crypto_stream(stream);
@@ -1508,8 +1524,8 @@ xqc_process_path_challenge_frame(xqc_connection_t *conn, xqc_packet_in_t *packet
15081524
}
15091525

15101526
xqc_log(conn->log, XQC_LOG_DEBUG,
1511-
"|path:%ui|state:%d|RECV path_challenge_data:%s|cid:%s|",
1512-
path->path_id, path->path_state,
1527+
"|path:%ui|state:%d|RECV path_challenge_data:%*s|cid:%s|",
1528+
path->path_id, path->path_state, XQC_PATH_CHALLENGE_DATA_LEN,
15131529
path_challenge_data, xqc_dcid_str(conn->engine, &packet_in->pi_pkt.pkt_dcid));
15141530

15151531
ret = xqc_write_path_response_frame_to_packet(conn, path, path_challenge_data);
@@ -2110,4 +2126,4 @@ xqc_process_repair_frame(xqc_connection_t *conn, xqc_packet_in_t *packet_in)
21102126
return XQC_OK;
21112127
}
21122128

2113-
#endif
2129+
#endif

src/transport/xqc_send_queue.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,19 @@ xqc_send_queue_remove_probe(xqc_list_head_t *pos)
277277
void
278278
xqc_send_queue_insert_unacked(xqc_packet_out_t *packet_out, xqc_list_head_t *head, xqc_send_queue_t *send_queue)
279279
{
280+
xqc_connection_t *conn = send_queue->sndq_conn;
280281
xqc_list_add_tail(&packet_out->po_list, head);
281282
if (!(packet_out->po_flag & XQC_POF_IN_UNACK_LIST)) {
282283
send_queue->sndq_packets_in_unacked_list++;
283284
packet_out->po_flag |= XQC_POF_IN_UNACK_LIST;
285+
if (send_queue->sndq_packets_in_unacked_list > XQC_SNDQ_MAX_UNACK_PACKETS_LIMIT) {
286+
if (conn) {
287+
XQC_CONN_ERR(conn, XQC_ELIMIT);
288+
xqc_log(conn->log, XQC_LOG_ERROR,
289+
"|sndq unack packets exceed|sndq_packets_in_unacked_list:%ui|",
290+
send_queue->sndq_packets_in_unacked_list);
291+
}
292+
}
284293
}
285294
}
286295

@@ -710,4 +719,4 @@ xqc_send_queue_drop_stream_frame_packets(xqc_connection_t *conn, xqc_stream_id_t
710719
if (count > 0) {
711720
xqc_log(conn->log, XQC_LOG_DEBUG, "|stream_id:%ui|to_drop: %d|count:%d|", stream_id, to_drop, count);
712721
}
713-
}
722+
}

src/transport/xqc_send_queue.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#define XQC_SNDQ_PACKETS_USED_MAX 18000
99
#define XQC_SNDQ_RELEASE_ENOUGH_SPACE_TH 10 /* 1 / 10*/
10+
#define XQC_SNDQ_MAX_UNACK_PACKETS_LIMIT (100 * 1000) /* limit unack packets to avoid ddos attack */
1011

1112
typedef struct xqc_send_queue_s {
1213

tests/test_server.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1367,8 +1367,8 @@ xqc_server_request_read_notify(xqc_h3_request_t *h3_request, xqc_request_notify_
13671367

13681368
for (int i = 0; i < headers->count; i++) {
13691369
printf("%s = %s\n", (char *)headers->headers[i].name.iov_base, (char *)headers->headers[i].value.iov_base);
1370-
1371-
if (memcmp((char *)headers->headers[i].name.iov_base, "priority", 8) == 0) {
1370+
if (headers->headers[i].name.iov_len == 8
1371+
&& memcmp((char *)headers->headers[i].name.iov_base, "priority", 8) == 0) {
13721372
xqc_h3_priority_t h3_prio;
13731373
xqc_int_t ret = xqc_parse_http_priority(&h3_prio,
13741374
headers->headers[i].value.iov_base,

0 commit comments

Comments
 (0)