mirror of
https://github.com/espressif/openthread.git
synced 2026-08-22 10:29:52 +00:00
[lowpan] validate received fragment headers (#2038)
Credit to OSS-Fuzz.
This commit is contained in:
@@ -1175,5 +1175,26 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError FragmentHeader::Init(const uint8_t *aFrame, uint8_t aFrameLength)
|
||||
{
|
||||
otError error = OT_ERROR_PARSE;
|
||||
|
||||
VerifyOrExit(aFrameLength >= sizeof(mDispatchSize) + sizeof(mTag));
|
||||
memcpy(&mDispatchSize, aFrame, sizeof(mDispatchSize) + sizeof(mTag));
|
||||
aFrame += sizeof(mDispatchSize) + sizeof(mTag);
|
||||
aFrameLength -= sizeof(mDispatchSize) + sizeof(mTag);
|
||||
|
||||
if (IsOffsetPresent())
|
||||
{
|
||||
VerifyOrExit(aFrameLength >= sizeof(mOffset));
|
||||
mOffset = *aFrame++;
|
||||
}
|
||||
|
||||
error = OT_ERROR_NONE;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Lowpan
|
||||
} // namespace ot
|
||||
|
||||
@@ -397,6 +397,18 @@ public:
|
||||
*/
|
||||
void Init(void) { mDispatchSize = HostSwap16(kDispatch); }
|
||||
|
||||
/**
|
||||
* This method initializes the fragment header from a frame @p aFrame.
|
||||
*
|
||||
* @param[in] aFrame The pointer to the frame.
|
||||
* @param[in] aFrameLength The length of the frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Fragment Header initialized successfully.
|
||||
* @retval OT_ERROR_PARSE Fragment header could not be initialized from @p aFrame (e.g., frame not long enough).
|
||||
*
|
||||
*/
|
||||
otError Init(const uint8_t *aFrame, uint8_t aFrameLength);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the header is a Fragment Header.
|
||||
*
|
||||
@@ -412,9 +424,15 @@ public:
|
||||
* @returns The Fragment Header length in bytes.
|
||||
*
|
||||
*/
|
||||
uint8_t GetHeaderLength(void) {
|
||||
return (HostSwap16(mDispatchSize) & kOffset) ? sizeof(*this) : sizeof(*this) - sizeof(mOffset);
|
||||
}
|
||||
uint8_t GetHeaderLength(void) const { return IsOffsetPresent() ? sizeof(*this) : sizeof(*this) - sizeof(mOffset); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Offset field is present.
|
||||
*
|
||||
* @returns TRUE if the Offset field is present, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsOffsetPresent(void) const { return (HostSwap16(mDispatchSize) & kOffset) != 0; }
|
||||
|
||||
/**
|
||||
* This method returns the Datagram Size value.
|
||||
@@ -422,7 +440,7 @@ public:
|
||||
* @returns The Datagram Size value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDatagramSize(void) { return HostSwap16(mDispatchSize) & kSizeMask; }
|
||||
uint16_t GetDatagramSize(void) const { return HostSwap16(mDispatchSize) & kSizeMask; }
|
||||
|
||||
/**
|
||||
* This method sets the Datagram Size value.
|
||||
@@ -440,7 +458,7 @@ public:
|
||||
* @returns The Datagram Tag value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDatagramTag(void) { return HostSwap16(mTag); }
|
||||
uint16_t GetDatagramTag(void) const { return HostSwap16(mTag); }
|
||||
|
||||
/**
|
||||
* This method sets the Datagram Tag value.
|
||||
@@ -456,7 +474,7 @@ public:
|
||||
* @returns The Datagram Offset value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDatagramOffset(void) { return (HostSwap16(mDispatchSize) & kOffset) ? static_cast<uint16_t>(mOffset) * 8 : 0; }
|
||||
uint16_t GetDatagramOffset(void) const { return IsOffsetPresent() ? static_cast<uint16_t>(mOffset) * 8 : 0; }
|
||||
|
||||
/**
|
||||
* This method sets the Datagram Offset value.
|
||||
|
||||
@@ -1998,34 +1998,34 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
{
|
||||
ThreadNetif &netif = GetNetif();
|
||||
otError error = OT_ERROR_NONE;
|
||||
Lowpan::FragmentHeader *fragmentHeader = reinterpret_cast<Lowpan::FragmentHeader *>(aFrame);
|
||||
uint16_t datagramLength = fragmentHeader->GetDatagramSize();
|
||||
uint16_t datagramTag = fragmentHeader->GetDatagramTag();
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
Message *message = NULL;
|
||||
int headerLength;
|
||||
|
||||
if (fragmentHeader->GetDatagramOffset() == 0)
|
||||
{
|
||||
aFrame += fragmentHeader->GetHeaderLength();
|
||||
aFrameLength -= fragmentHeader->GetHeaderLength();
|
||||
// Check the fragment header
|
||||
VerifyOrExit(fragmentHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_DROP);
|
||||
aFrame += fragmentHeader.GetHeaderLength();
|
||||
aFrameLength -= fragmentHeader.GetHeaderLength();
|
||||
|
||||
if (fragmentHeader.GetDatagramOffset() == 0)
|
||||
{
|
||||
VerifyOrExit((message = GetInstance().mMessagePool.New(Message::kTypeIp6, 0)) != NULL,
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
message->SetLinkSecurityEnabled(aMessageInfo.mLinkSecurity);
|
||||
message->SetPanId(aMessageInfo.mPanId);
|
||||
message->AddRss(aMessageInfo.mRss);
|
||||
headerLength = netif.GetLowpan().Decompress(*message, aMacSource, aMacDest, aFrame, aFrameLength,
|
||||
datagramLength);
|
||||
fragmentHeader.GetDatagramSize());
|
||||
VerifyOrExit(headerLength > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
aFrame += headerLength;
|
||||
aFrameLength -= static_cast<uint8_t>(headerLength);
|
||||
|
||||
VerifyOrExit(datagramLength >= message->GetOffset() + aFrameLength, error = OT_ERROR_PARSE);
|
||||
VerifyOrExit(fragmentHeader.GetDatagramSize() >= message->GetOffset() + aFrameLength, error = OT_ERROR_PARSE);
|
||||
|
||||
SuccessOrExit(error = message->SetLength(datagramLength));
|
||||
SuccessOrExit(error = message->SetLength(fragmentHeader.GetDatagramSize()));
|
||||
|
||||
message->SetDatagramTag(datagramTag);
|
||||
message->SetDatagramTag(fragmentHeader.GetDatagramTag());
|
||||
message->SetTimeout(kReassemblyTimeout);
|
||||
|
||||
// copy Fragment
|
||||
@@ -2053,16 +2053,13 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
}
|
||||
else
|
||||
{
|
||||
aFrame += fragmentHeader->GetHeaderLength();
|
||||
aFrameLength -= fragmentHeader->GetHeaderLength();
|
||||
|
||||
for (message = mReassemblyList.GetHead(); message; message = message->GetNext())
|
||||
{
|
||||
// Security Check: only consider reassembly buffers that had the same Security Enabled setting.
|
||||
if (message->GetLength() == datagramLength &&
|
||||
message->GetDatagramTag() == datagramTag &&
|
||||
message->GetOffset() == fragmentHeader->GetDatagramOffset() &&
|
||||
message->GetOffset() + aFrameLength <= datagramLength &&
|
||||
if (message->GetLength() == fragmentHeader.GetDatagramSize() &&
|
||||
message->GetDatagramTag() == fragmentHeader.GetDatagramTag() &&
|
||||
message->GetOffset() == fragmentHeader.GetDatagramOffset() &&
|
||||
message->GetOffset() + aFrameLength <= fragmentHeader.GetDatagramSize() &&
|
||||
message->IsLinkSecurityEnabled() == aMessageInfo.mLinkSecurity)
|
||||
{
|
||||
break;
|
||||
@@ -2116,9 +2113,9 @@ exit:
|
||||
aFrameLength,
|
||||
aMacSource.ToString(srcStringBuffer, sizeof(srcStringBuffer)),
|
||||
aMacDest.ToString(dstStringBuffer, sizeof(dstStringBuffer)),
|
||||
datagramTag,
|
||||
fragmentHeader->GetDatagramOffset(),
|
||||
datagramLength,
|
||||
fragmentHeader.GetDatagramTag(),
|
||||
fragmentHeader.GetDatagramOffset(),
|
||||
fragmentHeader.GetDatagramSize(),
|
||||
aMessageInfo.mLinkSecurity ? "yes" : "no"
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user