When trying to resolve DNS names into IP addresses, the DNS code fails from time to time with the following error: -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- error: ../../grub-core/net/dns.c:688:no DNS record found. -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
This happens when both IPv4 and IPv6 queries are performed against the DNS server (e.g. 8.8.8.8) but there is no IP returned for IPv6 query, as shown below: -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- grub> net_del_dns 192.168.122.1 grub> net_add_dns 8.8.8.8 grub> net_nslookup ipv4.test-ipv6.com error: ../../grub-core/net/dns.c:688:no DNS record found. grub> net_nslookup ipv4.test-ipv6.com 216.218.228.115 -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- The root cause is the code exiting prematurely when the data->addresses buffer has been allocated in recv_hook(), even if there was no address returned last time recv_hook() executed. This patch additionally simplifies the error handling. Signed-off-by: Renaud Métrich <rmetr...@redhat.com> --- grub-core/net/dns.c | 69 +++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index afa389494..2dfb98d98 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -261,43 +261,27 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), /* Code apparently assumed that only one packet is received as response. We may get multiple responses due to network condition, so check here and quit early. */ - if (*data->addresses) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + if (*data->naddresses) + goto out; head = (struct dns_header *) nb->data; ptr = (grub_uint8_t *) (head + 1); if (ptr >= nb->tail) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; if (head->id != data->id) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; if (!(head->flags & FLAGS_RESPONSE) || (head->flags & FLAGS_OPCODE)) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; if (head->ra_z_r_code & ERRCODE_MASK) { data->dns_err = 1; - grub_netbuff_free (nb); - return GRUB_ERR_NONE; + goto out; } for (i = 0; i < grub_be_to_cpu16 (head->qdcount); i++) { if (ptr >= nb->tail) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) ptr += *ptr + 1; if (ptr < nb->tail && (*ptr & 0xc0)) @@ -310,8 +294,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), if (!*data->addresses) { grub_errno = GRUB_ERR_NONE; - grub_netbuff_free (nb); - return GRUB_ERR_NONE; + goto out; } reparse_ptr = ptr; reparse: @@ -322,11 +305,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_uint32_t ttl = 0; grub_uint16_t length; if (ptr >= nb->tail) - { - if (!*data->naddresses) - grub_free (*data->addresses); - return GRUB_ERR_NONE; - } + goto out; ignored = !check_name (ptr, nb->data, nb->tail, data->name); while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) ptr += *ptr + 1; @@ -334,12 +313,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), ptr++; ptr++; if (ptr + 10 >= nb->tail) - { - if (!*data->naddresses) - grub_free (*data->addresses); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; if (*ptr++ != 0) ignored = 1; class = *ptr++; @@ -355,12 +329,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), length = *ptr++ << 8; length |= *ptr++; if (ptr + length > nb->tail) - { - if (!*data->naddresses) - grub_free (*data->addresses); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } + goto out; if (!ignored) { if (ttl_all > ttl) @@ -374,6 +343,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, ptr, 4); + grub_dprintf ("dns", "got A 0x%x\n", (*data->addresses)[*data->naddresses].ipv4); (*data->naddresses)++; data->stop = 1; break; @@ -384,6 +354,10 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, ptr, 16); + grub_dprintf ("dns", "got AAAA 0x%lx%lx\n", + (*data->addresses)[*data->naddresses].ipv6[0], + (*data->addresses)[*data->naddresses].ipv6[1] + ); (*data->naddresses)++; data->stop = 1; break; @@ -400,15 +374,14 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), if (!data->name) { data->dns_err = 1; - grub_errno = 0; - return GRUB_ERR_NONE; + grub_errno = GRUB_ERR_NONE; + goto out; } grub_dprintf ("dns", "CNAME %s\n", data->name); if (grub_strcmp (redirect_save, data->name) == 0) { data->dns_err = 1; - grub_free (redirect_save); - return GRUB_ERR_NONE; + goto out; } goto reparse; } @@ -440,8 +413,12 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), *data->naddresses * sizeof (dns_cache[h].addresses[0])); } + + out: grub_netbuff_free (nb); grub_free (redirect_save); + if (!*data->naddresses) + grub_free (*data->addresses); return GRUB_ERR_NONE; } -- 2.40.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel