Skip to content

Commit 685e239

Browse files
authored
Add boundary checks to prevent memory safety issues in BgpLayer::getHeaderLen (#1954)
1 parent 722ace3 commit 685e239

13 files changed

+129
-52
lines changed

Packet++/header/BgpLayer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ namespace pcpp
113113
}
114114

115115
void setBgpFields(size_t messageLen = 0);
116+
117+
bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend) override;
118+
119+
bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten) override;
116120
};
117121

118122
/// @class BgpOpenMessageLayer

Packet++/src/BgpLayer.cpp

Lines changed: 102 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Logger.h"
44
#include "BgpLayer.h"
5+
#include "Packet.h"
56
#include "EndianPortable.h"
67
#include "GeneralUtils.h"
78

@@ -117,6 +118,56 @@ namespace pcpp
117118
}
118119
}
119120

121+
bool BgpLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend)
122+
{
123+
if (m_Packet != nullptr)
124+
{
125+
int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
126+
const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
127+
128+
if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) > static_cast<ptrdiff_t>(rawPacketLen))
129+
{
130+
PCPP_LOG_ERROR("Requested offset is larger than total packet length");
131+
return false;
132+
}
133+
134+
if (m_NextLayer != nullptr && static_cast<ptrdiff_t>(offsetInLayer) > m_NextLayer->getData() - m_Data)
135+
{
136+
PCPP_LOG_ERROR("Requested offset exceeds current layer's boundary");
137+
return false;
138+
}
139+
}
140+
141+
return Layer::extendLayer(offsetInLayer, numOfBytesToExtend);
142+
}
143+
144+
bool BgpLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten)
145+
{
146+
if (m_Packet != nullptr)
147+
{
148+
int rawPacketLen = m_Packet->getRawPacket()->getRawDataLen();
149+
const uint8_t* rawPacketPtr = m_Packet->getRawPacket()->getRawData();
150+
151+
if (m_Data - rawPacketPtr + static_cast<ptrdiff_t>(offsetInLayer) +
152+
static_cast<ptrdiff_t>(numOfBytesToShorten) >
153+
static_cast<ptrdiff_t>(rawPacketLen))
154+
{
155+
PCPP_LOG_ERROR("Requested number of bytes to shorten is larger than total packet length");
156+
return false;
157+
}
158+
159+
if (m_NextLayer != nullptr &&
160+
static_cast<ptrdiff_t>(offsetInLayer) + static_cast<ptrdiff_t>(numOfBytesToShorten) >
161+
m_NextLayer->getData() - m_Data)
162+
{
163+
PCPP_LOG_ERROR("Requested number of bytes to shorten exceeds current layer's boundary");
164+
return false;
165+
}
166+
}
167+
168+
return Layer::shortenLayer(offsetInLayer, numOfBytesToShorten);
169+
}
170+
120171
// ~~~~~~~~~~~~~~~~~~~~
121172
// BgpOpenMessageLayer
122173
// ~~~~~~~~~~~~~~~~~~~~
@@ -261,29 +312,32 @@ namespace pcpp
261312
uint8_t newOptionalParamsData[1500];
262313
size_t newOptionalParamsDataLen = optionalParamsToByteArray(optionalParameters, newOptionalParamsData, 1500);
263314
size_t curOptionalParamsDataLen = getOptionalParametersLength();
315+
int offsetInLayer = sizeof(bgp_open_message);
264316

265317
if (newOptionalParamsDataLen > curOptionalParamsDataLen)
266318
{
267-
bool res = extendLayer(sizeof(bgp_open_message), newOptionalParamsDataLen - curOptionalParamsDataLen);
268-
if (!res)
319+
size_t numOfBytesToExtend = newOptionalParamsDataLen - curOptionalParamsDataLen;
320+
321+
if (!extendLayer(offsetInLayer, numOfBytesToExtend))
269322
{
270323
PCPP_LOG_ERROR("Couldn't extend BGP open layer to include the additional optional parameters");
271-
return res;
324+
return false;
272325
}
273326
}
274327
else if (newOptionalParamsDataLen < curOptionalParamsDataLen)
275328
{
276-
bool res = shortenLayer(sizeof(bgp_open_message), curOptionalParamsDataLen - newOptionalParamsDataLen);
277-
if (!res)
329+
size_t numOfBytesToShorten = curOptionalParamsDataLen - newOptionalParamsDataLen;
330+
331+
if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
278332
{
279333
PCPP_LOG_ERROR("Couldn't shorten BGP open layer to set the right size of the optional parameters data");
280-
return res;
334+
return false;
281335
}
282336
}
283337

284338
if (newOptionalParamsDataLen > 0)
285339
{
286-
memcpy(m_Data + sizeof(bgp_open_message), newOptionalParamsData, newOptionalParamsDataLen);
340+
memcpy(m_Data + offsetInLayer, newOptionalParamsData, newOptionalParamsDataLen);
287341
}
288342

