mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-26 03:12:16 -04:00
Reject oversized RRsets at slab construction
dns_rdataslab_fromrdataset(), dns_rdataslab_merge() and
dns_rdataslab_subtract() summed per-record storage into an
unsigned int with no upper-bound check. An RRset whose total
encoded size exceeds DNS_RDATA_MAXLENGTH cannot fit in a DNS
message and is unservable; building its in-memory representation
only burns memory on data that will fail at response time, and at
the upper bound the running sum could in theory wrap.
Cap the running total at DNS_RDATA_MAXLENGTH and return ISC_R_NOSPACE
when exceeded. Update the qpdb cache memory-purge test to use a
record size that fits within the new limit.
Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit f9d24b1b85)
This commit is contained in:
parent
99c226576a
commit
2bbbd60de3
2 changed files with 22 additions and 5 deletions
|
|
@ -176,7 +176,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
|||
static unsigned char removed;
|
||||
struct xrdata *x = NULL;
|
||||
unsigned char *rawbuf = NULL;
|
||||
unsigned int buflen;
|
||||
uint32_t buflen;
|
||||
isc_result_t result;
|
||||
unsigned int nitems;
|
||||
unsigned int nalloc;
|
||||
|
|
@ -291,6 +291,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
|||
if (rdataset->type == dns_rdatatype_rrsig) {
|
||||
buflen++;
|
||||
}
|
||||
if (buflen - reservelen - 2 > DNS_RDATA_MAXLENGTH) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto free_rdatas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +312,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
|||
if (rdataset->type == dns_rdatatype_rrsig) {
|
||||
buflen++;
|
||||
}
|
||||
if (buflen - reservelen - 2 > DNS_RDATA_MAXLENGTH) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto free_rdatas;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that singleton types are actually singletons.
|
||||
|
|
@ -523,7 +531,8 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
|||
unsigned char **tslabp) {
|
||||
unsigned char *ocurrent = NULL, *ostart = NULL, *ncurrent = NULL;
|
||||
unsigned char *tstart = NULL, *tcurrent = NULL, *data = NULL;
|
||||
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
|
||||
unsigned int ocount, ncount, count, olength, tcount, length;
|
||||
uint32_t tlength;
|
||||
dns_rdata_t ordata = DNS_RDATA_INIT;
|
||||
dns_rdata_t nrdata = DNS_RDATA_INIT;
|
||||
bool added_something = false;
|
||||
|
|
@ -611,6 +620,9 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
|||
if (type == dns_rdatatype_rrsig) {
|
||||
tlength++;
|
||||
}
|
||||
if (tlength - reservelen - 2 > DNS_RDATA_MAXLENGTH) {
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
tcount++;
|
||||
nncount++;
|
||||
added_something = true;
|
||||
|
|
@ -787,7 +799,8 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
|
|||
unsigned int flags, unsigned char **tslabp) {
|
||||
unsigned char *mcurrent = NULL, *sstart = NULL, *scurrent = NULL;
|
||||
unsigned char *tstart = NULL, *tcurrent = NULL;
|
||||
unsigned int mcount, scount, rcount, count, tlength, tcount, i;
|
||||
unsigned int mcount, scount, rcount, count, tcount, i;
|
||||
uint32_t tlength;
|
||||
dns_rdata_t srdata = DNS_RDATA_INIT;
|
||||
dns_rdata_t mrdata = DNS_RDATA_INIT;
|
||||
#if DNS_RDATASET_FIXED
|
||||
|
|
@ -842,7 +855,10 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
|
|||
* This rdata isn't in the sslab, and thus isn't
|
||||
* being subtracted.
|
||||
*/
|
||||
tlength += (unsigned int)(mcurrent - mrdatabegin);
|
||||
tlength += (uint32_t)(mcurrent - mrdatabegin);
|
||||
if (tlength - reservelen - 2 > DNS_RDATA_MAXLENGTH) {
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
tcount++;
|
||||
} else {
|
||||
rcount++;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ ISC_LOOP_TEST_IMPL(overmempurge_bigrdata) {
|
|||
* cache size doesn't reach the "max".
|
||||
*/
|
||||
while (i-- > 0) {
|
||||
overmempurge_addrdataset(db, now, i, 50054, 65535, false);
|
||||
overmempurge_addrdataset(db, now, i, 50054,
|
||||
DNS_RDATA_MAXLENGTH - 8, false);
|
||||
if (verbose) {
|
||||
print_message("# inuse: %zd max: %zd\n",
|
||||
isc_mem_inuse(mctx2), maxcache);
|
||||
|
|
|
|||
Loading…
Reference in a new issue