mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-07-10 13:29:45 -04:00
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).
This commit is contained in:
parent
2345ff7c88
commit
3ac4495945
1 changed files with 70 additions and 52 deletions
18
tasks.c
18
tasks.c
|
|
@ -1653,6 +1653,23 @@ STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
{
|
||||
TCB_t * pxNewTCB;
|
||||
|
||||
/* Guard against the stack size calculation overflowing. The stack is
|
||||
* allocated as ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ). If a
|
||||
* caller-supplied uxStackDepth is large enough that this product wraps
|
||||
* size_t, the allocation is far smaller than requested while
|
||||
* prvInitialiseNewTask() still computes the top of stack from the full
|
||||
* uxStackDepth, causing out-of-bounds writes when the initial stack frame
|
||||
* is written. The wrap is detected by multiplying and dividing back:
|
||||
* if dividing the byte size by sizeof( StackType_t ) does not recover
|
||||
* uxStackDepth then the multiplication overflowed. Leave pxNewTCB NULL
|
||||
* and skip allocation instead of under-allocating, so the failure is
|
||||
* reported through the single return at the end of the function. */
|
||||
if( ( ( size_t ) uxStackDepth ) != ( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) / sizeof( StackType_t ) ) )
|
||||
{
|
||||
pxNewTCB = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the stack grows down then allocate the stack then the TCB so the stack
|
||||
* does not grow into the TCB. Likewise if the stack grows up then allocate
|
||||
* the TCB then the stack. */
|
||||
|
|
@ -1724,6 +1741,7 @@ STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
}
|
||||
}
|
||||
#endif /* portSTACK_GROWTH */
|
||||
}
|
||||
|
||||
if( pxNewTCB != NULL )
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue