/*
* FreeRTOS Kernel < DEVELOPMENT BRANCH >
* Copyright ( C ) 2021 Amazon . com , Inc . or its affiliates . All Rights Reserved .
*
* SPDX - License - Identifier : MIT
*
* Permission is hereby granted , free of charge , to any person obtaining a copy of
* this software and associated documentation files ( the " Software " ) , to deal in
* the Software without restriction , including without limitation the rights to
* use , copy , modify , merge , publish , distribute , sublicense , and / or sell copies of
* the Software , and to permit persons to whom the Software is furnished to do so ,
* subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY , FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER
* IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*
* https : //www.FreeRTOS.org
* https : //github.com/FreeRTOS
*
*/
/*-----------------------------------------------------------
* Portable layer API . Each function must be defined for each port .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# ifndef PORTABLE_H
# define PORTABLE_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
* pre - processor definition was used to ensure the pre - processor found the correct
* portmacro . h file for the port being used . That scheme was deprecated in favour
* of setting the compiler ' s include path such that it found the correct
* portmacro . h file - removing the need for the constant and allowing the
* portmacro . h file to be located anywhere in relation to the port being used .
* Purely for reasons of backward compatibility the old method is still valid , but
* to make it clear that new projects should not use it , support for the port
* specific constants has been moved into the deprecated_definitions . h header
* file . */
# include "deprecated_definitions.h"
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
* did not result in a portmacro . h header file being included - and it should be
* included here . In this case the path to the correct portmacro . h header file
* must be set in the compiler ' s include path . */
# ifndef portENTER_CRITICAL
# include "portmacro.h"
# endif
# if portBYTE_ALIGNMENT == 32
# define portBYTE_ALIGNMENT_MASK ( 0x001f )
# elif portBYTE_ALIGNMENT == 16
# define portBYTE_ALIGNMENT_MASK ( 0x000f )
# elif portBYTE_ALIGNMENT == 8
# define portBYTE_ALIGNMENT_MASK ( 0x0007 )
# elif portBYTE_ALIGNMENT == 4
# define portBYTE_ALIGNMENT_MASK ( 0x0003 )
# elif portBYTE_ALIGNMENT == 2
# define portBYTE_ALIGNMENT_MASK ( 0x0001 )
# elif portBYTE_ALIGNMENT == 1
# define portBYTE_ALIGNMENT_MASK ( 0x0000 )
# else /* if portBYTE_ALIGNMENT == 32 */
# error "Invalid portBYTE_ALIGNMENT definition"
# endif /* if portBYTE_ALIGNMENT == 32 */
# ifndef portUSING_MPU_WRAPPERS
# define portUSING_MPU_WRAPPERS 0
# endif
# ifndef portNUM_CONFIGURABLE_REGIONS
# define portNUM_CONFIGURABLE_REGIONS 1
# endif
# ifndef portHAS_STACK_OVERFLOW_CHECKING
# define portHAS_STACK_OVERFLOW_CHECKING 0
# endif
# ifndef portARCH_NAME
# define portARCH_NAME NULL
# endif
# ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP
/* Defaults to 0 for backward compatibility. */
# define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
# endif
/* *INDENT-OFF* */
# ifdef __cplusplus
extern " C " {
# endif
/* *INDENT-ON* */
# include "mpu_wrappers.h"
/*
* Setup the stack of a new task so it is ready to be placed under the
* scheduler control . The registers have to be placed on the stack in
* the order that the port expects to find them .
*
*/
# if ( portUSING_MPU_WRAPPERS == 1 )
# if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t * pxPortInitialiseStack ( StackType_t * pxTopOfStack ,
StackType_t * pxEndOfStack ,
TaskFunction_t pxCode ,
void * pvParameters ,
Memory Protection Unit (MPU) Enhancements (#705)
Memory Protection Unit (MPU) Enhancements
This commit introduces a new MPU wrapper that places additional
restrictions on unprivileged tasks. The following is the list of changes
introduced with the new MPU wrapper:
1. Opaque and indirectly verifiable integers for kernel object handles:
All the kernel object handles (for example, queue handles) are now
opaque integers. Previously object handles were raw pointers.
2. Saving the task context in Task Control Block (TCB): When a task is
swapped out by the scheduler, the task's context is now saved in its
TCB. Previously the task's context was saved on its stack.
3. Execute system calls on a separate privileged only stack: FreeRTOS
system calls, which execute with elevated privilege, now use a
separate privileged only stack. Previously system calls used the
calling task's stack. The application writer can control the size of
the system call stack using new configSYSTEM_CALL_STACK_SIZE config
macro.
4. Memory bounds checks: FreeRTOS system calls which accept a pointer
and de-reference it, now verify that the calling task has required
permissions to access the memory location referenced by the pointer.
5. System call restrictions: The following system calls are no longer
available to unprivileged tasks:
- vQueueDelete
- xQueueCreateMutex
- xQueueCreateMutexStatic
- xQueueCreateCountingSemaphore
- xQueueCreateCountingSemaphoreStatic
- xQueueGenericCreate
- xQueueGenericCreateStatic
- xQueueCreateSet
- xQueueRemoveFromSet
- xQueueGenericReset
- xTaskCreate
- xTaskCreateStatic
- vTaskDelete
- vTaskPrioritySet
- vTaskSuspendAll
- xTaskResumeAll
- xTaskGetHandle
- xTaskCallApplicationTaskHook
- vTaskList
- vTaskGetRunTimeStats
- xTaskCatchUpTicks
- xEventGroupCreate
- xEventGroupCreateStatic
- vEventGroupDelete
- xStreamBufferGenericCreate
- xStreamBufferGenericCreateStatic
- vStreamBufferDelete
- xStreamBufferReset
Also, an unprivileged task can no longer use vTaskSuspend to suspend
any task other than itself.
We thank the following people for their inputs in these enhancements:
- David Reiss of Meta Platforms, Inc.
- Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling
of School of Computer Science and Engineering, Southeast University,
China.
- Xinwen Fu of Department of Computer Science, University of
Massachusetts Lowell, USA.
- Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado
Boulder, USA.
2 years ago
BaseType_t xRunPrivileged ,
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION ;
# else
StackType_t * pxPortInitialiseStack ( StackType_t * pxTopOfStack ,
TaskFunction_t pxCode ,
void * pvParameters ,
Memory Protection Unit (MPU) Enhancements (#705)
Memory Protection Unit (MPU) Enhancements
This commit introduces a new MPU wrapper that places additional
restrictions on unprivileged tasks. The following is the list of changes
introduced with the new MPU wrapper:
1. Opaque and indirectly verifiable integers for kernel object handles:
All the kernel object handles (for example, queue handles) are now
opaque integers. Previously object handles were raw pointers.
2. Saving the task context in Task Control Block (TCB): When a task is
swapped out by the scheduler, the task's context is now saved in its
TCB. Previously the task's context was saved on its stack.
3. Execute system calls on a separate privileged only stack: FreeRTOS
system calls, which execute with elevated privilege, now use a
separate privileged only stack. Previously system calls used the
calling task's stack. The application writer can control the size of
the system call stack using new configSYSTEM_CALL_STACK_SIZE config
macro.
4. Memory bounds checks: FreeRTOS system calls which accept a pointer
and de-reference it, now verify that the calling task has required
permissions to access the memory location referenced by the pointer.
5. System call restrictions: The following system calls are no longer
available to unprivileged tasks:
- vQueueDelete
- xQueueCreateMutex
- xQueueCreateMutexStatic
- xQueueCreateCountingSemaphore
- xQueueCreateCountingSemaphoreStatic
- xQueueGenericCreate
- xQueueGenericCreateStatic
- xQueueCreateSet
- xQueueRemoveFromSet
- xQueueGenericReset
- xTaskCreate
- xTaskCreateStatic
- vTaskDelete
- vTaskPrioritySet
- vTaskSuspendAll
- xTaskResumeAll
- xTaskGetHandle
- xTaskCallApplicationTaskHook
- vTaskList
- vTaskGetRunTimeStats
- xTaskCatchUpTicks
- xEventGroupCreate
- xEventGroupCreateStatic
- vEventGroupDelete
- xStreamBufferGenericCreate
- xStreamBufferGenericCreateStatic
- vStreamBufferDelete
- xStreamBufferReset
Also, an unprivileged task can no longer use vTaskSuspend to suspend
any task other than itself.
We thank the following people for their inputs in these enhancements:
- David Reiss of Meta Platforms, Inc.
- Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling
of School of Computer Science and Engineering, Southeast University,
China.
- Xinwen Fu of Department of Computer Science, University of
Massachusetts Lowell, USA.
- Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado
Boulder, USA.
2 years ago
BaseType_t xRunPrivileged ,
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION ;
# endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */
# else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
# if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
StackType_t * pxPortInitialiseStack ( StackType_t * pxTopOfStack ,
StackType_t * pxEndOfStack ,
TaskFunction_t pxCode ,
void * pvParameters ) PRIVILEGED_FUNCTION ;
# else
StackType_t * pxPortInitialiseStack ( StackType_t * pxTopOfStack ,
TaskFunction_t pxCode ,
void * pvParameters ) PRIVILEGED_FUNCTION ;
# endif
# endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
/* Used by heap_5.c to define the start address and size of each memory region
* that together comprise the total FreeRTOS heap space . */
typedef struct HeapRegion
{
uint8_t * pucStartAddress ;
size_t xSizeInBytes ;
} HeapRegion_t ;
/* Used to pass information about the heap out of vPortGetHeapStats(). */
typedef struct xHeapStats
{
size_t xAvailableHeapSpaceInBytes ; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
size_t xSizeOfLargestFreeBlockInBytes ; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xSizeOfSmallestFreeBlockInBytes ; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xNumberOfFreeBlocks ; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
size_t xMinimumEverFreeBytesRemaining ; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
size_t xNumberOfSuccessfulAllocations ; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
size_t xNumberOfSuccessfulFrees ; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
} HeapStats_t ;
/*
* Used to define multiple heap regions for use by heap_5 . c . This function
* must be called before any calls to pvPortMalloc ( ) - not creating a task ,
* queue , semaphore , mutex , software timer , event group , etc . will result in
* pvPortMalloc being called .
*
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
* defines a region of memory that can be used as the heap . The array is
* terminated by a HeapRegions_t structure that has a size of 0. The region
* with the lowest start address must appear first in the array .
*/
void vPortDefineHeapRegions ( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION ;
/*
* Returns a HeapStats_t structure filled with information about the current
* heap state .
*/
void vPortGetHeapStats ( HeapStats_t * pxHeapStats ) ;
/*
* Map to the memory management routines required for the port .
*/
void * pvPortMalloc ( size_t xSize ) PRIVILEGED_FUNCTION ;
void * pvPortCalloc ( size_t xNum ,
size_t xSize ) PRIVILEGED_FUNCTION ;
void vPortFree ( void * pv ) PRIVILEGED_FUNCTION ;
void vPortInitialiseBlocks ( void ) PRIVILEGED_FUNCTION ;
size_t xPortGetFreeHeapSize ( void ) PRIVILEGED_FUNCTION ;
size_t xPortGetMinimumEverFreeHeapSize ( void ) PRIVILEGED_FUNCTION ;
# if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
void * pvPortMallocStack ( size_t xSize ) PRIVILEGED_FUNCTION ;
void vPortFreeStack ( void * pv ) PRIVILEGED_FUNCTION ;
# else
# define pvPortMallocStack pvPortMalloc
# define vPortFreeStack vPortFree
# endif
# if ( configUSE_MALLOC_FAILED_HOOK == 1 )
/**
* task . h
* @ code { c }
* void vApplicationMallocFailedHook ( void )
* @ endcode
*
* This hook function is called when allocation failed .
*/
void vApplicationMallocFailedHook ( void ) ; /*lint !e526 Symbol not defined as it is an application callback. */
# endif
/*
* Setup the hardware ready for the scheduler to take control . This generally
* sets up a tick interrupt and sets timers for the correct tick frequency .
*/
BaseType_t xPortStartScheduler ( void ) PRIVILEGED_FUNCTION ;
/*
* Undo any hardware / ISR setup that was performed by xPortStartScheduler ( ) so
* the hardware is left in its original condition after the scheduler stops
* executing .
*/
void vPortEndScheduler ( void ) PRIVILEGED_FUNCTION ;
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer .
*
* Fills the xMPUSettings structure with the memory region information
* contained in xRegions .
*/
# if ( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION ;
void vPortStoreTaskMPUSettings ( xMPU_SETTINGS * xMPUSettings ,
const struct xMEMORY_REGION * const xRegions ,
StackType_t * pxBottomOfStack ,
uint32_t ulStackDepth ) PRIVILEGED_FUNCTION ;
# endif
Memory Protection Unit (MPU) Enhancements (#705)
Memory Protection Unit (MPU) Enhancements
This commit introduces a new MPU wrapper that places additional
restrictions on unprivileged tasks. The following is the list of changes
introduced with the new MPU wrapper:
1. Opaque and indirectly verifiable integers for kernel object handles:
All the kernel object handles (for example, queue handles) are now
opaque integers. Previously object handles were raw pointers.
2. Saving the task context in Task Control Block (TCB): When a task is
swapped out by the scheduler, the task's context is now saved in its
TCB. Previously the task's context was saved on its stack.
3. Execute system calls on a separate privileged only stack: FreeRTOS
system calls, which execute with elevated privilege, now use a
separate privileged only stack. Previously system calls used the
calling task's stack. The application writer can control the size of
the system call stack using new configSYSTEM_CALL_STACK_SIZE config
macro.
4. Memory bounds checks: FreeRTOS system calls which accept a pointer
and de-reference it, now verify that the calling task has required
permissions to access the memory location referenced by the pointer.
5. System call restrictions: The following system calls are no longer
available to unprivileged tasks:
- vQueueDelete
- xQueueCreateMutex
- xQueueCreateMutexStatic
- xQueueCreateCountingSemaphore
- xQueueCreateCountingSemaphoreStatic
- xQueueGenericCreate
- xQueueGenericCreateStatic
- xQueueCreateSet
- xQueueRemoveFromSet
- xQueueGenericReset
- xTaskCreate
- xTaskCreateStatic
- vTaskDelete
- vTaskPrioritySet
- vTaskSuspendAll
- xTaskResumeAll
- xTaskGetHandle
- xTaskCallApplicationTaskHook
- vTaskList
- vTaskGetRunTimeStats
- xTaskCatchUpTicks
- xEventGroupCreate
- xEventGroupCreateStatic
- vEventGroupDelete
- xStreamBufferGenericCreate
- xStreamBufferGenericCreateStatic
- vStreamBufferDelete
- xStreamBufferReset
Also, an unprivileged task can no longer use vTaskSuspend to suspend
any task other than itself.
We thank the following people for their inputs in these enhancements:
- David Reiss of Meta Platforms, Inc.
- Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling
of School of Computer Science and Engineering, Southeast University,
China.
- Xinwen Fu of Department of Computer Science, University of
Massachusetts Lowell, USA.
- Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado
Boulder, USA.
2 years ago
/**
* @ brief Checks if the calling task is authorized to access the given buffer .
*
* @ param pvBuffer The buffer which the calling task wants to access .
* @ param ulBufferLength The length of the pvBuffer .
* @ param ulAccessRequested The permissions that the calling task wants .
*
* @ return pdTRUE if the calling task is authorized to access the buffer ,
* pdFALSE otherwise .
*/
# if ( portUSING_MPU_WRAPPERS == 1 )
BaseType_t xPortIsAuthorizedToAccessBuffer ( const void * pvBuffer ,
uint32_t ulBufferLength ,
uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION ;
# endif
Add Access Control List to MPU ports (#765)
This PR adds Access Control to kernel objects on a per task basis to MPU
ports. The following needs to be defined in the `FreeRTOSConfig.h` to
enable this feature:
```c
#define configUSE_MPU_WRAPPERS_V1 0
#define configENABLE_ACCESS_CONTROL_LIST 1
```
This PR adds the following new APIs:
```c
void vGrantAccessToTask( TaskHandle_t xTask,
TaskHandle_t xTaskToGrantAccess );
void vRevokeAccessToTask( TaskHandle_t xTask,
TaskHandle_t xTaskToRevokeAccess );
void vGrantAccessToSemaphore( TaskHandle_t xTask,
SemaphoreHandle_t xSemaphoreToGrantAccess );
void vRevokeAccessToSemaphore( TaskHandle_t xTask,
SemaphoreHandle_t xSemaphoreToRevokeAccess );
void vGrantAccessToQueue( TaskHandle_t xTask,
QueueHandle_t xQueueToGrantAccess );
void vRevokeAccessToQueue( TaskHandle_t xTask,
QueueHandle_t xQueueToRevokeAccess );
void vGrantAccessToQueueSet( TaskHandle_t xTask,
QueueSetHandle_t xQueueSetToGrantAccess );
void vRevokeAccessToQueueSet( TaskHandle_t xTask,
QueueSetHandle_t xQueueSetToRevokeAccess );
void vGrantAccessToEventGroup( TaskHandle_t xTask,
EventGroupHandle_t xEventGroupToGrantAccess );
void vRevokeAccessToEventGroup( TaskHandle_t xTask,
EventGroupHandle_t xEventGroupToRevokeAccess );
void vGrantAccessToStreamBuffer( TaskHandle_t xTask,
StreamBufferHandle_t xStreamBufferToGrantAccess );
void vRevokeAccessToStreamBuffer( TaskHandle_t xTask,
StreamBufferHandle_t xStreamBufferToRevokeAccess );
void vGrantAccessToMessageBuffer( TaskHandle_t xTask,
MessageBufferHandle_t xMessageBufferToGrantAccess );
void vRevokeAccessToMessageBuffer( TaskHandle_t xTask,
MessageBufferHandle_t xMessageBufferToRevokeAccess );
void vGrantAccessToTimer( TaskHandle_t xTask,
TimerHandle_t xTimerToGrantAccess );
void vRevokeAccessToTimer( TaskHandle_t xTask,
TimerHandle_t xTimerToRevokeAccess );
```
An unprivileged task by default has access to itself only and no other
kernel object. The application writer needs to explicitly grant an
unprivileged task access to all the kernel objects it needs. The best
place to do that is before starting the scheduler when all the kernel
objects are created.
For example, let's say an unprivileged tasks needs access to a queue and
an event group, the application writer needs to do the following:
```c
vGrantAccessToQueue( xUnprivilegedTaskHandle, xQueue );
vGrantAccessToEventGroup( xUnprivilegedTaskHandle, xEventGroup );
```
The application writer MUST revoke all the accesses before deleting a
task. Failing to do so will result in undefined behavior. In the above
example, the application writer needs to make the following 2 calls
before deleting the task:
```c
vRevokeAccessToQueue( xUnprivilegedTaskHandle, xQueue );
vRevokeAccessToEventGroup( xUnprivilegedTaskHandle, xEventGroup );
```
1 year ago
/**
* @ brief Checks if the calling task is authorized to access the given kernel object .
*
* @ param lInternalIndexOfKernelObject The index of the kernel object in the kernel
* object handle pool .
*
* @ return pdTRUE if the calling task is authorized to access the kernel object ,
* pdFALSE otherwise .
*/
# if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
BaseType_t xPortIsAuthorizedToAccessKernelObject ( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION ;
# endif
/* *INDENT-OFF* */
# ifdef __cplusplus
}
# endif
/* *INDENT-ON* */
# endif /* PORTABLE_H */