Summary
Possible infinite loop in subsys/net/lib/dns/dns_pack.c
int dns_copy_qname(uint8_t *buf, uint16_t *len, uint16_t size,
struct dns_msg_t *dns_msg, uint16_t pos)
{
uint16_t msg_size = dns_msg->msg_size;
uint8_t *msg = dns_msg->msg;
uint16_t lb_size;
int rc = -EINVAL;
*len = 0U;
while (1) {
if (pos >= msg_size) {
rc = -ENOMEM;
break;
}
lb_size = msg[pos];
/* pointer */
if (lb_size > DNS_LABEL_MAX_SIZE) {
uint8_t mask = DNS_LABEL_MAX_SIZE;
if (pos + 1 >= msg_size) {
rc = -ENOMEM;
break;
}
/* See: RFC 1035, 4.1.4. Message compression */
pos = ((msg[pos] & mask) << 8) + msg[pos + 1];
continue;
}
If a malicious packet that causes the assignment of "pos" to be assigned to the same value it already contains, or a chain of pos assignments jumping back and forth causing the same position to be visited again, there will be an infinite loop. Read https://datatracker.ietf.org/doc/html/rfc9267#section-2 for more info on the same attack.
Impact
A denial-of-service issue that could cause an infinite loop.
Fix Recommendation
Have a separate variable containing the target position of the last jump (initialised to pos). Before every jump, make sure the target of the next jump is strictly less than the target of the previous jump. Then assign the new location to that variable and "jump" to the new target.
Note: the if (lb_size > DNS_LABEL_MAX_SIZE) {
condition is also wrong according to RFC 9267, it should check that the two top bits are 0b11. If they are 0b10 or 0b01, the packet should be discarded.
Also note that the function dns_unpack_name does more or less the exact same thing (but copying to a printable string rather than a sequence of length-prefixed labels), but with a completely different code style. I suggest that the core logic of these functions are merged into one function to make the security analysis of that file easier. That second function has protection against infinite loops by putting an upper bound on loops using the loop_check variable.
Patches
For more information
If you have any questions or comments about this advisory:
embargo: 2025-06-07
Summary
Possible infinite loop in subsys/net/lib/dns/dns_pack.c
If a malicious packet that causes the assignment of "pos" to be assigned to the same value it already contains, or a chain of pos assignments jumping back and forth causing the same position to be visited again, there will be an infinite loop. Read https://datatracker.ietf.org/doc/html/rfc9267#section-2 for more info on the same attack.
Impact
A denial-of-service issue that could cause an infinite loop.
Fix Recommendation
Have a separate variable containing the target position of the last jump (initialised to pos). Before every jump, make sure the target of the next jump is strictly less than the target of the previous jump. Then assign the new location to that variable and "jump" to the new target.
Note: the
if (lb_size > DNS_LABEL_MAX_SIZE) {
condition is also wrong according to RFC 9267, it should check that the two top bits are 0b11. If they are 0b10 or 0b01, the packet should be discarded.Also note that the function dns_unpack_name does more or less the exact same thing (but copying to a printable string rather than a sequence of length-prefixed labels), but with a completely different code style. I suggest that the core logic of these functions are merged into one function to make the security analysis of that file easier. That second function has protection against infinite loops by putting an upper bound on loops using the loop_check variable.
Patches
For more information
If you have any questions or comments about this advisory:
embargo: 2025-06-07