From 72769f0d4306b82c382bae45d7bede26153839ce Mon Sep 17 00:00:00 2001 From: liuxueli Date: Wed, 7 Jul 2021 18:04:52 +0800 Subject: TSG-6935: 修复DNS解析层处理TCP的DNS流量,返回DROPME时未调用业务层CLOSE状态导致内存泄漏 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dns.cpp | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/dns.cpp b/src/dns.cpp index 7e2f58d..77b06b2 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -1663,10 +1663,10 @@ int parse_dns_protocol(struct streaminfo *a_stream, unsigned char opstate, char unsigned long long register_flag = dns_register_flag; save_dns_business_info_t *context = (save_dns_business_info_t *)(*pme); - if(payload_len < 12 ) + if(payload_len<12 || payload==NULL) { FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); - MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_FATAL, "parse_dns_protocol", "tuple4: %s payload_len < 12", printaddr(&a_stream->addr, thread_seq)); + MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_DEBUG, "parse_dns_protocol", "tuple4: %s payload_len<12 or payload==NULL", printaddr(&a_stream->addr, thread_seq)); return APP_STATE_DROPME; } @@ -1694,10 +1694,12 @@ int parse_dns_protocol(struct streaminfo *a_stream, unsigned char opstate, char if(context->session_state&SESSION_STATE_PENDING) { session_state = SESSION_STATE_CLOSE; + context->session_state=SESSION_STATE_CLOSE; } else { session_state = SESSION_STATE_PENDING|SESSION_STATE_DATA|SESSION_STATE_CLOSE; + context->session_state=SESSION_STATE_CLOSE; } } @@ -1851,12 +1853,18 @@ char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a state=parse_dns_protocol(a_udp, a_udp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; case OP_STATE_CLOSE: - state=callback_dns_business_plug(a_udp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); + state=parse_dns_protocol(a_udp, a_udp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; } if(state&APP_STATE_DROPME || a_udp->opstate==OP_STATE_CLOSE) { + save_dns_business_info_t *context=(save_dns_business_info_t *)(*pme); + if((context->session_state&SESSION_STATE_CLOSE)!=SESSION_STATE_CLOSE) + { + state=callback_dns_business_plug(a_udp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); + } + dictator_free(thread_seq, *pme); *pme = NULL; } @@ -1871,7 +1879,7 @@ char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a char *payload = NULL; char state=APP_STATE_GIVEME; struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail; - save_dns_business_info_t *dns_pme=(save_dns_business_info_t*)*pme; + save_dns_business_info_t *context=(save_dns_business_info_t*)*pme; if(!check_port(a_tcp->addr, DNS_PORT)) { @@ -1894,8 +1902,8 @@ char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a { *pme = dictator_malloc(thread_seq, sizeof(save_dns_business_info_t)); memset(*pme, 0, sizeof(save_dns_business_info_t)); - dns_pme = (save_dns_business_info_t *)*pme; - dns_pme->skip_len=2; + context = (save_dns_business_info_t *)*pme; + context->skip_len=2; } /* no break here!!!! */ @@ -1919,17 +1927,17 @@ char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a if(tcp_detail->serverbytes <= 2) { - dns_pme->skip_len -= payload_len; + context->skip_len -= payload_len; break; } else { - if(dns_pme->skip_len!=0) + if(context->skip_len!=0) { - payload_len -= dns_pme->skip_len; - payload += dns_pme->skip_len; + payload_len -= context->skip_len; + payload += context->skip_len; - dns_pme->skip_len=0; + context->skip_len=2; //https://datatracker.ietf.org/doc/html/rfc7766#section-8 } } @@ -1944,12 +1952,18 @@ char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a state=parse_dns_protocol(a_tcp, a_tcp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; case OP_STATE_CLOSE: - state=callback_dns_business_plug(a_tcp, pme, NULL, DNS_UNKOWN, SESSION_STATE_CLOSE, thread_seq, a_packet); + state=parse_dns_protocol(a_tcp, a_tcp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; } if(state&APP_STATE_DROPME || a_tcp->opstate==OP_STATE_CLOSE) { + save_dns_business_info_t *context=(save_dns_business_info_t *)(*pme); + if((context->session_state&SESSION_STATE_CLOSE)!=SESSION_STATE_CLOSE) + { + state=callback_dns_business_plug(a_tcp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); + } + dictator_free(thread_seq, *pme); *pme = NULL; } -- cgit v1.2.3