289343
getOpenMsgHeader()->optionalParameterLength = (uint8_t)newOptionalParamsDataLen;
@@ -565,32 +619,32 @@ namespace pcpp
565619
uint8_t newWithdrawnRoutesData[1500];
566620
size_t newWithdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, newWithdrawnRoutesData, 1500);
567621
size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
622+
int offsetInLayer = sizeof(bgp_common_header) + sizeof(uint16_t);
568623

569624
if (newWithdrawnRoutesDataLen > curWithdrawnRoutesDataLen)
570625
{
571-
bool res = extendLayer(sizeof(bgp_common_header) + sizeof(uint16_t),
572-
newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen);
573-
if (!res)
626+
size_t numOfBytesToExtend = newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen;
627+
628+
if (!extendLayer(offsetInLayer, numOfBytesToExtend))
574629
{
575630
PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional withdrawn routes");
576-
return res;
631+
return false;
577632
}
578633
}
579634
else if (newWithdrawnRoutesDataLen < curWithdrawnRoutesDataLen)
580635
{
581-
bool res = shortenLayer(sizeof(bgp_common_header) + sizeof(uint16_t),
582-
curWithdrawnRoutesDataLen - newWithdrawnRoutesDataLen);
583-
if (!res)
636+
size_t numOfBytesToShorten = curWithdrawnRoutesDataLen - newWithdrawnRoutesDataLen;
637+
638+
if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
584639
{
585640
PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the withdrawn routes data");
586-
return res;
641+
return false;
587642
}
588643
}
589644

590645
if (newWithdrawnRoutesDataLen > 0)
591646
{
592-
memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t), newWithdrawnRoutesData,
593-
newWithdrawnRoutesDataLen);
647+
memcpy(m_Data + offsetInLayer, newWithdrawnRoutesData, newWithdrawnRoutesDataLen);
594648
}
595649

596650
getBasicHeader()->length =
@@ -642,32 +696,32 @@ namespace pcpp
642696
size_t newPathAttributesDataLen = pathAttributesToByteArray(pathAttributes, newPathAttributesData, 1500);
643697
size_t curPathAttributesDataLen = getPathAttributesLength();
644698
size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
699+
int offsetInLayer = sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen;
645700

646701
if (newPathAttributesDataLen > curPathAttributesDataLen)
647702
{
648-
bool res = extendLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen,
649-
newPathAttributesDataLen - curPathAttributesDataLen);
650-
if (!res)
703+
size_t numOfBytesToExtend = newPathAttributesDataLen - curPathAttributesDataLen;
704+
705+
if (!extendLayer(offsetInLayer, numOfBytesToExtend))
651706
{
652707
PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional path attributes");
653-
return res;
708+
return false;
654709
}
655710
}
656711
else if (newPathAttributesDataLen < curPathAttributesDataLen)
657712
{
658-
bool res = shortenLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen,
659-
curPathAttributesDataLen - newPathAttributesDataLen);
660-
if (!res)
713+
size_t numOfBytesToShorten = curPathAttributesDataLen - newPathAttributesDataLen;
714+
715+
if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
661716
{
662717
PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the path attributes data");
663-
return res;
718+
return false;
664719
}
665720
}
666721

667722
if (newPathAttributesDataLen > 0)
668723
{
669-
memcpy(m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen,
670-
newPathAttributesData, newPathAttributesDataLen);
724+
memcpy(m_Data + offsetInLayer, newPathAttributesData, newPathAttributesDataLen);
671725
}
672726

673727
getBasicHeader()->length =
@@ -741,35 +795,33 @@ namespace pcpp
741795
size_t curNlriDataLen = getNetworkLayerReachabilityInfoLength();
742796
size_t curPathAttributesDataLen = getPathAttributesLength();
743797
size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength();
798+
int offsetInLayer =
799+
sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen + curPathAttributesDataLen;
744800

745801
if (newNlriDataLen > curNlriDataLen)
746802
{
747-
bool res = extendLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen +
748-
curPathAttributesDataLen,
749-
newNlriDataLen - curNlriDataLen);
750-
if (!res)
803+
size_t numOfBytesToExtend = newNlriDataLen - curNlriDataLen;
804+
805+
if (!extendLayer(offsetInLayer, numOfBytesToExtend))
751806
{
752807
PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional NLRI data");
753-
return res;
808+
return false;
754809
}
755810
}
756811
else if (newNlriDataLen < curNlriDataLen)
757812
{
758-
bool res = shortenLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen +
759-
curPathAttributesDataLen,
760-
curNlriDataLen - newNlriDataLen);
761-
if (!res)
813+
size_t numOfBytesToShorten = curNlriDataLen - newNlriDataLen;
814+
815+
if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
762816
{
763817
PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the NLRI data");
764-
return res;
818+
return false;
765819
}
766820
}
767821

768822
if (newNlriDataLen > 0)
769823
{
770-
memcpy(m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen +
771-
curPathAttributesDataLen,
772-
newNlriData, newNlriDataLen);
824+
memcpy(m_Data + offsetInLayer, newNlriData, newNlriDataLen);
773825
}
774826

