mirror of
https://github.com/espressif/openthread.git
synced 2026-10-02 05:47:40 +00:00
[dataset] validate TLVs when applying configuration (#2680)
Credit to OSS-Fuzz.
This commit is contained in:
@@ -60,6 +60,21 @@ void Dataset::Clear(void)
|
|||||||
mLength = 0;
|
mLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Dataset::IsValid(void) const
|
||||||
|
{
|
||||||
|
bool rval = true;
|
||||||
|
const Tlv *cur = reinterpret_cast<const Tlv *>(mTlvs);
|
||||||
|
const Tlv *end = reinterpret_cast<const Tlv *>(mTlvs + mLength);
|
||||||
|
|
||||||
|
for (; cur < end; cur = cur->GetNext())
|
||||||
|
{
|
||||||
|
VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end && Tlv::IsValid(*cur), rval = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
Tlv *Dataset::Get(Tlv::Type aType)
|
Tlv *Dataset::Get(Tlv::Type aType)
|
||||||
{
|
{
|
||||||
Tlv *cur = reinterpret_cast<Tlv *>(mTlvs);
|
Tlv *cur = reinterpret_cast<Tlv *>(mTlvs);
|
||||||
@@ -523,6 +538,8 @@ otError Dataset::ApplyConfiguration(Instance &aInstance) const
|
|||||||
const Tlv * cur = reinterpret_cast<const Tlv *>(mTlvs);
|
const Tlv * cur = reinterpret_cast<const Tlv *>(mTlvs);
|
||||||
const Tlv * end = reinterpret_cast<const Tlv *>(mTlvs + mLength);
|
const Tlv * end = reinterpret_cast<const Tlv *>(mTlvs + mLength);
|
||||||
|
|
||||||
|
VerifyOrExit(IsValid(), error = OT_ERROR_PARSE);
|
||||||
|
|
||||||
while (cur < end)
|
while (cur < end)
|
||||||
{
|
{
|
||||||
switch (cur->GetType())
|
switch (cur->GetType())
|
||||||
@@ -578,6 +595,7 @@ otError Dataset::ApplyConfiguration(Instance &aInstance) const
|
|||||||
{
|
{
|
||||||
const NetworkNameTlv *name = static_cast<const NetworkNameTlv *>(cur);
|
const NetworkNameTlv *name = static_cast<const NetworkNameTlv *>(cur);
|
||||||
otNetworkName networkName;
|
otNetworkName networkName;
|
||||||
|
|
||||||
memcpy(networkName.m8, name->GetNetworkName(), name->GetLength());
|
memcpy(networkName.m8, name->GetNetworkName(), name->GetLength());
|
||||||
networkName.m8[name->GetLength()] = '\0';
|
networkName.m8[name->GetLength()] = '\0';
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method indicates whether or not the dataset appears to be well-formed.
|
||||||
|
*
|
||||||
|
* @returns TRUE if the dataset appears to be well-formed, FALSE otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool IsValid(void) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a pointer to the TLV.
|
* This method returns a pointer to the TLV.
|
||||||
*
|
*
|
||||||
@@ -216,7 +224,8 @@ public:
|
|||||||
*
|
*
|
||||||
* @param[in] aInstance A reference to the OpenThread instance.
|
* @param[in] aInstance A reference to the OpenThread instance.
|
||||||
*
|
*
|
||||||
* @retval OT_ERROR_NONE Successfully applied configuration.
|
* @retval OT_ERROR_NONE Successfully applied configuration.
|
||||||
|
* @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
otError ApplyConfiguration(Instance &aInstance) const;
|
otError ApplyConfiguration(Instance &aInstance) const;
|
||||||
|
|||||||
@@ -146,8 +146,9 @@ void DatasetManager::HandleDetach(void)
|
|||||||
Restore();
|
Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatasetManager::Set(const Dataset &aDataset)
|
otError DatasetManager::Set(const Dataset &aDataset)
|
||||||
{
|
{
|
||||||
|
otError error = OT_ERROR_NONE;
|
||||||
const Timestamp *timestamp;
|
const Timestamp *timestamp;
|
||||||
int compare;
|
int compare;
|
||||||
|
|
||||||
@@ -160,7 +161,7 @@ void DatasetManager::Set(const Dataset &aDataset)
|
|||||||
|
|
||||||
if (mLocal.GetType() == Tlv::kActiveTimestamp)
|
if (mLocal.GetType() == Tlv::kActiveTimestamp)
|
||||||
{
|
{
|
||||||
aDataset.ApplyConfiguration(GetInstance());
|
SuccessOrExit(error = aDataset.ApplyConfiguration(GetInstance()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +183,9 @@ void DatasetManager::Set(const Dataset &aDataset)
|
|||||||
{
|
{
|
||||||
mTimer.Start(1000);
|
mTimer.Start(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatasetManager::HandleTimer(void)
|
void DatasetManager::HandleTimer(void)
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* This method applies the Active or Pending Dataset to the Thread interface.
|
* This method applies the Active or Pending Dataset to the Thread interface.
|
||||||
*
|
*
|
||||||
* @retval OT_ERROR_NONE Successfully applied configuration.
|
* @retval OT_ERROR_NONE Successfully applied configuration.
|
||||||
|
* @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
otError ApplyConfiguration(void) const;
|
otError ApplyConfiguration(void) const;
|
||||||
@@ -157,8 +158,11 @@ protected:
|
|||||||
*
|
*
|
||||||
* @param[in] aDataset The Operational Dataset.
|
* @param[in] aDataset The Operational Dataset.
|
||||||
*
|
*
|
||||||
|
* @retval OT_ERROR_NONE Successfully applied configuration.
|
||||||
|
* @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void Set(const Dataset &aDataset);
|
otError Set(const Dataset &aDataset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the Operational Dataset for the partition.
|
* This method sets the Operational Dataset for the partition.
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
|
|||||||
offset += sizeof(Tlv) + data.tlv.GetLength();
|
offset += sizeof(Tlv) + data.tlv.GetLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set(dataset);
|
VerifyOrExit(Set(dataset) == OT_ERROR_NONE, state = StateTlv::kReject);
|
||||||
netif.GetNetworkDataLeader().IncrementVersion();
|
netif.GetNetworkDataLeader().IncrementVersion();
|
||||||
netif.GetNetworkDataLeader().IncrementStableVersion();
|
netif.GetNetworkDataLeader().IncrementStableVersion();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,51 @@
|
|||||||
namespace ot {
|
namespace ot {
|
||||||
namespace MeshCoP {
|
namespace MeshCoP {
|
||||||
|
|
||||||
|
bool Tlv::IsValid(const Tlv &aTlv)
|
||||||
|
{
|
||||||
|
bool rval = true;
|
||||||
|
|
||||||
|
switch (aTlv.GetType())
|
||||||
|
{
|
||||||
|
case Tlv::kChannel:
|
||||||
|
rval = static_cast<const ChannelTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kPanId:
|
||||||
|
rval = static_cast<const PanIdTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kExtendedPanId:
|
||||||
|
rval = static_cast<const ExtendedPanIdTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kNetworkName:
|
||||||
|
rval = static_cast<const NetworkNameTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kNetworkMasterKey:
|
||||||
|
rval = static_cast<const NetworkMasterKeyTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kPSKc:
|
||||||
|
rval = static_cast<const PSKcTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kMeshLocalPrefix:
|
||||||
|
rval = static_cast<const MeshLocalPrefixTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Tlv::kSecurityPolicy:
|
||||||
|
rval = static_cast<const SecurityPolicyTlv &>(aTlv).IsValid();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
bool SteeringDataTlv::IsCleared(void) const
|
bool SteeringDataTlv::IsCleared(void) const
|
||||||
{
|
{
|
||||||
bool rval = true;
|
bool rval = true;
|
||||||
|
|||||||
@@ -166,6 +166,16 @@ public:
|
|||||||
return ot::Tlv::GetValueOffset(aMessage, static_cast<uint8_t>(aType), aOffset, aLength);
|
return ot::Tlv::GetValueOffset(aMessage, static_cast<uint8_t>(aType), aOffset, aLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static method indicates whether a TLV appears to be well-formed.
|
||||||
|
*
|
||||||
|
* @param[in] aTlv A reference to the TLV.
|
||||||
|
*
|
||||||
|
* @returns TRUE if the TLV appears to be well-formed, FALSE otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool IsValid(const Tlv &aTlv);
|
||||||
|
|
||||||
} OT_TOOL_PACKED_END;
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user