From 21493d5654484f6dd3427228832d02688789e47c Mon Sep 17 00:00:00 2001 From: Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> Date: Fri, 13 Dec 2024 12:48:45 +0100 Subject: [PATCH] DNS: fix Index-out-of-bounds error (#2644) ``` Running: /home/ivan/Downloads/clusterfuzz-testcase-minimized-fuzz_ndpi_reader_pl7m_simplest_internal-5759495480868864 protocols/dns.c:482:5: runtime error: index 4 out of bounds for type 'u_int8_t[4]' (aka 'unsigned char[4]') SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior protocols/dns.c:482:5 protocols/dns.c:483:5: runtime error: index 4 out of bounds for type 'u_int32_t[4]' (aka 'unsigned int[4]') SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior protocols/dns.c:483:5 protocols/dns.c:490:12: runtime error: index 4 out of bounds for type 'u_int32_t[4]' (aka 'unsigned int[4]') ``` Found by oss-fuzz See: https://issues.oss-fuzz.com/issues/383911300?pli=1 --- src/lib/protocols/dns.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index d109098d18f..927e09af211 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -475,21 +475,26 @@ static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct, || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */ )) { if(found == 0) { - /* Necessary for IP address comparison */ - memset(&flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], 0, sizeof(ndpi_ip_addr_t)); - memcpy(&flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], packet->payload + x, data_len); - flow->protos.dns.is_rsp_addr_ipv6[flow->protos.dns.num_rsp_addr] = (data_len == 16) ? 1 : 0; - flow->protos.dns.rsp_addr_ttl[flow->protos.dns.num_rsp_addr] = ttl; - - if(ndpi_struct->cfg.address_cache_size) - ndpi_cache_address(ndpi_struct, - flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], - flow->host_server_name, - packet->current_time_ms/1000, - flow->protos.dns.rsp_addr_ttl[flow->protos.dns.num_rsp_addr]); + if(flow->protos.dns.num_rsp_addr < MAX_NUM_DNS_RSP_ADDRESSES) { + /* Necessary for IP address comparison */ + memset(&flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], 0, sizeof(ndpi_ip_addr_t)); - if(++flow->protos.dns.num_rsp_addr == MAX_NUM_DNS_RSP_ADDRESSES) + memcpy(&flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], packet->payload + x, data_len); + flow->protos.dns.is_rsp_addr_ipv6[flow->protos.dns.num_rsp_addr] = (data_len == 16) ? 1 : 0; + flow->protos.dns.rsp_addr_ttl[flow->protos.dns.num_rsp_addr] = ttl; + + if(ndpi_struct->cfg.address_cache_size) + ndpi_cache_address(ndpi_struct, + flow->protos.dns.rsp_addr[flow->protos.dns.num_rsp_addr], + flow->host_server_name, + packet->current_time_ms/1000, + flow->protos.dns.rsp_addr_ttl[flow->protos.dns.num_rsp_addr]); + + ++flow->protos.dns.num_rsp_addr; + } + + if(flow->protos.dns.num_rsp_addr >= MAX_NUM_DNS_RSP_ADDRESSES) found = 1; } }