mirror of
https://github.com/espressif/openthread.git
synced 2026-10-03 14:27:38 +00:00
[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:
@@ -886,11 +886,13 @@ exit:
|
|||||||
|
|
||||||
Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage)
|
Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage)
|
||||||
{
|
{
|
||||||
Error error = kErrorAbort;
|
Error error = kErrorAbort;
|
||||||
uint16_t offset = aMessage.GetOffset();
|
OffsetRange offsetRange;
|
||||||
Tlv tlv;
|
Tlv tlv;
|
||||||
KeepAliveTlv keepAliveTlv;
|
KeepAliveTlv keepAliveTlv;
|
||||||
|
|
||||||
|
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||||
|
|
||||||
if (aHeader.GetType() == Dns::Header::kTypeResponse)
|
if (aHeader.GetType() == Dns::Header::kTypeResponse)
|
||||||
{
|
{
|
||||||
// A Keep Alive response message is allowed on a client from a sever.
|
// 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
|
// Parse and validate the Keep Alive Message
|
||||||
|
|
||||||
SuccessOrExit(aMessage.Read(offset, keepAliveTlv));
|
SuccessOrExit(aMessage.Read(offsetRange, keepAliveTlv));
|
||||||
offset += keepAliveTlv.GetSize();
|
VerifyOrExit(offsetRange.Contains(keepAliveTlv.GetSize()));
|
||||||
|
offsetRange.AdvanceOffset(keepAliveTlv.GetSize());
|
||||||
|
|
||||||
VerifyOrExit((keepAliveTlv.GetType() == KeepAliveTlv::kType) && keepAliveTlv.IsValid());
|
VerifyOrExit((keepAliveTlv.GetType() == KeepAliveTlv::kType) && keepAliveTlv.IsValid());
|
||||||
|
|
||||||
// Keep Alive message MUST contain only one Keep Alive TLV.
|
// Keep Alive message MUST contain only one Keep Alive TLV.
|
||||||
|
|
||||||
while (offset < aMessage.GetLength())
|
while (!offsetRange.IsEmpty())
|
||||||
{
|
{
|
||||||
SuccessOrExit(aMessage.Read(offset, tlv));
|
SuccessOrExit(aMessage.Read(offsetRange, tlv));
|
||||||
offset += tlv.GetSize();
|
|
||||||
|
VerifyOrExit(offsetRange.Contains(tlv.GetSize()));
|
||||||
|
offsetRange.AdvanceOffset(tlv.GetSize());
|
||||||
|
|
||||||
VerifyOrExit((tlv.GetType() != KeepAliveTlv::kType) && (tlv.GetType() != RetryDelayTlv::kType));
|
VerifyOrExit((tlv.GetType() != KeepAliveTlv::kType) && (tlv.GetType() != RetryDelayTlv::kType));
|
||||||
}
|
}
|
||||||
|
|
||||||
VerifyOrExit(offset == aMessage.GetLength());
|
|
||||||
|
|
||||||
if (aHeader.GetType() == Dns::Header::kTypeQuery)
|
if (aHeader.GetType() == Dns::Header::kTypeQuery)
|
||||||
{
|
{
|
||||||
if (IsServer())
|
if (IsServer())
|
||||||
|
|||||||
Reference in New Issue
Block a user