From 3def40b01b79ceb0f20a3fbff857a10e9195352a Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 13 Nov 2017 16:10:35 +1100 Subject: [PATCH] 4816. [bug] Don't use a common array for storing EDNS options in DiG as it could fill up. [RT #45611] --- CHANGES | 3 ++ bin/dig/dighost.c | 89 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index e355b9e53e..f559a9af01 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4816. [bug] Don't use a common array for storing EDNS options + in DiG as it could fill up. [RT #45611] + 4815. [bug] rbt_test.c:insert_and_delete needed to call dns_rbt_addnode instead of dns_rbt_addname. [RT #46553] diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index e0058e5a8d..1b3191a0e0 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -655,6 +655,41 @@ make_empty_lookup(void) { return (looknew); } +#define EDNSOPT_OPTIONS 100U + +static void +cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) { + size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS; + size_t i; + looknew->ednsopts = isc_mem_allocate(mctx, len); + if (looknew->ednsopts == NULL) + fatal("out of memory"); + for (i = 0; i < EDNSOPT_OPTIONS; i++) { + looknew->ednsopts[i].code = 0; + looknew->ednsopts[i].length = 0; + looknew->ednsopts[i].value = NULL; + } + looknew->ednsoptscnt = 0; + if (lookold == NULL || lookold->ednsopts == NULL) + return; + + for (i = 0; i < lookold->ednsoptscnt; i++) { + len = lookold->ednsopts[i].length; + if (len != 0) { + INSIST(lookold->ednsopts[i].value != NULL); + looknew->ednsopts[i].value = + isc_mem_allocate(mctx, len); + if (looknew->ednsopts[i].value == NULL) + fatal("out of memory"); + memmove(looknew->ednsopts[i].value, + lookold->ednsopts[i].value, len); + } + looknew->ednsopts[i].code = lookold->ednsopts[i].code; + looknew->ednsopts[i].length = len; + } + looknew->ednsoptscnt = lookold->ednsoptscnt; +} + /*% * Clone a lookup, perhaps copying the server list. This does not clone * the query list, since it will be regenerated by the setup_lookup() @@ -700,8 +735,12 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { looknew->seenbadcookie = lookold->seenbadcookie; looknew->badcookie = lookold->badcookie; looknew->cookie = lookold->cookie; - looknew->ednsopts = lookold->ednsopts; - looknew->ednsoptscnt = lookold->ednsoptscnt; + if (lookold->ednsopts != NULL) { + cloneopts(looknew, lookold); + } else { + looknew->ednsopts = NULL; + looknew->ednsoptscnt = 0; + } looknew->ednsneg = lookold->ednsneg; looknew->padding = lookold->padding; looknew->mapped = lookold->mapped; @@ -1317,13 +1356,6 @@ setup_libs(void) { check_result(result, "isc_mutex_init"); } -/* - * Array of up to 100 options configured by +ednsopt - */ -#define EDNSOPT_OPTIONS 100U -static dns_ednsopt_t ednsopts[EDNSOPT_OPTIONS]; -static unsigned char ednsoptscnt = 0; - typedef struct dig_ednsoptname { isc_uint32_t code; const char *name; @@ -1355,7 +1387,7 @@ save_opt(dig_lookup_t *lookup, char *code, char *value) { isc_boolean_t found = ISC_FALSE; unsigned int i; - if (ednsoptscnt == EDNSOPT_OPTIONS) + if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) fatal("too many ednsopts"); for (i = 0; i < N_EDNS_OPTNAMES; i++) { @@ -1372,9 +1404,16 @@ save_opt(dig_lookup_t *lookup, char *code, char *value) { fatal("bad edns code point: %s", code); } - ednsopts[ednsoptscnt].code = num; - ednsopts[ednsoptscnt].length = 0; - ednsopts[ednsoptscnt].value = NULL; + if (lookup->ednsopts == NULL) { + cloneopts(lookup, NULL); + } + + if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) + isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value); + + lookup->ednsopts[lookup->ednsoptscnt].code = num; + lookup->ednsopts[lookup->ednsoptscnt].length = 0; + lookup->ednsopts[lookup->ednsoptscnt].value = NULL; if (value != NULL) { char *buf; @@ -1384,14 +1423,13 @@ save_opt(dig_lookup_t *lookup, char *code, char *value) { isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1); result = isc_hex_decodestring(value, &b); check_result(result, "isc_hex_decodestring"); - ednsopts[ednsoptscnt].value = isc_buffer_base(&b); - ednsopts[ednsoptscnt].length = isc_buffer_usedlength(&b); + lookup->ednsopts[lookup->ednsoptscnt].value = + isc_buffer_base(&b); + lookup->ednsopts[lookup->ednsoptscnt].length = + isc_buffer_usedlength(&b); } - if (lookup->ednsoptscnt == 0) - lookup->ednsopts = &ednsopts[ednsoptscnt]; lookup->ednsoptscnt++; - ednsoptscnt++; } /*% @@ -1570,6 +1608,15 @@ destroy_lookup(dig_lookup_t *lookup) { if (lookup->ecs_addr != NULL) isc_mem_free(mctx, lookup->ecs_addr); + if (lookup->ednsopts != NULL) { + size_t i; + for (i = 0; i < EDNSOPT_OPTIONS; i++) { + if (lookup->ednsopts[i].value != NULL) + isc_mem_free(mctx, lookup->ednsopts[i].value); + } + isc_mem_free(mctx, lookup->ednsopts); + } + isc_mem_free(mctx, lookup); } @@ -4127,12 +4174,6 @@ destroy_libs(void) { debug("Removing log context"); isc_log_destroy(&lctx); - while (ednsoptscnt > 0U) { - ednsoptscnt--; - if (ednsopts[ednsoptscnt].value != NULL) - isc_mem_free(mctx, ednsopts[ednsoptscnt].value); - } - debug("Destroy memory"); if (memdebugging != 0) isc_mem_stats(mctx, stderr);