From 271c50a0447db982cecacdafdf5768815ee70cce Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 5 Mar 2026 08:36:43 -0800 Subject: [PATCH] [dso] validate parsed TLV size in `ProcessKeepAliveMessage()` (#12609) This commit updates the `Dso::Connection::ProcessKeepAliveMessage()` method to use the `OffsetRange` class for parsing TLVs. This approach robustly validates the size of each parsed TLV against the remaining length of the received message. Utilizing `OffsetRange::Contains()` ensures that the reported TLV size via `GetSize()` does not exceed the available bytes in the message, preventing potential out-of-bounds reads or infinite loops when iterating over subsequent TLVs. --- src/core/net/dns_dso.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/core/net/dns_dso.cpp b/src/core/net/dns_dso.cpp index 577894485..1102bb1c7 100644 --- a/src/core/net/dns_dso.cpp +++ b/src/core/net/dns_dso.cpp @@ -886,11 +886,13 @@ exit: Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage) { - Error error = kErrorAbort; - uint16_t offset = aMessage.GetOffset(); + Error error = kErrorAbort; + OffsetRange offsetRange; Tlv tlv; KeepAliveTlv keepAliveTlv; + offsetRange.InitFromMessageOffsetToEnd(aMessage); + if (aHeader.GetType() == Dns::Header::kTypeResponse) { // A Keep Alive response message is allowed on a client from a sever. @@ -918,23 +920,24 @@ Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const // Parse and validate the Keep Alive Message - SuccessOrExit(aMessage.Read(offset, keepAliveTlv)); - offset += keepAliveTlv.GetSize(); + SuccessOrExit(aMessage.Read(offsetRange, keepAliveTlv)); + VerifyOrExit(offsetRange.Contains(keepAliveTlv.GetSize())); + offsetRange.AdvanceOffset(keepAliveTlv.GetSize()); VerifyOrExit((keepAliveTlv.GetType() == KeepAliveTlv::kType) && keepAliveTlv.IsValid()); // Keep Alive message MUST contain only one Keep Alive TLV. - while (offset < aMessage.GetLength()) + while (!offsetRange.IsEmpty()) { - SuccessOrExit(aMessage.Read(offset, tlv)); - offset += tlv.GetSize(); + SuccessOrExit(aMessage.Read(offsetRange, tlv)); + + VerifyOrExit(offsetRange.Contains(tlv.GetSize())); + offsetRange.AdvanceOffset(tlv.GetSize()); VerifyOrExit((tlv.GetType() != KeepAliveTlv::kType) && (tlv.GetType() != RetryDelayTlv::kType)); } - VerifyOrExit(offset == aMessage.GetLength()); - if (aHeader.GetType() == Dns::Header::kTypeQuery) { if (IsServer())