Skip to content

Commit f590724

Browse files
tony-josi-awsSkptakactions-user
authored
Add integer overflow checks to buffer allocation APIs (#1017)
* Add checks to verify integer overflows doesnt occur during buffer allocations * Uncrustify: triggered by comment * updating review feedback --------- Co-authored-by: Soren Ptak <[email protected]> Co-authored-by: GitHub Action <[email protected]>
1 parent eed294c commit f590724

File tree

2 files changed

+169
-60
lines changed

2 files changed

+169
-60
lines changed

source/portable/BufferManagement/BufferAllocation_2.c

Lines changed: 113 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
#define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )
6464
#endif /* ipconfigUSE_TCP == 1 */
6565

66+
#define baALIGNMENT_BYTES ( sizeof( size_t ) )
67+
#define baALIGNMENT_MASK ( baALIGNMENT_BYTES - 1U )
68+
#define baADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( SIZE_MAX - ( b ) ) )
69+
6670
/* Compile time assertion with zero runtime effects
6771
* it will assert on 'e' not being zero, as it tries to divide by it,
6872
* will also print the line where the error occurred in case of failure */
@@ -175,8 +179,11 @@ BaseType_t xNetworkBuffersInitialise( void )
175179

176180
uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )
177181
{
178-
uint8_t * pucEthernetBuffer;
182+
uint8_t * pucEthernetBuffer = NULL;
183+
size_t uxMaxAllowedBytes = ( SIZE_MAX >> 1 );
179184
size_t xSize = *pxRequestedSizeBytes;
185+
size_t xBytesRequiredForAlignment, xAllocatedBytes;
186+
BaseType_t xIntegerOverflowed = pdFALSE;
180187

181188
if( xSize < baMINIMAL_BUFFER_SIZE )
182189
{
@@ -187,25 +194,46 @@ uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )
187194

188195
/* Round up xSize to the nearest multiple of N bytes,
189196
* where N equals 'sizeof( size_t )'. */
190-
if( ( xSize & ( sizeof( size_t ) - 1U ) ) != 0U )
197+
if( ( xSize & baALIGNMENT_MASK ) != 0U )
191198
{
192-
xSize = ( xSize | ( sizeof( size_t ) - 1U ) ) + 1U;
193-
}
199+
xBytesRequiredForAlignment = baALIGNMENT_BYTES - ( xSize & baALIGNMENT_MASK );
194200

195-
*pxRequestedSizeBytes = xSize;
201+
if( baADD_WILL_OVERFLOW( xSize, xBytesRequiredForAlignment ) == 0 )
202+
{
203+
xSize += xBytesRequiredForAlignment;
204+
}
205+
else
206+
{
207+
xIntegerOverflowed = pdTRUE;
208+
}
209+
}
196210

197-
/* Allocate a buffer large enough to store the requested Ethernet frame size
198-
* and a pointer to a network buffer structure (hence the addition of
199-
* ipBUFFER_PADDING bytes). */
200-
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
201-
configASSERT( pucEthernetBuffer != NULL );
211+
if( baADD_WILL_OVERFLOW( xSize, ipBUFFER_PADDING ) == 0 )
212+
{
213+
xAllocatedBytes = xSize + ipBUFFER_PADDING;
214+
}
215+
else
216+
{
217+
xIntegerOverflowed = pdTRUE;
218+
}
202219

203-
if( pucEthernetBuffer != NULL )
220+
if( ( xIntegerOverflowed == pdFALSE ) && ( xAllocatedBytes <= uxMaxAllowedBytes ) )
204221
{
205-
/* Enough space is left at the start of the buffer to place a pointer to
206-
* the network buffer structure that references this Ethernet buffer.
207-
* Return a pointer to the start of the Ethernet buffer itself. */
208-
pucEthernetBuffer += ipBUFFER_PADDING;
222+
*pxRequestedSizeBytes = xSize;
223+
224+
/* Allocate a buffer large enough to store the requested Ethernet frame size
225+
* and a pointer to a network buffer structure (hence the addition of
226+
* ipBUFFER_PADDING bytes). */
227+
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xAllocatedBytes );
228+
configASSERT( pucEthernetBuffer != NULL );
229+
230+
if( pucEthernetBuffer != NULL )
231+
{
232+
/* Enough space is left at the start of the buffer to place a pointer to
233+
* the network buffer structure that references this Ethernet buffer.
234+
* Return a pointer to the start of the Ethernet buffer itself. */
235+
pucEthernetBuffer += ipBUFFER_PADDING;
236+
}
209237
}
210238

