diff --git a/History.txt b/History.txt index c9b18cb44..7baa62ab7 100644 --- a/History.txt +++ b/History.txt @@ -1,5 +1,140 @@ Documentation and download available at https://www.FreeRTOS.org/ +Changes between FreeRTOS V11.3.0 and FreeRTOS V11.3.1 released August 2026 + + + Add Symmetric Multiprocessing (SMP) support to the Armv8-M ports for the + GCC, ArmClang and IAR toolchains. This adds per core critical nesting + state, spinlocks, inter-core yield and wakeup using SEV/WFE, primary and + secondary core bring up synchronization, and a core safe PendSV context + switch. Single core builds are unchanged. We thank @AhmedIsmail02 for + their contribution. + + Add new xTaskPeriodicDelay API for periodic tasks. It supersedes + xTaskDelayUntil by preventing run away of pxPreviousWakeTime, catching up + skipped periods immediately while returning the number of periods skipped, + and returning 0 when not enough ticks have elapsed. We thank @ntd for + their contribution. + + Add uxTaskCallForEachTask API, which invokes a caller supplied callback + for each task in the system, and refactor uxTaskGetSystemState to use it. + We thank @DRNadler for their contribution. + + Add configIDLE_AFFINITY configuration option, which pins each Idle task to + its corresponding core in SMP systems. It defaults to 0, which allows the + scheduler to run Idle tasks on any available core. We thank @rus084 for + their contribution. + + Add validation to SecureContext_AllocateContext in the ARMv8-M secure side + ports to ensure that the requested secure stack size plus the stack seal + size does not overflow before allocating. We thank Jordan Mecom (Block, + Inc.) for reporting this issue. + + Add assertions to vQueueDelete to check that no tasks are blocked on the + queue being deleted. + + Add a link to the FreeRTOS Kernel threat model in SECURITY.md. + + Add documentation clarifying that the MemoryRegion_t ulParameters macros + are port specific, so applications must use the tskMPU_REGION_* or + portMPU_REGION_* values that match their MPU port. We thank @Old-Ding for + their contribution. + + Add a comment documenting that a privileged task must revoke access + permissions before deleting a kernel object when using Access Control + Lists. + + Update the ARM_CRx_No_GIC port to declare vPortYield as a weak symbol so + that devices with a dedicated software interrupt register can substitute + their own yield trigger. The default behavior is unchanged. We thank + @maximdeclercq for their contribution. + + Update the FreeRTOSConfig.h template to use a 32-bit tick type, which + avoids compiler warnings on Windows where a 64-bit tick resolves to + unsigned long long. + + Update the deprecated CMake configuration warning to use INTERFACE rather + than PUBLIC for the freertos_config interface library. We thank @Isla-jq + for their contribution. + + Fix vPortFreeSecureContext in the ARMv8-M ports to read xSecureContext at + the correct offset. When the MPU is enabled, the first item in the TCB is + the stored context location rather than the top of stack, so + xSecureContext is located at a negative offset from that position. + + Fix SecureContext_AllocateContext in the ARMv8-M secure side ports to + reject a secure stack size smaller than the stack seal size. + + Fix SecureContext_FreeContext in the ARMv8-M secure side ports to refuse + to free the secure context that is currently loaded, as indicated by + PSPLIM. Freeing it left the running task referencing freed secure memory. + The task handle supplied by the non-secure side is untrusted, so it is + now used only as an additional ownership check. + + Fix the ARMv8-M ports to service the portSVC_START_SCHEDULER and + portSVC_FREE_SECURE_CONTEXT supervisor calls only when they are raised + from privileged code. When the MPU is enabled, both requests are now + ignored unless the calling program counter lies within the privileged + functions section. + + Fix a type confusion in xQueueAddToSet by verifying that the object + passed as the queue set really is a queue set, that is, that its item + size is sizeof( Queue_t * ). Passing an ordinary queue now returns + pdFAIL rather than allowing prvNotifyQueueSetContainer to copy item size + bytes from a single pointer on the stack. + + Fix xTimerGenericCommandFromTask to validate the lower bound of + xCommandID in addition to the existing upper bound, so that only the + valid task command range from tmrCOMMAND_START_DONT_TRACE to + tmrCOMMAND_DELETE is accepted. Rejected commands return pdFAIL, and + behavior for valid commands and for xTimerGenericCommandFromISR is + unchanged. + + Fix a kernel object pool entry leak by adding an MPU wrapper for the + xTimerDelete API, so that the pool index is freed when a timer is deleted + with MPU wrappers version 2. + + Fix the MPU wrapper macro mapping for the ARMv8-M ports. + + Fix silently failing critical sections in unprivileged tasks by + disallowing configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS with MPU wrappers + version 2 in the ARMv7-M MPU ports. The option now defaults to 0 under + version 2, and explicitly setting it to 1 raises a compile time error. + Behavior with MPU wrappers version 1 is unchanged. + + Fix a time of check to time of use race condition in vTaskListTasks, where + reading the volatile task count twice allowed a task to be created between + the reads, resulting in an undersized allocation and a possible buffer + overflow in uxTaskGetSystemState. We thank @srpatcha for their + contribution. + + Fix a spurious heap_5 assertion when configENABLE_HEAP_PROTECTOR is 1 and + an allocation cannot be satisfied. The free block search reaching the end + marker is a normal out of memory condition, so pvPortMalloc now returns + NULL and invokes the malloc failed hook instead of asserting. + + Fix batching stream buffers to unblock a receiver only after the buffered + byte count exceeds, rather than reaches, the trigger level. Previously a + receiver could be woken early and xStreamBufferReceive could return 0 + bytes. Stream buffer and message buffer semantics are unchanged. We thank + @officialasishkumar for their contribution. + + Fix MISRA C 2012 Rule 20.4 violation by replacing `#define static` with a + STATIC macro, which also keeps the static variables in + vApplicationGetIdleTaskMemory and vApplicationGetPassiveIdleTaskMemory + static when portREMOVE_STATIC_QUALIFIER is defined. We thank @elsonwei for + their contribution. + + Fix undefined behavior in the MSVC-MingW port caused by left shifting a + signed int by 31 or more bits. + + Fix a duplicate Doxygen \defgroup identifier by giving + uxTaskBasePriorityGet its own group instead of reusing the + uxTaskPriorityGet group. + + Fix the incorrect #endif comment after vPortSetupTimerInterrupt in the GCC + and IAR RISC-V ports, which duplicated configMTIME_BASE_ADDRESS and + omitted configMTIMECMP_BASE_ADDRESS. We thank @cuiweixie for their + contribution. + + Fix incorrect #endif comments in croutine.c and queue.c, which reversed + the configUSE_CO_ROUTINES condition and named the wrong configuration + option for configSUPPORT_DYNAMIC_ALLOCATION. We thank @Zepp-Hanzj for + their contribution. + + Fix the configLIST_VOLATILE #endif comment and the documented parameter + names for uxListRemove in include/list.h. We thank @rakeshr-source for + their contribution. + + Fix the type and timeout values used in the xStreamBufferSend and + xMessageBufferSend documentation examples. We thank @Isla-jq for their + contribution. + + Fix copy and paste comment typos in xTaskGetApplicationTaskTag and + xTaskGetApplicationTaskTagFromISR, and a typo in the + xTaskGenericNotifyWait comment. We thank @wanghengZzz for their + contributions. + + Fix comment typos in the queue.h, list.h and task.h documentation, + including the xQueueReceiveFromISR and xQueueGenericSend examples, the + listGET_ITEM_VALUE_OF_HEAD_ENTRY \page tag, and the uxIndexToCLear typo. + We thank @zepp-chen for their contribution. + + Fix the FreeRTOSConfig.h template path referenced in README.md. We thank + @IClementI for their contribution. + + Fix the missing V prefix in the release_tag and namespace-prefix inputs of + the auto release workflow. + + Fix long path failures in the Windows kernel demo builds by enabling + Windows long path support in CI. + + Remove an unnecessary const variable from the GCC and IAR RISC-V ports. We + thank @IClementI for their contribution. + Changes between FreeRTOS V11.2.0 and FreeRTOS V11.3.0 released March 2026 + Correct minor mistakes in code comments in event_groups.c, include/queue.h, diff --git a/examples/template_configuration/FreeRTOSConfig.h b/examples/template_configuration/FreeRTOSConfig.h index 4a74fe4ca..58727854d 100644 --- a/examples/template_configuration/FreeRTOSConfig.h +++ b/examples/template_configuration/FreeRTOSConfig.h @@ -577,7 +577,7 @@ /* Defines the kernel provided implementation of * vApplicationGetIdleTaskMemory() and vApplicationGetTimerTaskMemory() * to provide the memory that is used by the Idle task and Timer task - * respectively. The application can provide it's own implementation of + * respectively. The application can provide its own implementation of * vApplicationGetIdleTaskMemory() and vApplicationGetTimerTaskMemory() by * setting configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. */ #define configKERNEL_PROVIDED_STATIC_MEMORY 1 diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 2fe2ec719..3e54f1b5e 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -1786,6 +1786,14 @@ #define traceRETURN_vTaskDelete() #endif +#ifndef traceENTER_xTaskPeriodicDelay + #define traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement ) +#endif + +#ifndef traceRETURN_xTaskPeriodicDelay + #define traceRETURN_xTaskPeriodicDelay( xIncrements ) +#endif + #ifndef traceENTER_xTaskDelayUntil #define traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) #endif diff --git a/include/croutine.h b/include/croutine.h index a5e2e4462..616553669 100644 --- a/include/croutine.h +++ b/include/croutine.h @@ -528,7 +528,7 @@ void vCoRoutineSchedule( void ); * functions used by tasks. * * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to - * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * pass data between a co-routine and ISR, whereas xQueueSendFromISR() and * xQueueReceiveFromISR() can only be used to pass data between a task and and * ISR. * @@ -628,7 +628,7 @@ void vCoRoutineSchedule( void ); * functions used by tasks. * * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to - * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * pass data between a co-routine and ISR, whereas xQueueSendFromISR() and * xQueueReceiveFromISR() can only be used to pass data between a task and and * ISR. * diff --git a/include/list.h b/include/list.h index f9a8c00f6..1c0232369 100644 --- a/include/list.h +++ b/include/list.h @@ -31,7 +31,7 @@ * heavily for the schedulers needs, it is also available for use by * application code. * - * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a + * List_t can only store pointers to ListItem_t. Each ListItem_t contains a * numeric value (xItemValue). Most of the time the lists are sorted in * ascending item value order. * @@ -42,7 +42,7 @@ * is because the tail contains a wrap back pointer to the true head of * the list. * - * In addition to it's value, each list item contains a pointer to the next + * In addition to its value, each list item contains a pointer to the next * item in the list (pxNext), a pointer to the list it is in (pxContainer) * and a pointer back to the object that contains it. These later two * pointers are included for efficiency of list manipulation. There is @@ -74,7 +74,7 @@ * compiler's options were set for maximum optimisation has been inspected and * deemed to be as intended. That said, as compiler technology advances, and * especially if aggressive cross module optimisation is used (a use case that - * has not been exercised to any great extend) then it is feasible that the + * has not been exercised to any great extent) then it is feasible that the * volatile qualifier will be needed for correct optimisation. It is expected * that a compiler removing essential code because, without the volatile * qualifier on the list structure members and with aggressive cross module @@ -219,7 +219,7 @@ typedef struct xLIST * Access macro to retrieve the value of the list item at the head of a given * list. * - * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \page listGET_ITEM_VALUE_OF_HEAD_ENTRY listGET_ITEM_VALUE_OF_HEAD_ENTRY * \ingroup LinkedList */ #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) diff --git a/include/mpu_wrappers.h b/include/mpu_wrappers.h index ebbd5f940..69e6cbb40 100644 --- a/include/mpu_wrappers.h +++ b/include/mpu_wrappers.h @@ -286,9 +286,17 @@ #else /* portUSING_MPU_WRAPPERS */ - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA - #define FREERTOS_SYSTEM_CALL + #ifndef PRIVILEGED_FUNCTION + #define PRIVILEGED_FUNCTION + #endif + + #ifndef PRIVILEGED_DATA + #define PRIVILEGED_DATA + #endif + + #ifndef FREERTOS_SYSTEM_CALL + #define FREERTOS_SYSTEM_CALL + #endif #endif /* portUSING_MPU_WRAPPERS */ diff --git a/include/queue.h b/include/queue.h index e3dbbefd2..90d185c3d 100644 --- a/include/queue.h +++ b/include/queue.h @@ -44,7 +44,7 @@ /** * Type by which queues are referenced. For example, a call to xQueueCreate() - * returns an QueueHandle_t variable that can then be used as a parameter to + * returns a QueueHandle_t variable that can then be used as a parameter to * xQueueSend(), xQueueReceive(), etc. */ struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */ @@ -60,7 +60,7 @@ typedef struct QueueDefinition * QueueSetHandle_t; /** * Queue sets can contain both queues and semaphores, so the * QueueSetMemberHandle_t is defined as a type to be used where a parameter or - * return value can be either an QueueHandle_t or an SemaphoreHandle_t. + * return value can be either a QueueHandle_t or a SemaphoreHandle_t. */ typedef struct QueueDefinition * QueueSetMemberHandle_t; @@ -185,7 +185,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * @param pucQueueStorage If uxItemSize is not zero then * pucQueueStorage must point to a uint8_t array that is at least large * enough to hold the maximum number of items that can be in the queue at any - * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is + * one time - which is ( uxQueueLength * uxItemSize ) bytes. If uxItemSize is * zero then pucQueueStorage can be NULL. * * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which @@ -604,7 +604,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * BaseType_t xQueueGenericSend( * QueueHandle_t xQueue, * const void * pvItemToQueue, - * TickType_t xTicksToWait + * TickType_t xTicksToWait, * BaseType_t xCopyPosition * ); * @endcode @@ -1189,7 +1189,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * // ... * - * if( xHigherPrioritytaskWoken == pdTRUE ) + * if( xHigherPriorityTaskWoken == pdTRUE ) * { * // Writing to the queue caused a task to unblock and the unblocked task * // has a priority higher than or equal to the priority of the currently @@ -1451,7 +1451,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, * // task will be woken. * } * - * if( xHigherPrioritytaskWoken == pdTRUE ); + * if( xHigherPriorityTaskWoken == pdTRUE ) * { * // As xHigherPriorityTaskWoken is now set to pdTRUE then a context * // switch should be requested. The macro used is port specific and @@ -1664,7 +1664,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * Note 2: Blocking on a queue set that contains a mutex will not cause the * mutex holder to inherit the priority of the blocked task. * - * Note 3: An additional 4 bytes of RAM is required for each space in a every + * Note 3: An additional 4 bytes of RAM is required for each space in every * queue added to a queue set. Therefore counting semaphores that have a high * maximum count value should not be added to a queue set. * @@ -1716,7 +1716,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * Note 2: Blocking on a queue set that contains a mutex will not cause the * mutex holder to inherit the priority of the blocked task. * - * Note 3: An additional 4 bytes of RAM is required for each space in a every + * Note 3: An additional 4 bytes of RAM is required for each space in every * queue added to a queue set. Therefore counting semaphores that have a high * maximum count value should not be added to a queue set. * @@ -1767,7 +1767,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * a call to xQueueSelectFromSet() has first returned a handle to that set member. * * @param xQueueOrSemaphore The handle of the queue or semaphore being added to - * the queue set (cast to an QueueSetMemberHandle_t type). + * the queue set (cast to a QueueSetMemberHandle_t type). * * @param xQueueSet The handle of the queue set to which the queue or semaphore * is being added. @@ -1790,7 +1790,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * function. * * @param xQueueOrSemaphore The handle of the queue or semaphore being removed - * from the queue set (cast to an QueueSetMemberHandle_t type). + * from the queue set (cast to a QueueSetMemberHandle_t type). * * @param xQueueSet The handle of the queue set in which the queue or semaphore * is included. @@ -1836,7 +1836,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * a QueueSetMemberHandle_t type) contained in the queue set that contains data, * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained * in the queue set that is available, or NULL if no such queue or semaphore - * exists before before the specified block time expires. + * exists before the specified block time expires. */ #if ( configUSE_QUEUE_SETS == 1 ) QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, diff --git a/include/task.h b/include/task.h index 679b6fcea..193d242f5 100644 --- a/include/task.h +++ b/include/task.h @@ -89,7 +89,7 @@ * task. h * * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an TaskHandle_t variable that can then + * returns (via a pointer parameter) a TaskHandle_t variable that can then * be used as a parameter to vTaskDelete to delete the task. * * \defgroup TaskHandle_t TaskHandle_t @@ -579,7 +579,7 @@ typedef enum * * Example usage: * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. + * // Create a TaskParameters_t structure that defines the task to be created. * static const TaskParameters_t xCheckTaskParameters = * { * vATask, // pvTaskCode - the function that implements the task. @@ -677,7 +677,7 @@ typedef enum * * Example usage: * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. + * // Create a TaskParameters_t structure that defines the task to be created. * // The StaticTask_t variable is only included in the structure when * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can * // be used to force the variable into the RTOS kernel's privileged data area. @@ -893,6 +893,43 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; */ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; +/** + * task. h + * @code{c} + * TickType_t xTaskPeriodicDelay( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement ); + * @endcode + * + * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Periodic task delay to ensure a constant execution frequency. + * + * This function is similar to xTaskDelayUntil () with a few important differences: + * - pxPreviousWakeTime contains the last past wake time, so it never runs away + * - if you suspend the task, when you resume it pxPreviousWakeTime will instantly + * catch up all skipped increments + * - it returns the number of increments added to pxPreviosWakeTime + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use. Following this the variable is automatically updated. + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Passing the same xTimeIncrement + * parameter value will cause the task to execute with a fixed interval. + * + * @return Number of times xTimeIncrement has been added to pxPreviousWakeTime. + * It is 0 on the first call or if not enough ticks have been elapsed since the + * last call, 1 in normal circumstances or more than 1 if some period has been + * skipped for some reason (e.g. when the caller task is suspended for more than + * xTimeIncrement ticks). + * + * \defgroup xTaskPeriodicDelay xTaskPeriodicDelay + * \ingroup TaskCtrl + */ +TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; + /** * task. h * @code{c} @@ -1038,7 +1075,7 @@ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, * // it itself. * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) * { - * // The task has changed it's priority. + * // The task has changed its priority. * } * * // ... @@ -2120,7 +2157,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for * uxTaskGetSystemState() to be available. * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * uxTaskGetSystemState() populates a TaskStatus_t structure for each task in * the system. TaskStatus_t structures contain, among other things, members * for the task handle, task name, task priority, task state, and total amount * of run time consumed by the task. See the TaskStatus_t structure @@ -3270,7 +3307,7 @@ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, /** * task. h * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear ); + * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear ); * * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); * @endcode diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/ARMv8M/non_secure/port.c +++ b/portable/ARMv8M/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portasm.c b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portasm.c index b584c63e7..bd1654759 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portasm.c +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portasm.c @@ -126,9 +126,9 @@ " restore_general_regs_first_task: \n" " subs r2, #32 \n" " ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r2, #48 \n" " ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ @@ -402,9 +402,9 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att " restore_general_regs: \n" " subs r2, #32 \n" " ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r2, #48 \n" " ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portasm.c b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portasm.c index d215f8f73..718119aad 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portasm.c +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portasm.c @@ -121,9 +121,9 @@ " restore_general_regs_first_task: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ @@ -375,9 +375,9 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att " restore_general_regs: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ diff --git a/portable/ARMv8M/secure/context/secure_context.c b/portable/ARMv8M/secure/context/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/ARMv8M/secure/context/secure_context.c +++ b/portable/ARMv8M/secure/context/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/CodeWarrior/HCS12/port.c b/portable/CodeWarrior/HCS12/port.c index 2d564cd66..fbff071ea 100644 --- a/portable/CodeWarrior/HCS12/port.c +++ b/portable/CodeWarrior/HCS12/port.c @@ -63,7 +63,7 @@ scheduler startup function. */ /* Calls to portENTER_CRITICAL() can be nested. When they are nested the critical section should not be left (i.e. interrupts should not be re-enabled) until the nesting depth reaches 0. This variable simply tracks the nesting -depth. Each task maintains it's own critical nesting depth variable so +depth. Each task maintains its own critical nesting depth variable so uxCriticalNesting is saved and restored from the task stack during a context switch. */ volatile UBaseType_t uxCriticalNesting = 0xff; diff --git a/portable/GCC/ARM_CM0/port.c b/portable/GCC/ARM_CM0/port.c index fd3229a76..a4f957796 100644 --- a/portable/GCC/ARM_CM0/port.c +++ b/portable/GCC/ARM_CM0/port.c @@ -689,7 +689,7 @@ static void prvTaskExitError( void ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return( ulReturnValue << 1UL ); } diff --git a/portable/GCC/ARM_CM0/portasm.c b/portable/GCC/ARM_CM0/portasm.c index 179a71546..4896f654d 100644 --- a/portable/GCC/ARM_CM0/portasm.c +++ b/portable/GCC/ARM_CM0/portasm.c @@ -111,9 +111,9 @@ " restore_general_regs_first_task: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ @@ -366,9 +366,9 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att " restore_general_regs: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM23/non_secure/portasm.c b/portable/GCC/ARM_CM23/non_secure/portasm.c index b584c63e7..bd1654759 100644 --- a/portable/GCC/ARM_CM23/non_secure/portasm.c +++ b/portable/GCC/ARM_CM23/non_secure/portasm.c @@ -126,9 +126,9 @@ " restore_general_regs_first_task: \n" " subs r2, #32 \n" " ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r2, #48 \n" " ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ @@ -402,9 +402,9 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att " restore_general_regs: \n" " subs r2, #32 \n" " ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r3!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r2, #48 \n" " ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ diff --git a/portable/GCC/ARM_CM23/secure/secure_context.c b/portable/GCC/ARM_CM23/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM23/secure/secure_context.c +++ b/portable/GCC/ARM_CM23/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c index d215f8f73..718119aad 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c @@ -121,9 +121,9 @@ " restore_general_regs_first_task: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ @@ -375,9 +375,9 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att " restore_general_regs: \n" " subs r1, #32 \n" " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context on the task stack. */ " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */ - " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */ + " stmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context on the task stack. */ " subs r1, #48 \n" " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */ " mov r8, r4 \n" /* r8 = r4. */ diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM33/secure/secure_context.c b/portable/GCC/ARM_CM33/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM33/secure/secure_context.c +++ b/portable/GCC/ARM_CM33/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM35P/non_secure/port.c b/portable/GCC/ARM_CM35P/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM35P/non_secure/port.c +++ b/portable/GCC/ARM_CM35P/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM35P/secure/secure_context.c b/portable/GCC/ARM_CM35P/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM35P/secure/secure_context.c +++ b/portable/GCC/ARM_CM35P/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c index c8d3439b6..6b7ed02a0 100644 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -96,12 +96,14 @@ typedef void ( * portISR_t )( void ); #define portPERIPHERALS_START_ADDRESS 0x40000000UL #define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL -/* Constants required to access and manipulate the SysTick. */ +/* Constants required to access and manipulate the SysTick and other FreeRTOS + * interrupts. */ #define portNVIC_SYSTICK_INT ( 0x00000002UL ) #define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) /* Constants required to set up the initial stack. */ #define portINITIAL_XPSR ( 0x01000000 ) @@ -877,12 +879,11 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall - * the highest priority. */ + /* Make PendSV and SysTick the lowest priority interrupts, and configure + * SVCall for sufficient preemption priority. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - portNVIC_SHPR2_REG = 0; - + portNVIC_SHPR2_REG = portNVIC_SVC_PRI; /* Configure the regions in the MPU that are common to all tasks. */ prvSetupMPU(); @@ -1206,7 +1207,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return( ulReturnValue << 1UL ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index 5a3527157..e1a70c511 100644 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -106,12 +106,14 @@ typedef void ( * portISR_t )( void ); #define portPERIPHERALS_START_ADDRESS 0x40000000UL #define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL -/* Constants required to access and manipulate the SysTick. */ +/* Constants required to access and manipulate the SysTick and other FreeRTOS + * interrupts. */ #define portNVIC_SYSTICK_INT ( 0x00000002UL ) #define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) /* Constants required to manipulate the VFP. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ @@ -965,11 +967,11 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall - * the highest priority. */ + /* Make PendSV and SysTick the lowest priority interrupts, and configure + * SVCall for sufficient preemption priority. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - portNVIC_SHPR2_REG = 0; + portNVIC_SHPR2_REG = portNVIC_SVC_PRI; /* Configure the regions in the MPU that are common to all tasks. */ prvSetupMPU(); @@ -1350,7 +1352,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return( ulReturnValue << 1UL ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM52/non_secure/port.c b/portable/GCC/ARM_CM52/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM52/non_secure/port.c +++ b/portable/GCC/ARM_CM52/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM52/secure/secure_context.c b/portable/GCC/ARM_CM52/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM52/secure/secure_context.c +++ b/portable/GCC/ARM_CM52/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM52_NTZ/non_secure/port.c b/portable/GCC/ARM_CM52_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM52_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM52_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM55/non_secure/port.c b/portable/GCC/ARM_CM55/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM55/non_secure/port.c +++ b/portable/GCC/ARM_CM55/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM55/secure/secure_context.c b/portable/GCC/ARM_CM55/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM55/secure/secure_context.c +++ b/portable/GCC/ARM_CM55/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM85/non_secure/port.c b/portable/GCC/ARM_CM85/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM85/non_secure/port.c +++ b/portable/GCC/ARM_CM85/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CM85/secure/secure_context.c b/portable/GCC/ARM_CM85/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_CM85/secure/secure_context.c +++ b/portable/GCC/ARM_CM85/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_CRx_MPU/port.c b/portable/GCC/ARM_CRx_MPU/port.c index 56ff38384..f21ea49ae 100644 --- a/portable/GCC/ARM_CRx_MPU/port.c +++ b/portable/GCC/ARM_CRx_MPU/port.c @@ -489,7 +489,7 @@ static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return ulReturnValue << 1UL; } diff --git a/portable/GCC/ARM_STAR_MC3/non_secure/port.c b/portable/GCC/ARM_STAR_MC3/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_STAR_MC3/non_secure/port.c +++ b/portable/GCC/ARM_STAR_MC3/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/ARM_STAR_MC3/secure/secure_context.c b/portable/GCC/ARM_STAR_MC3/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/GCC/ARM_STAR_MC3/secure/secure_context.c +++ b/portable/GCC/ARM_STAR_MC3/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c b/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/GCC/HCS12/port.c b/portable/GCC/HCS12/port.c index 4355a3f11..77c03801c 100644 --- a/portable/GCC/HCS12/port.c +++ b/portable/GCC/HCS12/port.c @@ -64,7 +64,7 @@ BaseType_t ATTR_NEAR xStartSchedulerNear( void ); /* Calls to portENTER_CRITICAL() can be nested. When they are nested the * critical section should not be left (i.e. interrupts should not be re-enabled) * until the nesting depth reaches 0. This variable simply tracks the nesting - * depth. Each task maintains it's own critical nesting depth variable so + * depth. Each task maintains its own critical nesting depth variable so * uxCriticalNesting is saved and restored from the task stack during a context * switch. */ volatile UBaseType_t uxCriticalNesting = 0x80; /* un-initialized */ diff --git a/portable/GCC/MicroBlaze/port.c b/portable/GCC/MicroBlaze/port.c index fb8b410be..7b987949a 100644 --- a/portable/GCC/MicroBlaze/port.c +++ b/portable/GCC/MicroBlaze/port.c @@ -63,7 +63,7 @@ #define portISR_STACK_FILL_VALUE 0x55555555 /* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task - * maintains it's own count, so this variable is saved as part of the task + * maintains its own count, so this variable is saved as part of the task * context. */ volatile UBaseType_t uxCriticalNesting = portINITIAL_NESTING_VALUE; @@ -235,7 +235,7 @@ void vPortYield( void ) /* Perform the context switch in a critical section to assure it is * not interrupted by the tick ISR. It is not a problem to do this as - * each task maintains it's own interrupt status. */ + * each task maintains its own interrupt status. */ portENTER_CRITICAL(); /* Jump directly to the yield function to ensure there is no diff --git a/portable/GCC/MicroBlazeV8/portmacro.h b/portable/GCC/MicroBlazeV8/portmacro.h index d23214ea4..e8e0f3686 100644 --- a/portable/GCC/MicroBlazeV8/portmacro.h +++ b/portable/GCC/MicroBlazeV8/portmacro.h @@ -322,7 +322,7 @@ void vApplicationSetupTimerInterrupt( void ); /* * This is an application defined callback function used to clear whichever - * interrupt was installed by the the vApplicationSetupTimerInterrupt() callback + * interrupt was installed by the vApplicationSetupTimerInterrupt() callback * function - in this case the interrupt generated by the AXI timer. It is * provided as an application callback because the kernel will run on lots of * different MicroBlaze and FPGA configurations - not all of which will have the diff --git a/portable/GCC/MicroBlazeV9/portmacro.h b/portable/GCC/MicroBlazeV9/portmacro.h index 1fb9c8259..c3556f94c 100644 --- a/portable/GCC/MicroBlazeV9/portmacro.h +++ b/portable/GCC/MicroBlazeV9/portmacro.h @@ -337,7 +337,7 @@ void vApplicationSetupTimerInterrupt( void ); /* * This is an application defined callback function used to clear whichever - * interrupt was installed by the the vApplicationSetupTimerInterrupt() callback + * interrupt was installed by the vApplicationSetupTimerInterrupt() callback * function - in this case the interrupt generated by the AXI timer. It is * provided as an application callback because the kernel will run on lots of * different MicroBlaze and FPGA configurations - not all of which will have the diff --git a/portable/GCC/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM/freertos_risc_v_chip_specific_extensions.h b/portable/GCC/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM/freertos_risc_v_chip_specific_extensions.h index 4d8a5fb53..25c1b7fba 100644 --- a/portable/GCC/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM/freertos_risc_v_chip_specific_extensions.h +++ b/portable/GCC/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM/freertos_risc_v_chip_specific_extensions.h @@ -27,7 +27,7 @@ */ /* - * The FreeRTOS kernel's RISC-V port is split between the the code that is + * The FreeRTOS kernel's RISC-V port is split between the code that is * common across all currently supported RISC-V chips (implementations of the * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: * diff --git a/portable/GCC/RISC-V/chip_specific_extensions/RISCV_MTIME_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h b/portable/GCC/RISC-V/chip_specific_extensions/RISCV_MTIME_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h index 3be456cb4..a9599395d 100644 --- a/portable/GCC/RISC-V/chip_specific_extensions/RISCV_MTIME_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h +++ b/portable/GCC/RISC-V/chip_specific_extensions/RISCV_MTIME_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h @@ -27,7 +27,7 @@ */ /* - * The FreeRTOS kernel's RISC-V port is split between the the code that is + * The FreeRTOS kernel's RISC-V port is split between the code that is * common across all currently supported RISC-V chips (implementations of the * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: * diff --git a/portable/GCC/RISC-V/chip_specific_extensions/RISCV_no_extensions/freertos_risc_v_chip_specific_extensions.h b/portable/GCC/RISC-V/chip_specific_extensions/RISCV_no_extensions/freertos_risc_v_chip_specific_extensions.h index 9f93824bd..a55d66a94 100644 --- a/portable/GCC/RISC-V/chip_specific_extensions/RISCV_no_extensions/freertos_risc_v_chip_specific_extensions.h +++ b/portable/GCC/RISC-V/chip_specific_extensions/RISCV_no_extensions/freertos_risc_v_chip_specific_extensions.h @@ -27,7 +27,7 @@ */ /* - * The FreeRTOS kernel's RISC-V port is split between the the code that is + * The FreeRTOS kernel's RISC-V port is split between the code that is * common across all currently supported RISC-V chips (implementations of the * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: * diff --git a/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h b/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h index 5b9ef4c06..f738a6a3d 100644 --- a/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h +++ b/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h @@ -27,7 +27,7 @@ */ /* - * The FreeRTOS kernel's RISC-V port is split between the the code that is + * The FreeRTOS kernel's RISC-V port is split between the code that is * common across all currently supported RISC-V chips (implementations of the * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: * diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM23/non_secure/port.c +++ b/portable/IAR/ARM_CM23/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM23/secure/secure_context.c b/portable/IAR/ARM_CM23/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM23/secure/secure_context.c +++ b/portable/IAR/ARM_CM23/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM33/non_secure/port.c +++ b/portable/IAR/ARM_CM33/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM33/secure/secure_context.c b/portable/IAR/ARM_CM33/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM33/secure/secure_context.c +++ b/portable/IAR/ARM_CM33/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM35P/non_secure/port.c b/portable/IAR/ARM_CM35P/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM35P/non_secure/port.c +++ b/portable/IAR/ARM_CM35P/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM35P/secure/secure_context.c b/portable/IAR/ARM_CM35P/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM35P/secure/secure_context.c +++ b/portable/IAR/ARM_CM35P/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c index 0441e0f0c..a3b6517ef 100644 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -120,9 +120,11 @@ typedef void ( * portISR_t )( void ); #define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) #define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) +/* Constants to manipulate FreeRTOS interrupt priorities. */ #define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) /* Constants used to check the installation of the FreeRTOS interrupt handlers. */ #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) ) @@ -862,11 +864,11 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall - * the highest priority. */ + /* Make PendSV and SysTick the lowest priority interrupts, and configure + * SVCall for sufficient preemption priority. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - portNVIC_SHPR2_REG = 0; + portNVIC_SHPR2_REG = portNVIC_SVC_PRI; /* Configure the regions in the MPU that are common to all tasks. */ prvSetupMPU(); @@ -1139,7 +1141,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return( ulReturnValue << 1UL ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM52/non_secure/port.c b/portable/IAR/ARM_CM52/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM52/non_secure/port.c +++ b/portable/IAR/ARM_CM52/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM52/secure/secure_context.c b/portable/IAR/ARM_CM52/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM52/secure/secure_context.c +++ b/portable/IAR/ARM_CM52/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM52_NTZ/non_secure/port.c b/portable/IAR/ARM_CM52_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM52_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM52_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM55/non_secure/port.c b/portable/IAR/ARM_CM55/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM55/non_secure/port.c +++ b/portable/IAR/ARM_CM55/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM55/secure/secure_context.c b/portable/IAR/ARM_CM55/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM55/secure/secure_context.c +++ b/portable/IAR/ARM_CM55/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM85/non_secure/port.c b/portable/IAR/ARM_CM85/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM85/non_secure/port.c +++ b/portable/IAR/ARM_CM85/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_CM85/secure/secure_context.c b/portable/IAR/ARM_CM85/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_CM85/secure/secure_context.c +++ b/portable/IAR/ARM_CM85/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_STAR_MC3/non_secure/port.c b/portable/IAR/ARM_STAR_MC3/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_STAR_MC3/non_secure/port.c +++ b/portable/IAR/ARM_STAR_MC3/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/ARM_STAR_MC3/secure/secure_context.c b/portable/IAR/ARM_STAR_MC3/secure/secure_context.c index a91e5e891..daf0d9458 100644 --- a/portable/IAR/ARM_STAR_MC3/secure/secure_context.c +++ b/portable/IAR/ARM_STAR_MC3/secure/secure_context.c @@ -214,8 +214,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void ) if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS ) { /* Allocate the stack space if possible. */ - if( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) + if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) || + ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) ) { + /* Reject stacks that are too small (the CONTROL word would be + * written before the allocation, corrupting the secure heap) + * and sizes that would overflow when the seal size is added. */ pucStackMemory = NULL; } else @@ -286,9 +290,12 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl void * pvTaskHandle ) { uint32_t ulIPSR, ulSecureContextIndex; + uint8_t * pucStackLimit; - /* Read the Interrupt Program Status Register (IPSR) value. */ + /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit + * Register (PSPLIM) value. */ secureportREAD_IPSR( ulIPSR ); + secureportREAD_PSPLIM( pucStackLimit ); /* Do nothing if the processor is running in the Thread Mode. IPSR is zero * when the processor is running in the Thread Mode. */ @@ -300,8 +307,14 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl ulSecureContextIndex = xSecureContextHandle - 1UL; /* Ensure that the secure context being deleted is associated with - * the task. */ - if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) + * the task and is NOT the currently-loaded context. Freeing a + * context whose stack is currently loaded in PSPLIM would leave the + * running task referencing freed secure memory (use-after-free). + * pvTaskHandle is supplied by the non-secure side and is untrusted, + * so it is used only as an additional ownership match, not as + * authority. */ + if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) && + ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) ) { /* Free the stack space. */ vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit ); @@ -349,7 +362,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandl secureportREAD_PSPLIM( pucStackLimit ); - /* Ensure that task's context is loaded and the task is saving it's own + /* Ensure that task's context is loaded and the task is saving its own * context. */ if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) && ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) ) diff --git a/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c b/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c index 2bb4c1d44..9c3794c6b 100644 --- a/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c @@ -1109,7 +1109,6 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO { #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __syscalls_flash_start__; @@ -1121,6 +1120,19 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO #endif /* defined( __ARMCC_VERSION ) */ #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU == 1 */ + uint32_t ulPC; #if ( configENABLE_TRUSTZONE == 1 ) @@ -1170,39 +1182,54 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO break; case portSVC_FREE_SECURE_CONTEXT: + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) + { + #endif /* configENABLE_MPU */ + /* R0 contains TCB being freed and R1 contains the secure + * context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + ulR1 = pulCallerStackAddress[ 1 ]; - /* R0 contains TCB being freed and R1 contains the secure - * context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - ulR1 = pulCallerStackAddress[ 1 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 ); + #if ( configENABLE_MPU == 1 ) + } + #endif /* configENABLE_MPU */ break; #endif /* configENABLE_TRUSTZONE */ case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) + #if ( configENABLE_MPU == 1 ) + if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) && + ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) ) { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + #endif /* configENABLE_MPU */ + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + #if ( configENABLE_MPU == 1 ) } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); + #endif /* configENABLE_MPU */ break; #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) ) diff --git a/portable/IAR/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h b/portable/IAR/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h index 364fd5773..49c6479f0 100644 --- a/portable/IAR/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h +++ b/portable/IAR/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions/freertos_risc_v_chip_specific_extensions.h @@ -27,7 +27,7 @@ */ /* - * The FreeRTOS kernel's RISC-V port is split between the the code that is + * The FreeRTOS kernel's RISC-V port is split between the code that is * common across all currently supported RISC-V chips (implementations of the * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: * diff --git a/portable/MPLAB/PIC32MEC14xx/ISR_Support.h b/portable/MPLAB/PIC32MEC14xx/ISR_Support.h index ce7c4ad63..ad6c91487 100644 --- a/portable/MPLAB/PIC32MEC14xx/ISR_Support.h +++ b/portable/MPLAB/PIC32MEC14xx/ISR_Support.h @@ -78,7 +78,7 @@ la k0, uxInterruptNesting lw s6, (k0) - /* If the nesting count is 0 then swap to the the system stack, otherwise + /* If the nesting count is 0 then swap to the system stack, otherwise the system stack is already being used. */ bne s6, zero, 1f nop diff --git a/portable/MPLAB/PIC32MX/ISR_Support.h b/portable/MPLAB/PIC32MX/ISR_Support.h index 0bff08fe1..b92838895 100644 --- a/portable/MPLAB/PIC32MX/ISR_Support.h +++ b/portable/MPLAB/PIC32MX/ISR_Support.h @@ -60,7 +60,7 @@ la k0, uxInterruptNesting lw s6, (k0) - /* If the nesting count is 0 then swap to the the system stack, otherwise + /* If the nesting count is 0 then swap to the system stack, otherwise the system stack is already being used. */ bne s6, zero, 1f nop diff --git a/portable/MPLAB/PIC32MZ/ISR_Support.h b/portable/MPLAB/PIC32MZ/ISR_Support.h index 292877f42..396e345a0 100644 --- a/portable/MPLAB/PIC32MZ/ISR_Support.h +++ b/portable/MPLAB/PIC32MZ/ISR_Support.h @@ -174,7 +174,7 @@ la k0, uxInterruptNesting lw s6, (k0) - /* If the nesting count is 0 then swap to the the system stack, otherwise + /* If the nesting count is 0 then swap to the system stack, otherwise the system stack is already being used. */ bne s6, zero, 1f nop diff --git a/portable/RVDS/ARM_CM4_MPU/port.c b/portable/RVDS/ARM_CM4_MPU/port.c index 8620325ca..7cdf3ea87 100644 --- a/portable/RVDS/ARM_CM4_MPU/port.c +++ b/portable/RVDS/ARM_CM4_MPU/port.c @@ -95,13 +95,15 @@ typedef void ( * portISR_t )( void ); #define portPERIPHERALS_START_ADDRESS 0x40000000UL #define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL -/* Constants required to access and manipulate the SysTick. */ +/* Constants required to access and manipulate the SysTick and other FreeRTOS + * interrupts. */ #define portNVIC_SYSTICK_CLK ( 0x00000004UL ) #define portNVIC_SYSTICK_INT ( 0x00000002UL ) #define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) /* Constants required to manipulate the VFP. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ @@ -966,12 +968,11 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the same priority as the kernel, and the SVC - * handler highest priority so it can be used to exit a critical section - * (where lower priorities are masked). */ + /* Make PendSV and SysTick the lowest priority interrupts, and configure + * SVCall for sufficient preemption priority. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - portNVIC_SHPR2_REG = 0; + portNVIC_SHPR2_REG = portNVIC_SVC_PRI; /* Configure the regions in the MPU that are common to all tasks. */ prvSetupMPU(); @@ -1351,7 +1352,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) } /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ + * into the correct bit position of the attribute register. */ return( ulReturnValue << 1UL ); } /*-----------------------------------------------------------*/ diff --git a/portable/ThirdParty/Partner-Supported-Ports b/portable/ThirdParty/Partner-Supported-Ports index abc22103e..fccbbce9b 160000 --- a/portable/ThirdParty/Partner-Supported-Ports +++ b/portable/ThirdParty/Partner-Supported-Ports @@ -1 +1 @@ -Subproject commit abc22103e1e6634b33457d4127bff1ab62f27f90 +Subproject commit fccbbce9bd7e227ee211b01fdbbcf133dc3a474a diff --git a/queue.c b/queue.c index 83c7ac730..41ef8ef91 100644 --- a/queue.c +++ b/queue.c @@ -3225,7 +3225,16 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) taskENTER_CRITICAL(); { - if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + if( ( ( Queue_t * ) xQueueSet )->uxItemSize != ( UBaseType_t ) sizeof( Queue_t * ) ) + { + /* The object passed as the queue set is not a queue set. A queue + * set always has an item size of sizeof( Queue_t * ). Reject any + * other object to prevent a type confusion in which + * prvNotifyQueueSetContainer() would later copy uxItemSize bytes + * from a single pointer on the stack. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) { /* Cannot add a queue/semaphore to more than one queue set. */ xReturn = pdFAIL; diff --git a/stream_buffer.c b/stream_buffer.c index a4c6d268d..57ac1be06 100644 --- a/stream_buffer.c +++ b/stream_buffer.c @@ -272,7 +272,7 @@ static BaseType_t prvBytesInBufferMeetTriggerLevel( const StreamBuffer_t * const * the length and data bytes are written in two separate chunks, and we don't want * the reader to see the buffer as having grown until after all data is copied over. * This function takes a custom xHead value to indicate where to write to (necessary - * for chaining) and returns the the resulting xHead position. + * for chaining) and returns the resulting xHead position. * To mark the write as complete, manually set the buffer's xHead field with the * returned xHead from this function. */ @@ -314,7 +314,7 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, * the writer to see the buffer as having more free space until after all data is * copied over, especially if we have to abort the read due to insufficient receiving space. * This function takes a custom xTail value to indicate where to read from (necessary - * for chaining) and returns the the resulting xTail position. + * for chaining) and returns the resulting xTail position. * To mark the read as complete, manually set the buffer's xTail field with the * returned xTail from this function. */ diff --git a/tasks.c b/tasks.c index e11712927..43c9063c0 100644 --- a/tasks.c +++ b/tasks.c @@ -2362,6 +2362,55 @@ STATIC void prvInitialiseNewTask( TaskFunction_t pxTaskCode, #if ( INCLUDE_xTaskDelayUntil == 1 ) + TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) + { + TickType_t xIncrements, xTicksIncrements, xTicksToWait; + + traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement ); + + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + + vTaskSuspendAll(); + { + /* As long as everything is the same type, this plays well with overflows */ + const TickType_t xTicksElapsed = xTickCount - *pxPreviousWakeTime; + + configASSERT( uxSchedulerSuspended == 1U ); + + /* Number of increments to catch up: it could be 0 if + * not enough ticks have elapsed, 1 in the common case or + * more than 1 if the task has not been resumed in time */ + xIncrements = xTicksElapsed / xTimeIncrement; + xTicksIncrements = xIncrements * xTimeIncrement; + + /* Update to the last wake time */ + *pxPreviousWakeTime += xTicksIncrements; + + /* Ticks to the next wake time */ + xTicksToWait = xTimeIncrement - ( xTicksElapsed - xTicksIncrements ); + + prvAddCurrentTaskToDelayedList( xTicksToWait, pdFALSE ); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + * have put ourselves to sleep. */ + if( xTaskResumeAll() == pdFALSE ) + { + taskYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceRETURN_xTaskPeriodicDelay( xIncrements ); + + return xIncrements; + } + + BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) { @@ -7930,7 +7979,7 @@ TickType_t uxTaskResetEventItemValue( void ) *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ]; } - /* If ucNotifyValue is set then either the task never entered the + /* If ucNotifyState is set then either the task never entered the * blocked state (because a notification was already pending) or the * task unblocked because of a notification. Otherwise the task * unblocked because of a timeout. */ @@ -8800,7 +8849,7 @@ STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, * This is the kernel provided implementation of vApplicationGetIdleTaskMemory() * to provide the memory that is used by the Idle task. It is used when * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide - * it's own implementation of vApplicationGetIdleTaskMemory by setting + * its own implementation of vApplicationGetIdleTaskMemory by setting * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. */ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, @@ -8841,7 +8890,7 @@ STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, * This is the kernel provided implementation of vApplicationGetTimerTaskMemory() * to provide the memory that is used by the Timer service task. It is used when * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide - * it's own implementation of vApplicationGetTimerTaskMemory by setting + * its own implementation of vApplicationGetTimerTaskMemory by setting * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, diff --git a/timers.c b/timers.c index cfa2ee475..53e1be90b 100644 --- a/timers.c +++ b/timers.c @@ -524,9 +524,11 @@ xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; xMessage.u.xTimerParameters.pxTimer = xTimer; - configASSERT( xCommandID < tmrFIRST_FROM_ISR_COMMAND ); + /* Enforce a lower bound as well as an upper bound so that only + * valid task-issued commands are accepted here. */ + configASSERT( ( xCommandID >= tmrCOMMAND_START_DONT_TRACE ) && ( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) ); - if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) + if( ( xCommandID >= tmrCOMMAND_START_DONT_TRACE ) && ( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) ) { if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) {