mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Remove local stack variable form MPU wrappers
It was possible for a third party that had already independently gained the ability to execute injected code to achieve further privilege escalation by branching directly inside a FreeRTOS MPU API wrapper function with a manually crafted stack frame. This commit removes the local stack variable `xRunningPrivileged` so that a manually crafted stack frame cannot be used for privilege escalation by branching directly inside a FreeRTOS MPU API wrapper. We thank Certibit Consulting, LLC, Huazhong University of Science and Technology and the SecLab team at Northeastern University for reporting this issue. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
This commit is contained in:
parent
c4ad77f694
commit
51ea2bfe62
2
.github/lexicon.txt
vendored
2
.github/lexicon.txt
vendored
|
@ -2533,7 +2533,6 @@ vportgetheapstats
|
||||||
vportinitialiseblocks
|
vportinitialiseblocks
|
||||||
vportisrstartfirststask
|
vportisrstartfirststask
|
||||||
vportraisebasepri
|
vportraisebasepri
|
||||||
vportresetprivilege
|
|
||||||
vportsetmpuregistersetone
|
vportsetmpuregistersetone
|
||||||
vportsetuptimerinterrupt
|
vportsetuptimerinterrupt
|
||||||
vportstartfirststask
|
vportstartfirststask
|
||||||
|
@ -2852,7 +2851,6 @@ xperiod
|
||||||
xportgetcoreid
|
xportgetcoreid
|
||||||
xportgetfreeheapsize
|
xportgetfreeheapsize
|
||||||
xportinstallinterrupthandler
|
xportinstallinterrupthandler
|
||||||
xportraiseprivilege
|
|
||||||
xportregistercinterrupthandler
|
xportregistercinterrupthandler
|
||||||
xportregisterdump
|
xportregisterdump
|
||||||
xportstartfirsttask
|
xportstartfirsttask
|
||||||
|
|
|
@ -170,36 +170,6 @@
|
||||||
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
|
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
|
||||||
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
|
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calls the port specific code to raise the privilege.
|
|
||||||
*
|
|
||||||
* Sets xRunningPrivileged to pdFALSE if privilege was raised, else sets
|
|
||||||
* it to pdTRUE.
|
|
||||||
*/
|
|
||||||
#define xPortRaisePrivilege( xRunningPrivileged ) \
|
|
||||||
{ \
|
|
||||||
/* Check whether the processor is already privileged. */ \
|
|
||||||
xRunningPrivileged = portIS_PRIVILEGED(); \
|
|
||||||
\
|
|
||||||
/* If the processor is not already privileged, raise privilege. */ \
|
|
||||||
if( xRunningPrivileged == pdFALSE ) \
|
|
||||||
{ \
|
|
||||||
portRAISE_PRIVILEGE(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief If xRunningPrivileged is not pdTRUE, calls the port specific
|
|
||||||
* code to reset the privilege, otherwise does nothing.
|
|
||||||
*/
|
|
||||||
#define vPortResetPrivilege( xRunningPrivileged ) \
|
|
||||||
{ \
|
|
||||||
if( xRunningPrivileged == pdFALSE ) \
|
|
||||||
{ \
|
|
||||||
portRESET_PRIVILEGE(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||||
|
|
||||||
#else /* portUSING_MPU_WRAPPERS */
|
#else /* portUSING_MPU_WRAPPERS */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -478,30 +478,55 @@ void vPortEndScheduler( void )
|
||||||
|
|
||||||
void vPortEnterCritical( void )
|
void vPortEnterCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
{
|
||||||
|
portRAISE_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
uxCriticalNesting++;
|
uxCriticalNesting++;
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortExitCritical( void )
|
void vPortExitCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
|
||||||
|
|
||||||
configASSERT( uxCriticalNesting );
|
|
||||||
uxCriticalNesting--;
|
|
||||||
|
|
||||||
if( uxCriticalNesting == 0 )
|
|
||||||
{
|
{
|
||||||
portENABLE_INTERRUPTS();
|
portRAISE_PRIVILEGE();
|
||||||
}
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -514,30 +514,55 @@ void vPortEndScheduler( void )
|
||||||
|
|
||||||
void vPortEnterCritical( void )
|
void vPortEnterCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
{
|
||||||
|
portRAISE_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
uxCriticalNesting++;
|
uxCriticalNesting++;
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortExitCritical( void )
|
void vPortExitCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
|
||||||
|
|
||||||
configASSERT( uxCriticalNesting );
|
|
||||||
uxCriticalNesting--;
|
|
||||||
|
|
||||||
if( uxCriticalNesting == 0 )
|
|
||||||
{
|
{
|
||||||
portENABLE_INTERRUPTS();
|
portRAISE_PRIVILEGE();
|
||||||
}
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -442,41 +442,73 @@ void vPortEndScheduler( void )
|
||||||
|
|
||||||
void vPortEnterCritical( void )
|
void vPortEnterCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
|
||||||
|
|
||||||
portDISABLE_INTERRUPTS();
|
|
||||||
uxCriticalNesting++;
|
|
||||||
|
|
||||||
/* This is not the interrupt safe version of the enter critical function so
|
|
||||||
* assert() if it is being called from an interrupt context. Only API
|
|
||||||
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
|
||||||
* the critical nesting count is 1 to protect against recursive calls if the
|
|
||||||
* assert function also uses a critical section. */
|
|
||||||
if( uxCriticalNesting == 1 )
|
|
||||||
{
|
{
|
||||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
portRAISE_PRIVILEGE();
|
||||||
}
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
* assert() if it is being called from an interrupt context. Only API
|
||||||
|
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
* the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
* assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
* assert() if it is being called from an interrupt context. Only API
|
||||||
|
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
* the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
* assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortExitCritical( void )
|
void vPortExitCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
|
||||||
|
|
||||||
configASSERT( uxCriticalNesting );
|
|
||||||
|
|
||||||
uxCriticalNesting--;
|
|
||||||
|
|
||||||
if( uxCriticalNesting == 0 )
|
|
||||||
{
|
{
|
||||||
portENABLE_INTERRUPTS();
|
portRAISE_PRIVILEGE();
|
||||||
}
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -517,30 +517,55 @@ void vPortEndScheduler( void )
|
||||||
|
|
||||||
void vPortEnterCritical( void )
|
void vPortEnterCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
{
|
||||||
|
portRAISE_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
uxCriticalNesting++;
|
uxCriticalNesting++;
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortExitCritical( void )
|
void vPortExitCritical( void )
|
||||||
{
|
{
|
||||||
BaseType_t xRunningPrivileged;
|
if( portIS_PRIVILEGED() == pdFALSE )
|
||||||
xPortRaisePrivilege( xRunningPrivileged );
|
|
||||||
|
|
||||||
configASSERT( uxCriticalNesting );
|
|
||||||
uxCriticalNesting--;
|
|
||||||
|
|
||||||
if( uxCriticalNesting == 0 )
|
|
||||||
{
|
{
|
||||||
portENABLE_INTERRUPTS();
|
portRAISE_PRIVILEGE();
|
||||||
}
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
|
||||||
|
portRESET_PRIVILEGE();
|
||||||
|
portMEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue