CVE-2021-32020 (C, published 2021-05-03T22:15Z)
Description: value: The kernel in Amazon Web Services FreeRTOS before 10.4.3 has insufficient bounds checking during management of heap memory.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-119 \u2014 Improper Restriction of Operations within the Bounds of a Memory Buffer
The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Repository: https://github.com/FreeRTOS/FreeRTOS-Kernel
Files changed:
portable/MemMang/heap_1.c
portable/MemMang/heap_2.c
portable/MemMang/heap_4.c
portable/MemMang/heap_5.c
Commit message: Improve heap2 bounds checking (#224)

* Improve heap bounds checking in pvPortMalloc

Vulnerable code:
 * 1 tab == 4 spaces!
    /* Ensure that blocks are always aligned to the required number of bytes. */
                /* Byte alignment required. */
                xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
        /* Check there is enough room left for the allocation. */
        if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
 * 1 tab == 4 spaces!
        /* The wanted size is increased so it can contain a BlockLink_t
        if( xWantedSize > 0 )
            /* Ensure that blocks are always aligned to the required number of bytes. */
            if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 )
                /* Byte alignment required. */
        if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) )
            /* The wanted size is increased so it can contain a BlockLink_t
            if( xWantedSize > 0 )
                /* Ensure that blocks are always aligned to the required number
                 * of bytes. */
                    /* Byte alignment required. */
                    xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                    configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
            }
            else
                mtCOVERAGE_TEST_MARKER();
                 * one	of adequate size is found. */
                 * was	not found. */
 * 1 tab == 4 spaces!
            if( xWantedSize > 0 )
                /* Ensure that blocks are always aligned to the required number
                 * of bytes. */
                    /* Byte alignment required. */
                    xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                mtCOVERAGE_TEST_MARKER();
                 * one	of adequate size is found. */
                 * was	not found. */

Fixed code:
    /* Ensure that blocks are always aligned. */
                /* Byte alignment required. Check for overflow. */
                if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize )
                {
                    xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                } 
                else 
                {
                    xWantedSize = 0;
                }
        /* Check there is enough room left for the allocation and. */
        if( ( xWantedSize > 0 ) && /* valid size */
            ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
        /* The wanted size must be increased so it can contain a BlockLink_t
        if( ( xWantedSize > 0 ) && 
            ( ( xWantedSize + heapSTRUCT_SIZE ) >  xWantedSize ) ) /* Overflow check */
            /* Byte alignment required. Check for overflow. */
            if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) 
                    > xWantedSize )
                configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
            else
            {
                xWantedSize = 0;
            }       
        }
        else 
        {
            xWantedSize = 0; 

        if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
            /* The wanted size must be increased so it can contain a BlockLink_t
            if( ( xWantedSize > 0 ) && 
                ( ( xWantedSize + xHeapStructSize ) >  xWantedSize ) ) /* Overflow check */
                /* Ensure that blocks are always aligned. */
                    /* Byte alignment required. Check for overflow. */
                    if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) 
                            > xWantedSize )
                    {
                        xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                        configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
                    }
                    else
                    {
                        xWantedSize = 0;
                    }  
            } 
            else 
                xWantedSize = 0;
                 * one of adequate size is found. */
                 * was not found. */
            if( ( xWantedSize > 0 ) && 
                ( ( xWantedSize + xHeapStructSize ) >  xWantedSize ) ) /* Overflow check */
                /* Ensure that blocks are always aligned */
                    /* Byte alignment required. Check for overflow */
                    if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) >
                         xWantedSize )
                    {
                        xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
                    } 
                    else 
                    {
                        xWantedSize = 0;
                    }
                xWantedSize = 0;
                 * one of adequate size is found. */
                 * was not found. */