Skip to content

Commit 2febc0a

Browse files
mergify[bot]Alami-Aminepre-commit-ci[bot]
authored
[WiFi-PAF][Bugfix] heap-buffer overflow in GetPktSn (project-chip#71945) (project-chip#72333)
* [WiFi-PAF]: validate Read8 status and SnOffset bounds in GetPktSn * Porting fix to a debug method: DebugPktAckSn * copilot comment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- (cherry picked from commit d2f6c22) Co-authored-by: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ef8fe91 commit 2febc0a

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/wifipaf/WiFiPAFEndPoint.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,10 @@ SequenceNumber_t WiFiPAFEndPoint::AdjustRemoteReceiveWindow(SequenceNumber_t las
812812

813813
CHIP_ERROR WiFiPAFEndPoint::GetPktSn(Encoding::LittleEndian::Reader & reader, uint8_t * pHead, SequenceNumber_t & seqNum)
814814
{
815-
CHIP_ERROR err;
816815
BitFlags<WiFiPAFTP::HeaderFlags> rx_flags;
817816
size_t SnOffset = 0;
818817
SequenceNumber_t * pSn;
819-
err = reader.Read8(rx_flags.RawStorage()).StatusCode();
818+
ReturnErrorOnFailure(reader.Read8(rx_flags.RawStorage()).StatusCode());
820819
if (rx_flags.Has(WiFiPAFTP::HeaderFlags::kHankshake))
821820
{
822821
// Handkshake message => No ack/sn
@@ -832,6 +831,7 @@ CHIP_ERROR WiFiPAFEndPoint::GetPktSn(Encoding::LittleEndian::Reader & reader, ui
832831
{
833832
SnOffset += kTransferProtocolAckSize;
834833
}
834+
VerifyOrReturnError(SnOffset + sizeof(seqNum) <= reader.OctetsRead() + reader.Remaining(), CHIP_ERROR_MESSAGE_INCOMPLETE);
835835
pSn = pHead + SnOffset;
836836
seqNum = *pSn;
837837

@@ -866,6 +866,7 @@ CHIP_ERROR WiFiPAFEndPoint::DebugPktAckSn(const PktDirect_t PktDirect, Encoding:
866866
pAct = pHead + kTransferProtocolHeaderFlagsSize;
867867
SnOffset += kTransferProtocolAckSize;
868868
}
869+
VerifyOrExit(SnOffset + sizeof(*pSn) <= reader.OctetsRead() + reader.Remaining(), err = CHIP_ERROR_MESSAGE_INCOMPLETE);
869870
pSn = pHead + SnOffset;
870871
if (pAct == nullptr)
871872
{

src/wifipaf/tests/TestWiFiPAFLayer.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,37 @@ TEST_F(TestWiFiPAFLayer, CheckPafSession)
183183
EXPECT_EQ(RmPafSession(PafInfoAccess::kAccSessionId, sessionInfo), CHIP_ERROR_NOT_FOUND);
184184
}
185185

186+
// Run under ASan to catch regressions of the heap-buffer-overflow read.
187+
TEST_F(TestWiFiPAFLayer, GetPktSnRejectsShortFragment)
188+
{
189+
WiFiPAFSession sessionInfo = {
190+
.role = kWiFiPafRole_Publisher,
191+
.id = 1,
192+
.peer_id = 1,
193+
.peer_addr = { 0xd0, 0x17, 0x69, 0xee, 0x7f, 0x3c },
194+
.nodeId = 1,
195+
.discriminator = 0xF00,
196+
};
197+
198+
WiFiPAFEndPoint * newEndPoint = nullptr;
199+
ASSERT_EQ(NewEndPoint(&newEndPoint, sessionInfo, sessionInfo.role), CHIP_NO_ERROR);
200+
ASSERT_NE(newEndPoint, nullptr);
201+
SetEndPoint(newEndPoint);
202+
EXPECT_EQ(AddPafSession(PafInfoAccess::kAccSessionId, sessionInfo), CHIP_NO_ERROR);
203+
newEndPoint->mState = WiFiPAFEndPoint::kState_Ready;
204+
205+
// Flag byte 0x2B sets kFragmentAck and kManagementOpcode, pushing SnOffset
206+
// to 3 (header + mgmt-op + ack). With a 3-byte buffer, dereferencing
207+
// pHead + 3 is a heap-buffer-overflow read.
208+
constexpr uint8_t kShortFragmentWithMaxFlags[] = { 0x2B, 0x8F, 0x2B };
209+
auto packet = System::PacketBufferHandle::NewWithData(kShortFragmentWithMaxFlags, sizeof(kShortFragmentWithMaxFlags));
210+
ASSERT_FALSE(packet.IsNull());
211+
212+
EXPECT_EQ(newEndPoint->Receive(std::move(packet)), CHIP_ERROR_MESSAGE_INCOMPLETE);
213+
214+
EXPECT_EQ(RmPafSession(PafInfoAccess::kAccSessionId, sessionInfo), CHIP_NO_ERROR);
215+
}
216+
186217
TEST_F(TestWiFiPAFLayer, CheckRunAsCommissioner)
187218
{
188219
WiFiPAFSession sessionInfo = {

0 commit comments

Comments
 (0)