[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.
This commit is contained in:
Abtin Keshavarzian
2026-03-05 10:36:43 -06:00
committed by GitHub
parent 3ac4d4ac19
commit 271c50a044
+12 -9
View File
@@ -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())