Describe the set-up
- Repository:
STMicroelectronics/STM32CubeF7, current master revision.
- Affected middleware:
Middlewares/Third_Party/FreeRTOS, currently pinned by STM32CubeF7 to FreeRTOS middleware commit c239f63efc6ad8206e3af531d07eb5228e8ca57b.
- Affected file:
Source/CMSIS_RTOS/cmsis_os.c
- The issue is in the CMSIS-RTOS v1 middleware implementation and is not board-specific.
Describe the bug
osPoolCreate() can allocate a backing buffer smaller than required because the expression
pool_def->pool_sz * itemSize
is used as the argument to pvPortMalloc() without checking for integer overflow.
The pool control block nevertheless retains the original pool_sz and aligned itemSize. If the multiplication wraps, osPoolCreate() can therefore successfully create a pool whose allocated backing memory is substantially smaller than implied by its metadata.
Subsequent calls to osPoolAlloc() calculate an element address using:
p = (void *)((uint32_t)(pool_id->pool) +
(index * pool_id->item_sz));
and can consequently return a pointer outside the allocated backing buffer.
This can lead to an out-of-bounds memory access. osPoolCAlloc() can additionally turn the invalid pointer into an out-of-bounds write internally because it calls osPoolAlloc() and then clears memory through the returned pointer.
How To Reproduce
-
Create an application or minimal test harness that calls the public CMSIS-RTOS v1 osPoolCreate() API.
-
The affected module is:
Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c
- Supply an
osPoolDef_t whose pool size and aligned item size overflow when multiplied. For example, for 32-bit arithmetic:
pool_sz = 2
item_sz = 0x80000004
The aligned itemSize remains:
The intended backing allocation size is:
2 * 0x80000004 = 0x100000008
but the 32-bit multiplication wraps to:
Therefore:
pvPortMalloc(pool_def->pool_sz * itemSize)
requests only 8 bytes, while the pool metadata still records:
pool_sz = 2
item_sz = 0x80000004
- Allocate elements from the resulting pool. When
osPoolAlloc() selects a non-zero element index, it calculates the returned address using the large item_sz stride and can return a pointer outside the 8-byte backing allocation.
The same invalid pointer can also be consumed internally by osPoolCAlloc().
Additional context
The affected CMSIS-RTOS v1 implementation is no longer present in the HEAD revision of the standalone STMicroelectronics/stm32-mw-freertos repository. However, the current STM32CubeF7 master branch still pins its FreeRTOS submodule to the older middleware commit c239f63efc6ad8206e3af531d07eb5228e8ca57b, which contains the vulnerable implementation.
A possible fix is to validate the multiplication before allocating, for example by rejecting the request when:
itemSize != 0 &&
pool_def->pool_sz > SIZE_MAX / itemSize
The computation used to align pool_def->item_sz should also be checked independently for overflow.
Alternatively, STM32CubeF7 could update its pinned FreeRTOS middleware revision if compatibility permits.
Screenshots
Not applicable.
Describe the set-up
STMicroelectronics/STM32CubeF7, currentmasterrevision.Middlewares/Third_Party/FreeRTOS, currently pinned by STM32CubeF7 to FreeRTOS middleware commitc239f63efc6ad8206e3af531d07eb5228e8ca57b.Source/CMSIS_RTOS/cmsis_os.cDescribe the bug
osPoolCreate()can allocate a backing buffer smaller than required because the expressionis used as the argument to
pvPortMalloc()without checking for integer overflow.The pool control block nevertheless retains the original
pool_szand aligneditemSize. If the multiplication wraps,osPoolCreate()can therefore successfully create a pool whose allocated backing memory is substantially smaller than implied by its metadata.Subsequent calls to
osPoolAlloc()calculate an element address using:and can consequently return a pointer outside the allocated backing buffer.
This can lead to an out-of-bounds memory access.
osPoolCAlloc()can additionally turn the invalid pointer into an out-of-bounds write internally because it callsosPoolAlloc()and then clears memory through the returned pointer.How To Reproduce
Create an application or minimal test harness that calls the public CMSIS-RTOS v1
osPoolCreate()API.The affected module is:
osPoolDef_twhose pool size and aligned item size overflow when multiplied. For example, for 32-bit arithmetic:The aligned
itemSizeremains:The intended backing allocation size is:
but the 32-bit multiplication wraps to:
Therefore:
requests only 8 bytes, while the pool metadata still records:
osPoolAlloc()selects a non-zero element index, it calculates the returned address using the largeitem_szstride and can return a pointer outside the 8-byte backing allocation.The same invalid pointer can also be consumed internally by
osPoolCAlloc().Additional context
The affected CMSIS-RTOS v1 implementation is no longer present in the HEAD revision of the standalone
STMicroelectronics/stm32-mw-freertosrepository. However, the currentSTM32CubeF7masterbranch still pins its FreeRTOS submodule to the older middleware commitc239f63efc6ad8206e3af531d07eb5228e8ca57b, which contains the vulnerable implementation.A possible fix is to validate the multiplication before allocating, for example by rejecting the request when:
The computation used to align
pool_def->item_szshould also be checked independently for overflow.Alternatively, STM32CubeF7 could update its pinned FreeRTOS middleware revision if compatibility permits.
Screenshots
Not applicable.