Skip to content

Commit 3ac4495

Browse files
tasks: reject stack depth whose byte size overflows size_t
Defect: xTaskCreate() / prvCreateTask() can under-allocate a task stack when a caller supplies a very large uxStackDepth, leading to out-of-bounds writes when the initial stack frame is set up. Root cause: the stack is allocated as ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ). If that product wraps size_t, the allocation is far smaller than requested, yet prvInitialiseNewTask() still computes the top of stack from the full uxStackDepth and writes the initial context past the end of the allocation. Fix: before allocating, reject creation when ( ( size_t ) uxStackDepth ) > ( SIZE_MAX / sizeof( StackType_t ) ), returning NULL (task not created) instead of proceeding with an under-sized buffer. A host regression test kept outside this repository demonstrates the fault before the change and its absence afterwards (red then green).
1 parent 2345ff7 commit 3ac4495

1 file changed

Lines changed: 68 additions & 50 deletions

File tree

tasks.c

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,77 +1653,95 @@ STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
16531653
{
16541654
TCB_t * pxNewTCB;
16551655

1656-
/* If the stack grows down then allocate the stack then the TCB so the stack
1657-
* does not grow into the TCB. Likewise if the stack grows up then allocate
1658-
* the TCB then the stack. */
1659-
#if ( portSTACK_GROWTH > 0 )
1660-
{
1661-
/* Allocate space for the TCB. Where the memory comes from depends on
1662-
* the implementation of the port malloc function and whether or not static
1663-
* allocation is being used. */
1664-
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
1665-
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1666-
/* coverity[misra_c_2012_rule_11_5_violation] */
1667-
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
1668-
1669-
if( pxNewTCB != NULL )
1656+
/* Guard against the stack size calculation overflowing. The stack is
1657+
* allocated as ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ). If a
1658+
* caller-supplied uxStackDepth is large enough that this product wraps
1659+
* size_t, the allocation is far smaller than requested while
1660+
* prvInitialiseNewTask() still computes the top of stack from the full
1661+
* uxStackDepth, causing out-of-bounds writes when the initial stack frame
1662+
* is written. The wrap is detected by multiplying and dividing back:
1663+
* if dividing the byte size by sizeof( StackType_t ) does not recover
1664+
* uxStackDepth then the multiplication overflowed. Leave pxNewTCB NULL
1665+
* and skip allocation instead of under-allocating, so the failure is
1666+
* reported through the single return at the end of the function. */
1667+
if( ( ( size_t ) uxStackDepth ) != ( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) / sizeof( StackType_t ) ) )
1668+
{
1669+
pxNewTCB = NULL;
1670+
}
1671+
else
1672+
{
1673+
/* If the stack grows down then allocate the stack then the TCB so the stack
1674+
* does not grow into the TCB. Likewise if the stack grows up then allocate
1675+
* the TCB then the stack. */
1676+
#if ( portSTACK_GROWTH > 0 )
16701677
{
1671-
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1672-
1673-
/* Allocate space for the stack used by the task being created.
1674-
* The base of the stack memory stored in the TCB so the task can
1675-
* be deleted later if required. */
1678+
/* Allocate space for the TCB. Where the memory comes from depends on
1679+
* the implementation of the port malloc function and whether or not static
1680+
* allocation is being used. */
16761681
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
16771682
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
16781683
/* coverity[misra_c_2012_rule_11_5_violation] */
1679-
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
1684+
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
16801685

1681-
if( pxNewTCB->pxStack == NULL )
1686+
if( pxNewTCB != NULL )
16821687
{
1683-
/* Could not allocate the stack. Delete the allocated TCB. */
1684-
vPortFree( pxNewTCB );
1685-
pxNewTCB = NULL;
1686-
}
1687-
}
1688-
}
1689-
#else /* portSTACK_GROWTH */
1690-
{
1691-
StackType_t * pxStack;
1688+
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
16921689

1693-
/* Allocate space for the stack used by the task being created. */
1694-
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
1695-
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1696-
/* coverity[misra_c_2012_rule_11_5_violation] */
1697-
pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
1690+
/* Allocate space for the stack used by the task being created.
1691+
* The base of the stack memory stored in the TCB so the task can
1692+
* be deleted later if required. */
1693+
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
1694+
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1695+
/* coverity[misra_c_2012_rule_11_5_violation] */
1696+
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
16981697

1699-
if( pxStack != NULL )
1698+
if( pxNewTCB->pxStack == NULL )
1699+
{
1700+
/* Could not allocate the stack. Delete the allocated TCB. */
1701+
vPortFree( pxNewTCB );
1702+
pxNewTCB = NULL;
1703+
}
1704+
}
1705+
}
1706+
#else /* portSTACK_GROWTH */
17001707
{
1701-
/* Allocate space for the TCB. */
1708+
StackType_t * pxStack;
1709+
1710+
/* Allocate space for the stack used by the task being created. */
17021711
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
17031712
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
17041713
/* coverity[misra_c_2012_rule_11_5_violation] */
1705-
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
1714+
pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
17061715

1707-
if( pxNewTCB != NULL )
1716+
if( pxStack != NULL )
17081717
{
1709-
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1718+
/* Allocate space for the TCB. */
1719+
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
1720+
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1721+
/* coverity[misra_c_2012_rule_11_5_violation] */
1722+
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
17101723

1711-
/* Store the stack location in the TCB. */
1712-
pxNewTCB->pxStack = pxStack;
1724+
if( pxNewTCB != NULL )
1725+
{
1726+
( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
1727+
1728+
/* Store the stack location in the TCB. */
1729+
pxNewTCB->pxStack = pxStack;
1730+
}
1731+
else
1732+
{
1733+
/* The stack cannot be used as the TCB was not created. Free
1734+
* it again. */
1735+
vPortFreeStack( pxStack );
1736+
}
17131737
}
17141738
else
17151739
{
1716-
/* The stack cannot be used as the TCB was not created. Free
1717-
* it again. */
1718-
vPortFreeStack( pxStack );
1740+
pxNewTCB = NULL;
17191741
}
17201742
}
1721-
else
1722-
{
1723-
pxNewTCB = NULL;
1724-
}
1743+
#endif /* portSTACK_GROWTH */
17251744
}
1726-
#endif /* portSTACK_GROWTH */
17271745

17281746
if( pxNewTCB != NULL )
17291747
{

0 commit comments

Comments
 (0)