[PATCH] rdata: fix out-of-bounds write in NID and L64 tostruct()

Ismail Ramzi ismail at bugqore.com
Thu Jul 2 08:51:33 UTC 2026


tostruct_nid() and tostruct_l64() read the 16-bit Preference field with
uint16_fromregion(), which only reads region->base[0..1] and does not
advance the region. Unlike the sibling tostruct_lp(), they are missing
the following isc_region_consume(&region, 2), so at the memmove() the
region still has length 10 and still points at the start of the rdata:

	dns_rdata_toregion(rdata, &region);        /* region.length == 10 */
	nid->pref = uint16_fromregion(&region);    /* does not consume */
	memmove(nid->nid, region.base, region.length);

dns_rdata_nid_t.nid and dns_rdata_l64_t.l64 are fixed 8-byte trailing
arrays, and fromwire/fromtext pin rdata->length to exactly 10 for these
types. The memmove therefore copies 10 bytes into an 8-byte array, a
2-byte out-of-bounds write past the caller-supplied structure, and also
stores the wrong bytes (the two Preference octets land in nid[0..1]
instead of the Node ID).

This is reachable from dns_rdata_tostruct() on any valid NID (RFC 6742,
type 104) or L64 (type 106) record parsed from the network or a zone
file.

Add the missing isc_region_consume(&region, 2) so that exactly the
8-byte locator is copied, matching tostruct_lp().

Signed-off-by: Ismail Ramzi <ismail at bugqore.com>
---
diff --git a/lib/dns/rdata/generic/l64_106.c b/lib/dns/rdata/generic/l64_106.c
index 5e9b42e..fb00ea1 100644
--- a/lib/dns/rdata/generic/l64_106.c
+++ b/lib/dns/rdata/generic/l64_106.c
@@ -151,6 +151,7 @@ tostruct_l64(ARGS_TOSTRUCT) {
 
 	dns_rdata_toregion(rdata, &region);
 	l64->pref = uint16_fromregion(&region);
+	isc_region_consume(&region, 2);
 	memmove(l64->l64, region.base, region.length);
 	return ISC_R_SUCCESS;
 }
diff --git a/lib/dns/rdata/generic/nid_104.c b/lib/dns/rdata/generic/nid_104.c
index 80d0533..ce53a8f 100644
--- a/lib/dns/rdata/generic/nid_104.c
+++ b/lib/dns/rdata/generic/nid_104.c
@@ -151,6 +151,7 @@ tostruct_nid(ARGS_TOSTRUCT) {
 
 	dns_rdata_toregion(rdata, &region);
 	nid->pref = uint16_fromregion(&region);
+	isc_region_consume(&region, 2);
 	memmove(nid->nid, region.base, region.length);
 	return ISC_R_SUCCESS;
 }


More information about the bind-users mailing list