From 80d09879d1ba8256146e5909c67b542868035139 Mon Sep 17 00:00:00 2001 From: Soren Ptak Date: Thu, 28 Dec 2023 17:51:42 -0500 Subject: [PATCH] Add in Access Control List support to the port --- portable/GCC/ARM_CRx_MPU/port.c | 230 ++++++++++++++------------- portable/GCC/ARM_CRx_MPU/portmacro.h | 24 ++- 2 files changed, 143 insertions(+), 111 deletions(-) diff --git a/portable/GCC/ARM_CRx_MPU/port.c b/portable/GCC/ARM_CRx_MPU/port.c index 7427aa7c5..1fa59fdbe 100644 --- a/portable/GCC/ARM_CRx_MPU/port.c +++ b/portable/GCC/ARM_CRx_MPU/port.c @@ -39,6 +39,7 @@ /* Scheduler includes. */ #include "FreeRTOSConfig.h" #include "FreeRTOS.h" +#include "portmacro_asm.h" #include "portmacro.h" #include "task.h" #include "mpu_syscall_numbers.h" @@ -589,73 +590,16 @@ BaseType_t xPortIsAuthorizedToAccessBuffer( return xAccessGranted; } -#if( configENABLE_ACCESS_CONTROL_LIST == 1 ) - -BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) -/* PRIVILEGED_FUNCTION */ -{ - uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; - BaseType_t xAccessGranted = pdFALSE; - const xMPU_SETTINGS * xTaskMpuSettings; - - if( xSchedulerRunning == pdFALSE ) - { - /* Grant access to all the kernel objects before the scheduler - * is started. It is necessary because there is no task running - * yet and therefore, we cannot use the permissions of any - * task. */ - xAccessGranted = pdTRUE; - } - else - { - xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ - - ulAccessControlListEntryIndex = - ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS ); - ulAccessControlListEntryBit = - ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS ); - - if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == - portTASK_IS_PRIVILEGED_FLAG ) - { - xAccessGranted = pdTRUE; - } - else - { - if( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] & - ( 1U << ulAccessControlListEntryBit ) ) != 0 ) - { - xAccessGranted = pdTRUE; - } - } - } - - return xAccessGranted; -} - -#else - -BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject -) /* PRIVILEGED_FUNCTION */ -{ - ( void ) lInternalIndexOfKernelObject; - - /* If Access Control List feature is not used, all the tasks have - * access to all the kernel objects. */ - return pdTRUE; -} - -#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */ - /*---------------------------------------------------------------------------*/ /** @brief Determine if the FreeRTOS Task was created as a privileged task - * - * @return BaseType_t pdTRUE if the task's ulTaskFlags mark it as privileged. - * pdFALSE if the task was not created as a privileged task. * * @ingroup MPU Control * @ingroup Task Context + * + * @return pdTRUE if the Task was created as a privileged task. + * pdFALSE if the task was not created as a privileged task. + * */ BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */ { @@ -672,6 +616,122 @@ BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */ return xTaskIsPrivileged; } + +/** @brief Start the FreeRTOS-Kernel's control of Tasks by starting the System Tick + * Interrupt. + * + * @ingroup Scheduler + * @return BaseType_t This function is not meant to be returned from. + * If it does return it returns pdFALSE to mark that the scheduler could not be started. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* Start the timer that generates the tick ISR. */ + configSETUP_TICK_INTERRUPT(); + + /* Reset the critical section nesting count read to execute the first task. */ + ulCriticalNesting = 0UL; + + /* Configure the regions in the MPU that are common to all tasks. */ + prvSetupDefaultMPU(); + + xSchedulerRunning = pdTRUE; + + /* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */ + vPortStartFirstTask(); + + /* Will only get here if vTaskStartScheduler() was called with the CPU in + * a non-privileged mode or the binary point register was not set to its lowest + * possible value. prvTaskExitError() is referenced to prevent a compiler + * warning about it being defined but not referenced in the case that the user + * defines their own exit address. */ + ( void ) prvTaskExitError(); + return 0; +} +/*---------------------------------------------------------------------------*/ + +#if( configENABLE_ACCESS_CONTROL_LIST == 1 ) + + BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */ + { + uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; + BaseType_t xAccessGranted = pdFALSE; + const xMPU_SETTINGS * xTaskMpuSettings; + + if( xSchedulerRunning == pdFALSE ) + { + /* Grant access to all the kernel objects before the scheduler + * is started. It is necessary because there is no task running + * yet and therefore, we cannot use the permissions of any + * task. */ + xAccessGranted = pdTRUE; + } + else + { + xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ + + ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS ); + ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS ); + + if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) + { + xAccessGranted = pdTRUE; + } + else + { + if( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] & ( 1U << ulAccessControlListEntryBit ) ) != 0 ) + { + xAccessGranted = pdTRUE; + } + } + } + + return xAccessGranted; + } + + + void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */ + { + uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; + xMPU_SETTINGS * xTaskMpuSettings; + + ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS ); + ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS ); + + xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle ); + + xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit ); + } + + void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle, + int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */ + { + uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit; + xMPU_SETTINGS * xTaskMpuSettings; + + ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS ); + ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS ); + + xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle ); + + xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( 1U << ulAccessControlListEntryBit ); + } + +#else + +BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject +) /* PRIVILEGED_FUNCTION */ +{ + ( void ) lInternalIndexOfKernelObject; + + /* If Access Control List feature is not used, all the tasks have + * access to all the kernel objects. */ + return pdTRUE; +} + +#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */ + /*---------------------------------------------------------------------------*/ /** @brief Function that is used as the default Link Register address for a new Task @@ -698,54 +758,6 @@ void prvTaskExitError( void ) /*---------------------------------------------------------------------------*/ -/** @brief Start the FreeRTOS-Kernel's control of Tasks by starting the System Tick - * Interrupt. - * - * @ingroup Scheduler - * @return BaseType_t This function is not meant to be returned from. - * If it does return it returns pdFALSE to mark that the scheduler could not be started. - */ -BaseType_t xPortStartScheduler( void ) -{ -#if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - /* Sections used for Privileged Stacks to zero them out before starting tasks */ - extern uint32_t * __privileged_stacks_start__; - extern uint32_t * __privileged_stacks_end__; -#else /* if defined( __ARMCC_VERSION ) */ - /* Declaration when these variable are exported from linker scripts. */ - /* Sections used for Privileged Stacks to zero them out before starting tasks */ -/* - extern uint32_t __privileged_stacks_start__[]; - extern uint32_t __privileged_stacks_end__[]; -*/ -#endif /* if defined( __ARMCC_VERSION ) */ - - /* Start the timer that generates the tick ISR. */ - configSETUP_TICK_INTERRUPT(); - - /* Reset the critical section nesting count read to execute the first task. */ - ulCriticalNesting = 0UL; - - /* Configure the regions in the MPU that are common to all tasks. */ - prvSetupDefaultMPU(); - - xSchedulerRunning = pdTRUE; - - /* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */ - vPortStartFirstTask(); - - /* Will only get here if vTaskStartScheduler() was called with the CPU in - * a non-privileged mode or the binary point register was not set to its lowest - * possible value. prvTaskExitError() is referenced to prevent a compiler - * warning about it being defined but not referenced in the case that the user - * defines their own exit address. */ - ( void ) prvTaskExitError(); - return 0; -} -/*---------------------------------------------------------------------------*/ - /** @brief Function meant to end the FreeRTOS Scheduler, not implemented on this port. * @ingroup Scheduler */ diff --git a/portable/GCC/ARM_CRx_MPU/portmacro.h b/portable/GCC/ARM_CRx_MPU/portmacro.h index cf46ac0c6..ab42a1cab 100644 --- a/portable/GCC/ARM_CRx_MPU/portmacro.h +++ b/portable/GCC/ARM_CRx_MPU/portmacro.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V11.0.1 - * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: MIT * @@ -69,6 +69,15 @@ extern "C" { #error This Port is only usable with configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY set to 1 #endif /* ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY != 1 ) */ +#ifndef configENABLE_ACCESS_CONTROL_LIST + #define configENABLE_ACCESS_CONTROL_LIST 0 +#elif( configENABLE_ACCESS_CONTROL_LIST == 1 ) + #ifndef configPROTECTED_KERNEL_OBJECT_POOL_SIZE + #error "Set configPROTECTED_KERNEL_OBJECT_POOL_SIZE to at least the number " \ + "of FreeRTOS-Kernel Objects to be created" + #endif /* configPROTECTED_KERNEL_OBJECT_POOL_SIZE */ +#endif /* configENABLE_ACCESS_CONTROL_LIST */ + /** @brief The size in Bytes that the Privileged System Call Stack should be. * * @ingroup MPU Privilege @@ -537,8 +546,15 @@ UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap ); * padded. */ #define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL ) +/** @brief Size of the System Call Buffer in the TCB + * @ingroup Task Context + */ + #define portSYSTEM_CALL_STACK_SIZE configSYSTEM_CALL_STACK_SIZE +/* Size of an Access Control List (ACL) entry in bits. */ +#define portACL_ENTRY_SIZE_BITS ( 32U ) + /** @brief Structure to hold the MPU Register Values * @struct xMPU_REGION_REGISTERS * @@ -652,6 +668,10 @@ typedef struct MPU_SETTINGS * @ingroup Port Privilege */ xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo; + + #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) + uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE / portACL_ENTRY_SIZE_BITS ) + 1 ]; + #endif } xMPU_SETTINGS; #ifdef __cplusplus