211239
return pucEthernetBuffer;
@@ -234,8 +262,51 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS
234262
size_t uxCount;
235263
size_t uxMaxAllowedBytes = ( SIZE_MAX >> 1 );
236264
size_t xRequestedSizeBytesCopy = xRequestedSizeBytes;
265+
size_t xBytesRequiredForAlignment, xAllocatedBytes;
266+
BaseType_t xIntegerOverflowed = pdFALSE;
267+
268+
if( ( xRequestedSizeBytesCopy < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
269+
{
270+
/* ARP packets can replace application packets, so the storage must be
271+
* at least large enough to hold an ARP. */
272+
xRequestedSizeBytesCopy = baMINIMAL_BUFFER_SIZE;
273+
}
274+
275+
/* Add 2 bytes to xRequestedSizeBytesCopy and round up xRequestedSizeBytesCopy
276+
* to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
277+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytesCopy, 2 ) == 0 )
278+
{
279+
xRequestedSizeBytesCopy += 2U;
280+
}
281+
else
282+
{
283+
xIntegerOverflowed = pdTRUE;
284+
}
285+
286+
if( ( xRequestedSizeBytesCopy & baALIGNMENT_MASK ) != 0U )
287+
{
288+
xBytesRequiredForAlignment = baALIGNMENT_BYTES - ( xRequestedSizeBytesCopy & baALIGNMENT_MASK );
289+
290+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytesCopy, xBytesRequiredForAlignment ) == 0 )
291+
{
292+
xRequestedSizeBytesCopy += xBytesRequiredForAlignment;
293+
}
294+
else
295+
{
296+
xIntegerOverflowed = pdTRUE;
297+
}
298+
}
299+
300+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytesCopy, ipBUFFER_PADDING ) == 0 )
301+
{
302+
xAllocatedBytes = xRequestedSizeBytesCopy + ipBUFFER_PADDING;
303+
}
304+
else
305+
{
306+
xIntegerOverflowed = pdTRUE;
307+
}
237308

238-
if( ( xRequestedSizeBytesCopy <= uxMaxAllowedBytes ) && ( xNetworkBufferSemaphore != NULL ) )
309+
if( ( xIntegerOverflowed == pdFALSE ) && ( xAllocatedBytes <= uxMaxAllowedBytes ) && ( xNetworkBufferSemaphore != NULL ) )
239310
{
240311
/* If there is a semaphore available, there is a network buffer available. */
241312
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
@@ -261,25 +332,9 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS
261332

262333
if( xRequestedSizeBytesCopy > 0U )
263334
{
264-
if( ( xRequestedSizeBytesCopy < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
265-
{
266-
/* ARP packets can replace application packets, so the storage must be
267-
* at least large enough to hold an ARP. */
268-
xRequestedSizeBytesCopy = baMINIMAL_BUFFER_SIZE;
269-
}
270-
271-
/* Add 2 bytes to xRequestedSizeBytesCopy and round up xRequestedSizeBytesCopy
272-
* to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
273-
xRequestedSizeBytesCopy += 2U;
274-
275-
if( ( xRequestedSizeBytesCopy & ( sizeof( size_t ) - 1U ) ) != 0U )
276-
{
277-
xRequestedSizeBytesCopy = ( xRequestedSizeBytesCopy | ( sizeof( size_t ) - 1U ) ) + 1U;
278-
}
279-
280335
/* Extra space is obtained so a pointer to the network buffer can
281336
* be stored at the beginning of the buffer. */
282-
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytesCopy + ipBUFFER_PADDING );
337+
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xAllocatedBytes );
283338

284339
if( pxReturn->pucEthernetBuffer == NULL )
285340
{
@@ -403,32 +458,38 @@ NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDe
403458
size_t uxSizeBytes = xNewSizeBytes;
404459
NetworkBufferDescriptor_t * pxNetworkBufferCopy = pxNetworkBuffer;
405460

406-
407-
408461
xOriginalLength = pxNetworkBufferCopy->xDataLength + ipBUFFER_PADDING;
409-
uxSizeBytes = uxSizeBytes + ipBUFFER_PADDING;
410-
411-
pucBuffer = pucGetNetworkBuffer( &( uxSizeBytes ) );
412462

413-
if( pucBuffer == NULL )
414-
{
415-
/* In case the allocation fails, return NULL. */
416-
pxNetworkBufferCopy = NULL;
417-
}
418-
else
463+
if( baADD_WILL_OVERFLOW( uxSizeBytes, ipBUFFER_PADDING ) == 0 )
419464
{
420-
pxNetworkBufferCopy->xDataLength = uxSizeBytes;
465+
uxSizeBytes = uxSizeBytes + ipBUFFER_PADDING;
421466

422-
if( uxSizeBytes > xOriginalLength )
467+
pucBuffer = pucGetNetworkBuffer( &( uxSizeBytes ) );
468+
469+
if( pucBuffer == NULL )
423470
{
424-
uxSizeBytes = xOriginalLength;
471+
/* In case the allocation fails, return NULL. */
472+
pxNetworkBufferCopy = NULL;
425473
}
474+
else
475+
{
476+
pxNetworkBufferCopy->xDataLength = uxSizeBytes;
426477

427-
( void ) memcpy( pucBuffer - ipBUFFER_PADDING,
428-
pxNetworkBufferCopy->pucEthernetBuffer - ipBUFFER_PADDING,
429-
uxSizeBytes );
430-
vReleaseNetworkBuffer( pxNetworkBufferCopy->pucEthernetBuffer );
431-
pxNetworkBufferCopy->pucEthernetBuffer = pucBuffer;
478+
if( uxSizeBytes > xOriginalLength )
479+
{
480+
uxSizeBytes = xOriginalLength;
481+
}
482+
483+
( void ) memcpy( pucBuffer - ipBUFFER_PADDING,
484+
pxNetworkBufferCopy->pucEthernetBuffer - ipBUFFER_PADDING,
485+
uxSizeBytes );
486+
vReleaseNetworkBuffer( pxNetworkBufferCopy->pucEthernetBuffer );
487+
pxNetworkBufferCopy->pucEthernetBuffer = pucBuffer;
488+
}
489+
}
490+
else
491+
{
492+
pxNetworkBufferCopy = NULL;
432493
}
433494

434495
return pxNetworkBufferCopy;

source/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@
7575
STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
7676
#endif
7777

78+
#define baALIGNMENT_BYTES ( sizeof( size_t ) )
79+
#define baALIGNMENT_MASK ( baALIGNMENT_BYTES - 1U )
80+
#define baADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( SIZE_MAX - ( b ) ) )
81+
7882
/* A list of free (available) NetworkBufferDescriptor_t structures. */
7983
static List_t xFreeBuffersList;
8084

@@ -385,6 +389,8 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS
385389
{
386390
NetworkBufferDescriptor_t * pxReturn = NULL;
387391
size_t uxCount;
392+
size_t xBytesRequiredForAlignment, xAllocatedBytes;
393+
BaseType_t xIntegerOverflowed = pdFALSE;
388394

389395
if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
390396
{
@@ -397,19 +403,49 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS
397403
if( xRequestedSizeBytes != 0u )
398404
{
399405
#endif /* #ifdef PIC32_USE_ETHERNET */
400-
xRequestedSizeBytes += 2u;
401406

402-
if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
407+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytes, 2 ) == 0 )
408+
{
409+
xRequestedSizeBytes += 2U;
410+
}
411+
else
403412
{
404-
xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
413+
xIntegerOverflowed = pdTRUE;
414+
}
415+
416+
if( ( xRequestedSizeBytes & baALIGNMENT_MASK ) != 0U )
417+
{
418+
xBytesRequiredForAlignment = baALIGNMENT_BYTES - ( xRequestedSizeBytes & baALIGNMENT_MASK );
419+
420+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytes, xBytesRequiredForAlignment ) == 0 )
421+
{
422+
xRequestedSizeBytes += xBytesRequiredForAlignment;
423+
}
424+
else
425+
{
426+
xIntegerOverflowed = pdTRUE;
427+
}
405428
}
406429

430+
#ifdef PIC32_USE_ETHERNET
431+
( void ) xAllocatedBytes;
432+
#else
433+
if( baADD_WILL_OVERFLOW( xRequestedSizeBytes, ipBUFFER_PADDING ) == 0 )
434+
{
435+
xAllocatedBytes = xRequestedSizeBytes + ipBUFFER_PADDING;
436+
}
437+
else
438+
{
439+
xIntegerOverflowed = pdTRUE;
440+
}
441+
#endif /* #ifndef PIC32_USE_ETHERNET */
442+
407443
#ifdef PIC32_USE_ETHERNET
408444
}
409445
#endif /* #ifdef PIC32_USE_ETHERNET */
410446

411447
/* If there is a semaphore available, there is a network buffer available. */
412-
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
448+
if( ( xIntegerOverflowed == pdFALSE ) && ( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS ) )
413449
{
414450
/* Protect the structure as it is accessed from tasks and interrupts. */
415451
taskENTER_CRITICAL();
@@ -438,7 +474,7 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS
438474
#ifdef PIC32_USE_ETHERNET
439475
pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
440476
#else
441-
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
477+
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xAllocatedBytes );
442478
#endif /* #ifdef PIC32_USE_ETHERNET */
443479

444480
if( pxReturn->pucEthernetBuffer == NULL )
@@ -554,16 +590,28 @@ NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDe
554590
size_t xNewSizeBytes )
555591
{
556592
size_t xOriginalLength;
557-
uint8_t * pucBuffer;
593+
uint8_t * pucBuffer = NULL;
594+
BaseType_t xIntegerOverflowed = pdFALSE;
558595

559596
#ifdef PIC32_USE_ETHERNET
560597
xOriginalLength = pxNetworkBuffer->xDataLength;
561598
#else
562599
xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
563-
xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
600+
601+
if( baADD_WILL_OVERFLOW( xNewSizeBytes, ipBUFFER_PADDING ) == 0 )
602+
{
603+
xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
604+
}
605+
else
606+
{
607+
xIntegerOverflowed = pdTRUE;
608+
}
564609
#endif /* #ifdef PIC32_USE_ETHERNET */
565610

566-
pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
611+
if( xIntegerOverflowed == pdFALSE )
612+
{
613+
pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
614+
}
567615

568616
if( pucBuffer == NULL )
569617
{

0 commit comments

Comments
 (0)