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:
Gaurav Aggarwal 2022-09-07 19:49:48 +05:30 committed by Gaurav-Aggarwal-AWS
parent c4ad77f694
commit 51ea2bfe62
7 changed files with 1642 additions and 497 deletions

View file

@ -442,41 +442,73 @@ void vPortEndScheduler( void )
void vPortEnterCritical( void )
{
BaseType_t xRunningPrivileged;
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 )
if( portIS_PRIVILEGED() == pdFALSE )
{
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 )
{
BaseType_t xRunningPrivileged;
xPortRaisePrivilege( xRunningPrivileged );
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
if( portIS_PRIVILEGED() == pdFALSE )
{
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();
}
}
}
/*-----------------------------------------------------------*/