- Fix that when a partial EDNS option is in a query, the

response is a more RFC conformant FORMERR, since the EDNS
  option is malformed. Also fix to have an EDNS size for
  the reply error encoding for failed EDNS parse of the query.
  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
This commit is contained in:
W.C.A. Wijngaards
2026-09-03 17:20:35 +02:00
parent 11900cc2b0
commit bd210d124b
4 changed files with 34 additions and 3 deletions
+2
View File
@@ -1706,6 +1706,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
reply_edns.edns_version = EDNS_ADVERTISED_VERSION;
reply_edns.udp_size = EDNS_ADVERTISED_SIZE;
error_encode(c->buffer, ret, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns);
+5
View File
@@ -13,6 +13,11 @@
udpsize, the reply is truncated with TC and fix for the
rcode in that short reply to be a sensible rcode.
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
- Fix that when a partial EDNS option is in a query, the
response is a more RFC conformant FORMERR, since the EDNS
option is malformed. Also fix to have an EDNS size for
the reply error encoding for failed EDNS parse of the query.
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
2 September 2026: Wouter
- Fix to not commit to have_zone at apply AXFR time for auth
+18
View File
@@ -53,4 +53,22 @@ SECTION QUESTION
test. IN TXT
ENTRY_END
; Check an EDNS option with a too short content
; The EDNS OPT rdata is too short, for the option opt_len.
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
test. IN TXT
SECTION ADDITIONAL
. 32768 CLASS1230 OPT \# 04 00 0a 00 08
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA DO FORMERR
SECTION QUESTION
test. IN TXT
ENTRY_END
SCENARIO_END
+9 -3
View File
@@ -974,7 +974,6 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
}
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
@@ -984,8 +983,10 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
rdata_ptr += 4;
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
if(opt_len > rdata_len) {
/* option code partial */
return LDNS_RCODE_FORMERR;
}
/* handle parse time edns options here */
switch(opt_code) {
@@ -1160,6 +1161,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
rdata_len -= opt_len;
i++;
}
/* partial content (i.e. rdata len 3) is FORMERR */
if(rdata_len > 0 && rdata_len <= 3)
return LDNS_RCODE_FORMERR;
return LDNS_RCODE_NOERROR;
}
@@ -1240,6 +1244,8 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
/* This is lenient for partially broken messages
* from upstream. With a partial EDNS option. */
if(!edns_opt_list_append(&edns->opt_list_in,
opt_code, opt_len, rdata_ptr, region)) {