mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-10-19 11:19:34 +00:00
Fix double-free in blockdata_expand().
If blockdata_expand() fails, it frees the existing block chain and returns zero. Each call to blockdata_expand() checks for the zero return, and calls blockdata_free() as part of its clean-up, resulting in a double-free and crash. Thanks to fallrig for finding this.
This commit is contained in:
2 files changed
+11
-25
No files matched your search
+1
-1
@@ -132,7 +132,7 @@ int blockdata_expand(struct blockdata *block, size_t oldlen, char *data, size_t
|
||||
/* find size of current final block */
|
||||
for (b = block; oldlen > KEYBLOCK_LEN && b; b = b->next, oldlen -= KEYBLOCK_LEN);
|
||||
|
||||
/* chain to short for length, something is broken */
|
||||
/* chain too short for length, something is broken */
|
||||
if (oldlen > KEYBLOCK_LEN)
|
||||
{
|
||||
blockdata_free(block);
|
||||
|
||||
+10
-24
@@ -585,11 +585,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *sub
|
||||
{
|
||||
len = to_wire(daemon->workspacename);
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, daemon->workspacename, len))
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
addr.rrblock.datalen += len;
|
||||
}
|
||||
}
|
||||
@@ -607,11 +604,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *sub
|
||||
int secflag = 0;
|
||||
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p, 20))
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
addr.rrblock.datalen += 20;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
@@ -942,10 +936,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
{
|
||||
/* Copy the rest of the RR and end. */
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, endrr - p1))
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
addr.rrblock.datalen += endrr - p1;
|
||||
}
|
||||
else if (desc == 0)
|
||||
@@ -962,11 +954,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
|
||||
len = to_wire(name);
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, name, len))
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
addr.rrblock.datalen += len;
|
||||
}
|
||||
else
|
||||
@@ -976,11 +965,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
desc = endrr - p1;
|
||||
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, desc))
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
addr.rrblock.datalen += desc;
|
||||
p1 += desc;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user