summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliuxueli <[email protected]>2021-09-04 13:46:32 +0800
committerliuxueli <[email protected]>2021-09-04 13:46:32 +0800
commita2eb69b2ad840a40532ce24719e93fd9a20f643d (patch)
tree16c4db99c80a611520d582ee992a4c4f78d4483f
parent59638765e3eacdf0eac3d96e7941fb710d3a0590 (diff)
TSG-7636: 修复读越界问题
-rw-r--r--src/gquic_process.cpp166
1 files changed, 100 insertions, 66 deletions
diff --git a/src/gquic_process.cpp b/src/gquic_process.cpp
index 2f3ce62..107a47c 100644
--- a/src/gquic_process.cpp
+++ b/src/gquic_process.cpp
@@ -118,6 +118,12 @@ static int get_value(unsigned char *payload, int *offset, int len)
return 0;
}
+
+static int check_length(int last_len, int field_len)
+{
+ return ((last_len-field_len>0) ? 1 : 0);
+}
+
int quic_getLinkState(struct _quic_context *_context)
{
UCHAR state = 0;
@@ -229,23 +235,39 @@ unsigned long long get_variable_length(char *p, int offset, int v_len)
return 0;
}
-long long bit_to_value(char *payload, unsigned char flags, unsigned long long *out_value, int *used_len)
+long long bit_to_value(char *payload, int payload_len, unsigned char flags, unsigned long long *out_value, int *used_len)
{
switch(flags&0x3) // packet number
{
case 0x3: // 6 bytes
+ if(!check_length(payload_len-*used_len, 6))
+ {
+ return -1;
+ }
*out_value=get_variable_length(payload, *used_len, 6);
*used_len+=6;
break;
case 0x2: // 4 bytes
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
+ {
+ return -1;
+ }
*out_value=(unsigned long long)ntohl(*(unsigned int *)(payload+*used_len));
*used_len+=4;
break;
case 0x1: // 2bytes
+ if(!check_length(payload_len-*used_len, sizeof(unsigned short)))
+ {
+ return -1;
+ }
*out_value=(unsigned long long)ntohs(*(unsigned short *)(payload+*used_len));
*used_len+=2;
break;
default: // 1 byte
+ if(!check_length(payload_len-*used_len, sizeof(unsigned char)))
+ {
+ return -1;
+ }
*out_value=payload[*used_len];
*used_len+=1;
break;
@@ -268,23 +290,37 @@ int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread
return 0;
}
-int get_stream_id(struct streaminfo *pstream, struct _quic_context* _context, char* payload, unsigned char frame_type, int *used_len)
+int get_stream_id(struct streaminfo *pstream, struct _quic_context* _context, char* payload, int payload_len, unsigned char frame_type, int *used_len)
{
int stream_len=0,offset_len=0;
_context->quic_info.frame_hdr.frame_type=frame_type;
stream_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_ID)+1;
+ if(!check_length(payload_len-*used_len, stream_len))
+ {
+ return -1;
+ }
+
_context->quic_info.frame_hdr.stream_id=(unsigned int)get_variable_length(payload, *used_len, stream_len);
*used_len+=stream_len; // stream ID length
if(frame_type&GQUIC_SPECIAL_FRAME_STREAM_DLEN)
{
+ if(!check_length(payload_len-*used_len, 2))
+ {
+ return -1;
+ }
_context->quic_info.frame_hdr.data_len=ntohs(*(unsigned short *)(payload+*used_len));
*used_len+=2; //data length
}
offset_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET) ? (((frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET))>>2)+1 : 0;
+ if(!check_length(payload_len-*used_len, offset_len))
+ {
+ return -1;
+ }
+
_context->quic_info.frame_hdr.offset=get_variable_length(payload, *used_len, offset_len);
*used_len+=offset_len;
@@ -325,6 +361,7 @@ unsigned long long get_packet_number(char* data, int offset, char pkn_len)
// GQUIC version from 0 to 43
static enum _QUIC_VERSION parse_q0to43_header(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len)
{
+ int ret=0;
char public_flags=0;
struct _quic_public_header *gquic_hdr=&(_context->quic_info.quic_hdr);
@@ -380,8 +417,12 @@ static enum _QUIC_VERSION parse_q0to43_header(struct streaminfo *pstream, struct
return QUIC_VERSION_UNKNOWN;
}
- bit_to_value(payload, gquic_hdr->public_flags>>4, &gquic_hdr->packet_number, used_len);
-
+ ret=bit_to_value(payload, payload_len, gquic_hdr->public_flags>>4, &gquic_hdr->packet_number, used_len);
+ if(ret<0)
+ {
+ return (enum _QUIC_VERSION)gquic_hdr->quic_version;
+ }
+
if(gquic_hdr->public_flags==GQUIC_PUBLIC_FLAG_NONCE)
{
*used_len+=32; //diversification nonce
@@ -520,8 +561,8 @@ enum _QUIC_VERSION is_quic_protocol(struct streaminfo *pstream, struct _quic_con
(quic_version==GQUIC_VERSION_T099) ||
(quic_version>=GQUIC_VERSION_Q047 && quic_version<=GQUIC_VERSION_Q050) ||
(quic_version>=GQUIC_VERSION_Q051 && quic_version<=GQUIC_VERSION_Q059) ||
- (quic_version>=GQUIC_VERSION_T048&& quic_version<=GQUIC_VERSION_T049) ||
- (quic_version>=GQUIC_VERSION_T050&& quic_version<=GQUIC_VERSION_T059) ||
+ (quic_version>=GQUIC_VERSION_T048 && quic_version<=GQUIC_VERSION_T049) ||
+ (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
(quic_version>=QUANT_VERSION_00 && quic_version<=QUANT_VERSION_FF) ||
(quic_version>=QUIC_GO_VERSION_00 && quic_version<=QUIC_GO_VERSION_FF) ||
(quic_version>=QUICLY_VERSION_00 && quic_version<=QUICLY_VERSION_FF) ||
@@ -647,55 +688,6 @@ int parse_extension_tag(struct streaminfo *pstream, struct _quic_stream **quic_s
return 0;
}
-int gquic_frame_type_ack(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len, char frame_type, void *a_packet)
-{
- unsigned char num_timestamp;
- unsigned char num_blocks=0;;
- unsigned short largest_acked_delta_time=0;
- unsigned long long ack_block_length=0;
- unsigned long long largest_observed_ack=0;
-
- bit_to_value(payload, frame_type>>2, &largest_observed_ack, used_len); // frame_type -> LL
- largest_acked_delta_time=ntohs(*(unsigned short *)(payload+*used_len));
- *used_len+=sizeof(unsigned short);
-
- if(frame_type&0x20) // frame_type -> n
- {
- num_blocks=(*(unsigned char *)(payload+*used_len))-1;
- }
- bit_to_value(payload, frame_type>>2, &ack_block_length, used_len); // frame_type -> mm
-
- if(num_blocks>0)
- {
- *used_len+=1; //gap_to_next_block
-
- *used_len+=(num_blocks*sizeof(unsigned int)); //Ack block length
- }
-
- num_timestamp=*(unsigned char *)(payload+*used_len);
- *used_len += 1;
-
- if(num_timestamp > 0)
- {
- *used_len+=sizeof(unsigned char); //Delta Largest Observed
- *used_len+= sizeof(unsigned int); //First Timestamp
- *used_len+=(num_timestamp-1)*(1+2); //1+2=Delta Largest Observed+Time Since Previous Timestamp
- }
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_ACK",
- "largest_observed_ack: %llu largest_acked_delta_time: %u num_blocks: %d ack_block_length: %d num_timestamp: %d addr: %s",
- largest_observed_ack,
- largest_acked_delta_time,
- num_blocks,
- ack_block_length,
- num_timestamp,
- printaddr(&pstream->addr, pstream->threadnum));
-
- return 0;
-}
-
int gquic_frame_type_stream(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len, void *a_packet)
{
int ret=0;
@@ -703,6 +695,11 @@ int gquic_frame_type_stream(struct streaminfo *pstream, struct _quic_context* _c
unsigned short tag_num = 0;
unsigned int message_tag;
+ if(!check_length(payload_len-*used_len, 8))
+ {
+ return state;
+ }
+
message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
*used_len+=4;
@@ -762,6 +759,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
return APP_STATE_GIVEME; // PADDING frame
break;
case GQUIC_REGULAR_FRAME_RST_STREAM:
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)+sizeof(unsigned int)))
+ {
+ return APP_STATE_GIVEME;
+ }
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
*used_len+=sizeof(unsigned int);
@@ -783,12 +784,21 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
break;
case GQUIC_REGULAR_FRAME_CONNECTION_CLOSE:
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned short)))
+ {
+ return APP_STATE_GIVEME;
+ }
error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
*used_len+=sizeof(unsigned int);
reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
*used_len+=sizeof(unsigned short);
+ if(!check_length(payload_len-*used_len, reason_phrase_length))
+ {
+ return APP_STATE_GIVEME;
+ }
+
*used_len+=reason_phrase_length; // skip Reason Phrase
MESA_handle_runtime_log(g_quic_param.logger,
@@ -802,6 +812,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
break;
case GQUIC_REGULAR_FRAME_GOAWAY:
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned int)+sizeof(unsigned short)))
+ {
+ return APP_STATE_GIVEME;
+ }
error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
*used_len+=sizeof(unsigned int);
@@ -811,7 +825,11 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
*used_len+=sizeof(unsigned short);
-
+
+ if(!check_length(payload_len-*used_len, reason_phrase_length))
+ {
+ return APP_STATE_GIVEME;
+ }
*used_len+=reason_phrase_length; // skip Reason Phrase
MESA_handle_runtime_log(g_quic_param.logger,
@@ -824,6 +842,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
printaddr(&pstream->addr, pstream->threadnum));
break;
case GQUIC_REGULAR_FRAME_WINDOW_UPDATE:
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)))
+ {
+ return APP_STATE_GIVEME;
+ }
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
*used_len+=sizeof(unsigned int);
@@ -839,6 +861,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
printaddr(&pstream->addr, pstream->threadnum));
break;
case GQUIC_REGULAR_FRAME_BLOCKED:
+ if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
+ {
+ return APP_STATE_GIVEME;
+ }
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
*used_len+=sizeof(unsigned int);
@@ -850,7 +876,11 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
printaddr(&pstream->addr, pstream->threadnum));
break;
case GQUIC_REGULAR_FRAME_STOP_WAITING:
- bit_to_value(payload, _context->quic_info.quic_hdr.public_flags>>4, &least_unacked_delta, used_len);
+ ret=bit_to_value(payload, payload_len, _context->quic_info.quic_hdr.public_flags>>4, &least_unacked_delta, used_len);
+ if(ret<0)
+ {
+ return APP_STATE_GIVEME;
+ }
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
@@ -864,14 +894,13 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
//The receiver of a PING frame simply needs to ACK the packet containing this frame
break;
default: //Regular Frame Types
- if(frame_type&GQUIC_SPECIAL_FRAME_STREAM)
+ if(frame_type&GQUIC_SPECIAL_FRAME_STREAM || (frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK)
{
- stream_id=get_stream_id(pstream, _context, payload, frame_type, used_len);
- ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
- }
- else if((frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK) // high bit set 0; (frame_type: 01nullmmB)
- {
- stream_id=get_stream_id(pstream, _context, payload, frame_type, used_len);
+ stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
+ if(stream_id<0)
+ {
+ return APP_STATE_GIVEME;
+ }
ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
}
else if((frame_type&0xE0)==GQUIC_SPECIAL_FRAME_CONGEST_FB) // high two bits set 0; (frame_type: 01nullmmB)
@@ -898,9 +927,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
//QUIC_DATA:is quic data pcap;QUIC_TRUE:is handshake pcap;QUIC_RETURN_DROPME:not quic protocol;
int parse_gquic_Q046(struct streaminfo *pstream, struct _quic_context* _context, void *a_packet, char * payload, int payload_len, int *used_len)
{
+ int stream_id=0;
int ret=APP_STATE_GIVEME;
unsigned char frame_type;
-
+
while(*used_len < payload_len)
{
frame_type=payload[*used_len];
@@ -908,7 +938,11 @@ int parse_gquic_Q046(struct streaminfo *pstream, struct _quic_context* _context,
if(frame_type&IQUIC_FRAME_STREAM_HEX08)
{
- get_stream_id(pstream, _context, payload, frame_type, used_len);
+ stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
+ if(stream_id<0)
+ {
+ return APP_STATE_GIVEME;
+ }
ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
}
else