775827
getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newNlriDataLen - curNlriDataLen);
@@ -866,30 +918,33 @@ namespace pcpp
866918
}
867919

868920
size_t curNotificationDataLen = getNotificationDataLen();
921+
int offsetInLayer = sizeof(bgp_notification_message);
869922

870923
if (newNotificationDataLen > curNotificationDataLen)
871924
{
872-
bool res = extendLayer(sizeof(bgp_notification_message), newNotificationDataLen - curNotificationDataLen);
873-
if (!res)
925+
size_t numOfBytesToExtend = newNotificationDataLen - curNotificationDataLen;
926+
927+
if (!extendLayer(offsetInLayer, numOfBytesToExtend))
874928
{
875929
PCPP_LOG_ERROR("Couldn't extend BGP notification layer to include the additional notification data");
876-
return res;
930+
return false;
877931
}
878932
}
879933
else if (newNotificationDataLen < curNotificationDataLen)
880934
{
881-
bool res = shortenLayer(sizeof(bgp_notification_message), curNotificationDataLen - newNotificationDataLen);
882-
if (!res)
935+
size_t numOfBytesToShorten = curNotificationDataLen - newNotificationDataLen;
936+
937+
if (!shortenLayer(offsetInLayer, numOfBytesToShorten))
883938
{
884939
PCPP_LOG_ERROR(
885940
"Couldn't shorten BGP notification layer to set the right size of the notification data");
886-
return res;
941+
return false;
887942
}
888943
}
889944

890945
if (newNotificationDataLen > 0)
891946
{
892-
memcpy(m_Data + sizeof(bgp_notification_message), newNotificationData, newNotificationDataLen);
947+
memcpy(m_Data + offsetInLayer, newNotificationData, newNotificationDataLen);
893948
}
894949

895950
getNotificationMsgHeader()->length = htobe16(sizeof(bgp_notification_message) + newNotificationDataLen);

Packet++/src/Layer.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,11 @@ namespace pcpp
6363

6464
if (m_Packet == nullptr)
6565
{
66-
if ((size_t)offsetInLayer > m_DataLen)
66+
if (static_cast<size_t>(offsetInLayer) > m_DataLen)
6767
{
6868
PCPP_LOG_ERROR("Requested offset is larger than data length");
6969
return false;
7070
}
71-
7271
uint8_t* newData = new uint8_t[m_DataLen + numOfBytesToExtend];
7372
memcpy(newData, m_Data, offsetInLayer);
7473
memcpy(newData + offsetInLayer + numOfBytesToExtend, m_Data + offsetInLayer, m_DataLen - offsetInLayer);
@@ -89,14 +88,19 @@ namespace pcpp
8988
return false;
9089
}
9190

91+
if (static_cast<size_t>(offsetInLayer) + numOfBytesToShorten > m_DataLen)
92+
{
93+
PCPP_LOG_ERROR("Requested number of bytes to shorten is larger than data length");
94+
return false;
95+
}
96+
9297
if (m_Packet == nullptr)
9398
{
94-
if ((size_t)offsetInLayer >= m_DataLen)
99+
if (static_cast<size_t>(offsetInLayer) >= m_DataLen)
95100
{
96101
PCPP_LOG_ERROR("Requested offset is larger than data length");
97102
return false;
98103
}
99-
100104
uint8_t* newData = new uint8_t[m_DataLen - numOfBytesToShorten];
101105
memcpy(newData, m_Data, offsetInLayer);
102106
memcpy(newData + offsetInLayer, m_Data + offsetInLayer + numOfBytesToShorten,

Packet++/src/Packet.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ namespace pcpp
605605
bool passedExtendedLayer = false;
606606
for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
607607
{
608+
if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
609+
{
610+
PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
611+
return false;
612+
}
613+
608614
// set the data ptr
609615
curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
610616

@@ -656,20 +662,28 @@ namespace pcpp
656662
bool passedExtendedLayer = false;
657663
while (curLayer != nullptr)
658664
{
665+
if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
666+
{
667+
PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
668+
return false;
669+
}
670+
659671
// set the data ptr
660672
curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
661673

662674
// set a flag if arrived to the layer being shortened
663675
if (curLayer->getPrevLayer() == layer)
664676
passedExtendedLayer = true;
665677

678+
size_t headerLen = curLayer->getHeaderLen();
679+
666680
// change the data length only for layers who come before the shortened layer. For layers who come after,
667681
// data length isn't changed
668682
if (!passedExtendedLayer)
669683
curLayer->m_DataLen -= numOfBytesToShorten;
670684

671685
// assuming header length of the layer that requested to be extended hasn't been enlarged yet
672-
size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0);
686+
headerLen -= (curLayer == layer ? numOfBytesToShorten : 0);
673687
dataPtr += headerLen;
674688
curLayer = curLayer->getNextLayer();
675689
}

0 commit comments

Comments
 (0)