[mac] validate Header IE content length before reading IE structs (#13184)

GetThreadIe(), GetCslIe(), and GetTimeIe() read a fixed content struct
(VendorIeHeader / CslIe / TimeIe) at `ie + sizeof(HeaderIe)` after
matching the IE id, without first checking that the IE's Length field
covers that struct. FindPayloadIndex() only guarantees the IE header
plus its declared Length fit within the frame, so a matching IE whose
Length is shorter than the content struct (e.g. a zero-length vendor IE
placed at the end of the header-IE region) causes a read past the IE
content, and past the PSDU buffer when the IE ends at the frame
boundary.

Gate each content read on the IE Length being at least the
corresponding kIeContentSize before dereferencing the struct.
This commit is contained in:
Adil Burak Şen
2026-06-08 14:30:09 -07:00
committed by GitHub
parent 9b180d4c09
commit c801d291b3
2 changed files with 10 additions and 3 deletions
+3 -1
View File
@@ -1196,7 +1196,7 @@ const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
{
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
if (ie->GetId() == VendorIeHeader::kHeaderIeId)
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= VendorIeHeader::kIeContentSize))
{
const VendorIeHeader *vendorIe =
reinterpret_cast<const VendorIeHeader *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
@@ -1242,6 +1242,7 @@ const CslIe *Frame::GetCslIe(void) const
cur = GetHeaderIe(CslIe::kHeaderIeId);
VerifyOrExit(cur != nullptr);
VerifyOrExit(reinterpret_cast<const HeaderIe *>(cur)->GetLength() >= CslIe::kIeContentSize);
csl = reinterpret_cast<const CslIe *>(cur + sizeof(HeaderIe));
exit:
@@ -1270,6 +1271,7 @@ const TimeIe *Frame::GetTimeIe(void) const
cur = GetHeaderIe(VendorIeHeader::kHeaderIeId);
VerifyOrExit(cur != nullptr);
VerifyOrExit(reinterpret_cast<const HeaderIe *>(cur)->GetLength() >= TimeIe::kIeContentSize);
cur += sizeof(HeaderIe);
+7 -2
View File
@@ -211,7 +211,10 @@ public:
{
const uint8_t *ie = GetHeaderIe(RendezvousTimeIe::kHeaderIeId);
return (ie != nullptr) ? reinterpret_cast<const RendezvousTimeIe *>(ie + sizeof(HeaderIe)) : nullptr;
return (ie != nullptr &&
reinterpret_cast<const HeaderIe *>(ie)->GetLength() >= RendezvousTimeIe::kIeContentSize)
? reinterpret_cast<const RendezvousTimeIe *>(ie + sizeof(HeaderIe))
: nullptr;
}
/**
@@ -230,7 +233,9 @@ public:
{
const uint8_t *ie = GetThreadIe(ConnectionIe::kThreadIeSubtype);
return (ie != nullptr) ? reinterpret_cast<const ConnectionIe *>(ie + sizeof(HeaderIe)) : nullptr;
return (ie != nullptr && reinterpret_cast<const HeaderIe *>(ie)->GetLength() >= ConnectionIe::kIeContentSize)
? reinterpret_cast<const ConnectionIe *>(ie + sizeof(HeaderIe))
: nullptr;
}
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE