Handle error return from blockdata_alloc in all cases.

This commit is contained in:
Simon Kelley
2024-11-02 22:37:51 +00:00
parent 09a1839272
commit 7b7aef903e

View File

@@ -352,8 +352,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->stash = saved_question; forward->stash = saved_question;
saved_question = NULL; /* don't free */ saved_question = NULL; /* don't free */
} }
else else if (!(forward->stash = blockdata_alloc((char *)header, plen)))
forward->stash = blockdata_alloc((char *)header, plen); goto reply; /* no mem. return REFUSED */
forward->stash_len = plen; forward->stash_len = plen;
forward->frec_src.log_id = daemon->log_id; forward->frec_src.log_id = daemon->log_id;
@@ -995,7 +995,6 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
answer aside, whilst we get that. */ answer aside, whilst we get that. */
if (STAT_ISEQUAL(status, STAT_NEED_DS) || STAT_ISEQUAL(status, STAT_NEED_KEY)) if (STAT_ISEQUAL(status, STAT_NEED_DS) || STAT_ISEQUAL(status, STAT_NEED_KEY))
{ {
struct frec *new = NULL;
struct blockdata *stash; struct blockdata *stash;
/* Now save reply pending receipt of key data */ /* Now save reply pending receipt of key data */
@@ -1003,8 +1002,9 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
{ {
/* validate routines leave name of required record in daemon->keyname */ /* validate routines leave name of required record in daemon->keyname */
unsigned int flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY; unsigned int flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY;
struct frec *old;
if ((new = lookup_frec(daemon->keyname, forward->class, -1, -1, flags, flags))) if ((old = lookup_frec(daemon->keyname, forward->class, -1, -1, flags, flags)))
{ {
/* This is tricky; it detects loops in the dependency /* This is tricky; it detects loops in the dependency
graph for DNSSEC validation, say validating A requires DS B graph for DNSSEC validation, say validating A requires DS B
@@ -1015,18 +1015,18 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
can form a cycle, and under certain circumstances that can lock us in can form a cycle, and under certain circumstances that can lock us in
an infinite loop. Here we transform the situation into ABANDONED. */ an infinite loop. Here we transform the situation into ABANDONED. */
struct frec *f; struct frec *f;
for (f = new; f; f = f->blocking_query) for (f = old; f; f = f->blocking_query)
if (f == forward) if (f == forward)
break; break;
if (!f) if (!f)
{ {
forward->next_dependent = new->dependent; forward->next_dependent = old->dependent;
new->dependent = forward; old->dependent = forward;
/* Make consistent, only replace query copy with unvalidated answer /* Make consistent, only replace query copy with unvalidated answer
when we set ->blocking_query. */ when we set ->blocking_query. */
blockdata_free(forward->stash); blockdata_free(forward->stash);
forward->blocking_query = new; forward->blocking_query = old;
forward->stash_len = plen; forward->stash_len = plen;
forward->stash = stash; forward->stash = stash;
return; return;
@@ -1043,6 +1043,8 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
size_t nn; size_t nn;
int serverind, fd; int serverind, fd;
struct randfd_list *rfds = NULL; struct randfd_list *rfds = NULL;
struct frec *new = NULL;
struct blockdata *newstash = NULL;
/* Make sure we don't expire and free the orig frec during the /* Make sure we don't expire and free the orig frec during the
allocation of a new one: third arg of get_new_frec() does that. */ allocation of a new one: third arg of get_new_frec() does that. */
@@ -1052,6 +1054,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
daemon->keyname, forward->class, daemon->keyname, forward->class,
STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz)) && STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz)) &&
(fd = allocate_rfd(&rfds, server)) != -1 && (fd = allocate_rfd(&rfds, server)) != -1 &&
(newstash = blockdata_alloc((char *)header, nn)) &&
(new = get_new_frec(now, server, 1))) (new = get_new_frec(now, server, 1)))
{ {
struct frec *next = new->next; struct frec *next = new->next;
@@ -1081,7 +1084,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
new->new_id = get_id(); new->new_id = get_id();
header->id = htons(new->new_id); header->id = htons(new->new_id);
/* Save query for retransmission and de-dup */ /* Save query for retransmission and de-dup */
new->stash = blockdata_alloc((char *)header, nn); new->stash = newstash;
new->stash_len = nn; new->stash_len = nn;
if (daemon->fast_retry_time != 0) if (daemon->fast_retry_time != 0)
new->forward_timestamp = dnsmasq_milliseconds(); new->forward_timestamp = dnsmasq_milliseconds();
@@ -1104,7 +1107,9 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
return; return;
} }
free_rfds(&rfds); /* error unwind */ /* error unwind */
free_rfds(&rfds);
blockdata_free(newstash);
} }
blockdata_free(stash); /* don't leak this on failure. */ blockdata_free(stash); /* don't leak this on failure. */