GHSA-v9jj-7qjg-h6g6: Integer wraparounds, under-allocations, and heap buffer overflows in Eclipse ThreadX xQueueCreate() and xQueueCreateSet()

GHSA ID

GHSA‑v9jj‑7qjg‑h6g6

CVE ID

CVE‑2024‑2212

Severity

High

CVSS score

7.3 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:L)

CWE

CWE-122, CWE-190

Published

2024‑03‑26

Last updated

2024‑03‑26

Affected packages

Package Vulnerable versions Patched versions

Eclipse ThreadX

< 6.4.0

6.4.0

Description

Short description

In Eclipse ThreadX before 6.4.0, xQueueCreate() and xQueueCreateSet() functions from the FreeRTOS compatibility API (utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c) were missing parameter checks. This could lead to integer wraparound, under-allocations and heap buffer overflows.

Impact

If an attacker can control uxQueueLength or uxItemSize, they can cause an integer wraparound thus causing txfr_malloc() to allocate a small amount of memory, exposing to subsequent heap buffer overflows:

QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize)
{
    txfr_queue_t *p_queue;
    void *p_mem;
    size_t mem_size;
    UINT ret;

    configASSERT(uxQueueLength != 0u);
    configASSERT(uxItemSize >= sizeof(UINT));

#if (TX_FREERTOS_AUTO_INIT == 1)
    if(txfr_initialized != 1u) {
        tx_freertos_auto_init();
    }
#endif

    p_queue = txfr_malloc(sizeof(txfr_queue_t));
    if(p_queue == NULL) {
        return NULL;
    }

    mem_size = uxQueueLength*(uxItemSize);

    p_mem = txfr_malloc(mem_size); // VULN: integer wraparound and under-allocation
    if(p_mem == NULL) {
        txfr_free(p_queue);
        return NULL;
    }

    TX_MEMSET(p_mem, 0, mem_size);
    TX_MEMSET(p_queue, 0, sizeof(*p_queue));
    p_queue->allocated = 1u;
    p_queue->p_mem = p_mem;
    p_queue->id = TX_QUEUE_ID;

    p_queue->p_write = (uint8_t *)p_mem;
    p_queue->p_read = (uint8_t *)p_mem;
    p_queue->msg_size = uxItemSize;
    p_queue->queue_length = uxQueueLength;

    ret = tx_semaphore_create(&p_queue->read_sem, "", 0u);
    if(ret != TX_SUCCESS) {
        return NULL;
    }

    ret = tx_semaphore_create(&p_queue->write_sem, "", uxQueueLength);
    if(ret != TX_SUCCESS) {
        return NULL;
    }

    return p_queue;
}

If an attacker can control uxEventQueueLength, they can cause an integer wraparound thus causing txfr_malloc() to allocate a small amount of memory, exposing to subsequent heap buffer overflows:

QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
{
    txfr_queueset_t *p_set;
    void *p_mem;
    ULONG queue_size;
    UINT ret;

    configASSERT(uxEventQueueLength != 0u);

#if (TX_FREERTOS_AUTO_INIT == 1)
    if(txfr_initialized != 1u) {
        tx_freertos_auto_init();
    }
#endif

    p_set = txfr_malloc(sizeof(txfr_queueset_t));
    if(p_set == NULL) {
        return NULL;
    }

    queue_size = sizeof(void *) * uxEventQueueLength;
    p_mem = txfr_malloc(queue_size); // VULN: integer wraparound and under-allocation
    if(p_mem == NULL) {
        txfr_free(p_set);
        return NULL;
    }

    ret = tx_queue_create(&p_set->queue, "", sizeof(void *) / sizeof(UINT), p_mem, queue_size);
    if(ret != TX_SUCCESS) {
        TX_FREERTOS_ASSERT_FAIL();
        return NULL;
    }

    return p_set;
}

The two functions are part of an external API to be used by user’s application. The values of those parameters passed to the vulnerable functions depend on the user’s code.

Workarounds

Strict parameters checks in user code calling xQueueCreate() and xQueueCreateSet().

References

Pending