Skip to content

Commit d364fee

Browse files
committed
Fix Memory Leak from Multiple Decodes of TP
Fixes a memory leak in the QUIC transport parameters TLS extension decode code when multiple instances are present or multiple calls to the decode happen.
1 parent 3226cff commit d364fee

6 files changed

Lines changed: 99 additions & 11 deletions

File tree

src/core/connection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2159,7 +2159,7 @@ QuicConnRecvResumptionTicket(
21592159
)
21602160
{
21612161
BOOLEAN ResumptionAccepted = FALSE;
2162-
QUIC_TRANSPORT_PARAMETERS ResumedTP;
2162+
QUIC_TRANSPORT_PARAMETERS ResumedTP = {0};
21632163
CxPlatZeroMemory(&ResumedTP, sizeof(ResumedTP));
21642164
if (QuicConnIsServer(Connection)) {
21652165
if (Connection->Crypto.TicketValidationRejecting) {

src/core/crypto.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,7 +2244,7 @@ QuicCryptoDecodeServerTicket(
22442244
const uint8_t* Ticket,
22452245
_In_ const uint8_t* AlpnList,
22462246
_In_ uint16_t AlpnListLength,
2247-
_Out_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
2247+
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
22482248
_Outptr_result_buffer_maybenull_(*AppDataLength)
22492249
const uint8_t** AppData,
22502250
_Out_ uint32_t* AppDataLength
@@ -2497,7 +2497,7 @@ QuicCryptoDecodeClientTicket(
24972497
_In_ uint16_t ClientTicketLength,
24982498
_In_reads_bytes_(ClientTicketLength)
24992499
const uint8_t* ClientTicket,
2500-
_Out_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
2500+
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
25012501
_Outptr_result_buffer_maybenull_(*ServerTicketLength)
25022502
uint8_t** ServerTicket,
25032503
_Out_ uint32_t* ServerTicketLength,

src/core/crypto.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ QuicCryptoDecodeServerTicket(
386386
const uint8_t* Ticket,
387387
_In_ const uint8_t* AlpnList,
388388
_In_ uint16_t AlpnListLength,
389-
_Out_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
389+
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
390390
_Outptr_result_buffer_maybenull_(*AppDataLength)
391391
const uint8_t** AppData,
392392
_Out_ uint32_t* AppDataLength
@@ -421,7 +421,7 @@ QuicCryptoDecodeClientTicket(
421421
_In_ uint16_t ClientTicketLength,
422422
_In_reads_bytes_(ClientTicketLength)
423423
const uint8_t* ClientTicket,
424-
_Out_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
424+
_Inout_ QUIC_TRANSPORT_PARAMETERS* DecodedTP,
425425
_Outptr_result_buffer_maybenull_(*ServerTicketLength)
426426
uint8_t** ServerTicket,
427427
_Out_ uint32_t* ServerTicketLength,

src/core/crypto_tls.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ QuicCryptoTlsReadExtensions(
348348
} Extension;
349349
*/
350350

351+
BOOLEAN FoundSNI = FALSE;
352+
BOOLEAN FoundALPN = FALSE;
351353
BOOLEAN FoundTransportParameters = FALSE;
352354
while (BufferLength) {
353355
//
@@ -377,23 +379,49 @@ QuicCryptoTlsReadExtensions(
377379
}
378380

379381
if (ExtType == TlsExt_ServerName) {
382+
if (FoundSNI) {
383+
QuicTraceEvent(
384+
ConnError,
385+
"[conn][%p] ERROR, %s.",
386+
Connection,
387+
"Duplicate SNI extension present");
388+
return QUIC_STATUS_INVALID_PARAMETER;
389+
}
380390
QUIC_STATUS Status =
381391
QuicCryptoTlsReadSniExtension(
382392
Connection, Buffer, ExtLen, Info);
383393
if (QUIC_FAILED(Status)) {
384394
return Status;
385395
}
396+
FoundSNI = TRUE;
386397

387398
} else if (ExtType == TlsExt_AppProtocolNegotiation) {
399+
if (FoundALPN) {
400+
QuicTraceEvent(
401+
ConnError,
402+
"[conn][%p] ERROR, %s.",
403+
Connection,
404+
"Duplicate ALPN extension present");
405+
return QUIC_STATUS_INVALID_PARAMETER;
406+
}
388407
QUIC_STATUS Status =
389408
QuicCryptoTlsReadAlpnExtension(
390409
Connection, Buffer, ExtLen, Info);
391410
if (QUIC_FAILED(Status)) {
392411
return Status;
393412
}
413+
FoundALPN = TRUE;
394414

395415
} else if (Connection->Stats.QuicVersion != QUIC_VERSION_DRAFT_29) {
396416
if (ExtType == TLS_EXTENSION_TYPE_QUIC_TRANSPORT_PARAMETERS) {
417+
if (FoundTransportParameters) {
418+
QuicTraceEvent(
419+
ConnError,
420+
"[conn][%p] ERROR, %s.",
421+
Connection,
422+
"Duplicate QUIC TP extension present");
423+
return QUIC_STATUS_INVALID_PARAMETER;
424+
}
397425
if (!QuicCryptoTlsDecodeTransportParameters(
398426
Connection,
399427
FALSE,
@@ -407,6 +435,14 @@ QuicCryptoTlsReadExtensions(
407435

408436
} else {
409437
if (ExtType == TLS_EXTENSION_TYPE_QUIC_TRANSPORT_PARAMETERS_DRAFT) {
438+
if (FoundTransportParameters) {
439+
QuicTraceEvent(
440+
ConnError,
441+
"[conn][%p] ERROR, %s.",
442+
Connection,
443+
"Duplicate QUIC (draft) TP extension present");
444+
return QUIC_STATUS_INVALID_PARAMETER;
445+
}
410446
if (!QuicCryptoTlsDecodeTransportParameters(
411447
Connection,
412448
FALSE,
@@ -1254,7 +1290,7 @@ QuicCryptoTlsDecodeTransportParameters( // NOLINT(readability-function-size, goo
12541290
_In_reads_(TPLen)
12551291
const uint8_t* TPBuf,
12561292
_In_ uint16_t TPLen,
1257-
_Out_ QUIC_TRANSPORT_PARAMETERS* TransportParams
1293+
_Inout_ QUIC_TRANSPORT_PARAMETERS* TransportParams
12581294
)
12591295
{
12601296
BOOLEAN Result = FALSE;
@@ -1263,6 +1299,9 @@ QuicCryptoTlsDecodeTransportParameters( // NOLINT(readability-function-size, goo
12631299

12641300
UNREFERENCED_PARAMETER(Connection);
12651301

1302+
if (TransportParams->VersionInfo) {
1303+
CXPLAT_FREE(TransportParams->VersionInfo, QUIC_POOL_VERSION_INFO);
1304+
}
12661305
CxPlatZeroMemory(TransportParams, sizeof(QUIC_TRANSPORT_PARAMETERS));
12671306
TransportParams->MaxUdpPayloadSize = QUIC_TP_MAX_PACKET_SIZE_DEFAULT;
12681307
TransportParams->AckDelayExponent = QUIC_TP_ACK_DELAY_EXPONENT_DEFAULT;

src/core/transport_params.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ QuicCryptoTlsDecodeTransportParameters(
180180
_In_reads_(TPLen)
181181
const uint8_t* TPBuf,
182182
_In_ uint16_t TPLen,
183-
_Out_ QUIC_TRANSPORT_PARAMETERS* TransportParams
183+
_Inout_ QUIC_TRANSPORT_PARAMETERS* TransportParams
184184
);
185185

186186
//

src/core/unittest/TransportParamTest.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,49 @@ void EncodeDecodeAndCompare(
8282
auto TPBuffer = Buffer + CxPlatTlsTPHeaderSize;
8383
uint16_t TPBufferLength = (uint16_t)(BufferLength - CxPlatTlsTPHeaderSize);
8484

85-
QUIC_TRANSPORT_PARAMETERS Decoded;
85+
QUIC_TRANSPORT_PARAMETERS Decoded = {0};
86+
TransportParametersScope TPScope(&Decoded);
8687
BOOLEAN DecodedSuccessfully =
8788
QuicCryptoTlsDecodeTransportParameters(
8889
&JunkConnection, IsServer, TPBuffer, TPBufferLength, &Decoded);
8990

9091
CXPLAT_FREE(Buffer, QUIC_POOL_TLS_TRANSPARAMS);
91-
TransportParametersScope TPScope(&Decoded);
92-
9392
ASSERT_EQ(ShouldDecodeSuccessfully, DecodedSuccessfully);
94-
9593
if (ShouldDecodeSuccessfully) {
9694
CompareTransportParams(Original, &Decoded, IsServer);
9795
}
9896
}
9997

98+
void DecodeTwice(
99+
_In_ const QUIC_TRANSPORT_PARAMETERS* Original,
100+
_In_ bool IsServer = false
101+
)
102+
{
103+
uint32_t BufferLength;
104+
auto Buffer =
105+
QuicCryptoTlsEncodeTransportParameters(
106+
&JunkConnection, IsServer, Original, NULL, &BufferLength);
107+
ASSERT_NE(nullptr, Buffer);
108+
109+
ASSERT_TRUE(UINT16_MAX >= (BufferLength - CxPlatTlsTPHeaderSize));
110+
111+
auto TPBuffer = Buffer + CxPlatTlsTPHeaderSize;
112+
uint16_t TPBufferLength = (uint16_t)(BufferLength - CxPlatTlsTPHeaderSize);
113+
114+
QUIC_TRANSPORT_PARAMETERS Decoded = {0};
115+
TransportParametersScope TPScope(&Decoded);
116+
BOOLEAN DecodedSuccessfullyOnce =
117+
QuicCryptoTlsDecodeTransportParameters(
118+
&JunkConnection, IsServer, TPBuffer, TPBufferLength, &Decoded);
119+
BOOLEAN DecodedSuccessfullyTwice =
120+
QuicCryptoTlsDecodeTransportParameters(
121+
&JunkConnection, IsServer, TPBuffer, TPBufferLength, &Decoded);
122+
123+
CXPLAT_FREE(Buffer, QUIC_POOL_TLS_TRANSPARAMS);
124+
ASSERT_TRUE(DecodedSuccessfullyOnce);
125+
ASSERT_TRUE(DecodedSuccessfullyTwice);
126+
}
127+
100128
/*TEST(TransportParamTest, EmptyClient)
101129
{
102130
QUIC_TRANSPORT_PARAMETERS Original;
@@ -120,6 +148,15 @@ TEST(TransportParamTest, Preset1)
120148
EncodeDecodeAndCompare(&Original);
121149
}
122150

151+
TEST(TransportParamTest, Preset1DecodeTwice)
152+
{
153+
QUIC_TRANSPORT_PARAMETERS Original;
154+
CxPlatZeroMemory(&Original, sizeof(Original));
155+
Original.Flags |= QUIC_TP_FLAG_IDLE_TIMEOUT;
156+
Original.IdleTimeout = 100000;
157+
DecodeTwice(&Original);
158+
}
159+
123160
TEST(TransportParamTest, ZeroTP)
124161
{
125162
QUIC_TRANSPORT_PARAMETERS OriginalTP;
@@ -149,6 +186,18 @@ TEST(TransportParamTest, VersionNegotiationExtension)
149186
EncodeDecodeAndCompare(&OriginalTP);
150187
}
151188

189+
TEST(TransportParamTest, VersionNegotiationExtensionDecodeTwice)
190+
{
191+
QUIC_TRANSPORT_PARAMETERS OriginalTP;
192+
CxPlatZeroMemory(&OriginalTP, sizeof(OriginalTP));
193+
uint8_t VerInfo[21];
194+
OriginalTP.VersionInfo = VerInfo;
195+
OriginalTP.VersionInfoLength = sizeof(VerInfo);
196+
OriginalTP.Flags = QUIC_TP_FLAG_VERSION_NEGOTIATION;
197+
198+
DecodeTwice(&OriginalTP);
199+
}
200+
152201
TEST(TransportParamTest, CibirEncodingOne)
153202
{
154203
QUIC_TRANSPORT_PARAMETERS OriginalTP;

0 commit comments

Comments
 (0)