mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 02:17:47 +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;
|
||||
}
|
||||
|
||||
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 *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 * end = reinterpret_cast<const Tlv *>(mTlvs + mLength);
|
||||
|
||||
VerifyOrExit(IsValid(), error = OT_ERROR_PARSE);
|
||||
|
||||
while (cur < end)
|
||||
{
|
||||
switch (cur->GetType())
|
||||
@@ -578,6 +595,7 @@ otError Dataset::ApplyConfiguration(Instance &aInstance) const
|
||||
{
|
||||
const NetworkNameTlv *name = static_cast<const NetworkNameTlv *>(cur);
|
||||
otNetworkName networkName;
|
||||
|
||||
memcpy(networkName.m8, name->GetNetworkName(), name->GetLength());
|
||||
networkName.m8[name->GetLength()] = '\0';
|
||||
|
||||
|
||||
@@ -69,6 +69,14 @@ public:
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -216,7 +224,8 @@ public:
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -146,8 +146,9 @@ void DatasetManager::HandleDetach(void)
|
||||
Restore();
|
||||
}
|
||||
|
||||
void DatasetManager::Set(const Dataset &aDataset)
|
||||
otError DatasetManager::Set(const Dataset &aDataset)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
const Timestamp *timestamp;
|
||||
int compare;
|
||||
|
||||
@@ -160,7 +161,7 @@ void DatasetManager::Set(const Dataset &aDataset)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void DatasetManager::HandleTimer(void)
|
||||
|
||||
@@ -116,7 +116,8 @@ public:
|
||||
/**
|
||||
* 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;
|
||||
@@ -157,8 +158,11 @@ protected:
|
||||
*
|
||||
* @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.
|
||||
|
||||
@@ -300,7 +300,7 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
|
||||
offset += sizeof(Tlv) + data.tlv.GetLength();
|
||||
}
|
||||
|
||||
Set(dataset);
|
||||
VerifyOrExit(Set(dataset) == OT_ERROR_NONE, state = StateTlv::kReject);
|
||||
netif.GetNetworkDataLeader().IncrementVersion();
|
||||
netif.GetNetworkDataLeader().IncrementStableVersion();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,51 @@
|
||||
namespace ot {
|
||||
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 rval = true;
|
||||
|
||||
@@ -166,6 +166,16 @@ public:
|
||||
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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user