Skip to content

Integer overflow in CMSIS-RTOS osPoolCreate() causes undersized allocation and out-of-bounds access. #133

Description

@Arslan8

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

  1. Create an application or minimal test harness that calls the public CMSIS-RTOS v1 osPoolCreate() API.

  2. The affected module is:

Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c
  1. 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:

0x80000004

The intended backing allocation size is:

2 * 0x80000004 = 0x100000008

but the 32-bit multiplication wraps to:

0x00000008

Therefore:

pvPortMalloc(pool_def->pool_sz * itemSize)

requests only 8 bytes, while the pool metadata still records:

pool_sz = 2
item_sz = 0x80000004
  1. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinginternal bug trackerIssue confirmed and logged into the internal bug tracking systemmwMiddleware-related issue or pull-request.rtosReal-Time Operating System

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions