Allocate Secure context

Hi !

I’m using LPC55S69 port for a while and can see that secure context allocation by SecureContext_AllocateContext() use the same heap memory for privileged and nonprivileged tasks.

I think context of privileged tasks ( Idle ) should use own heap memory array and nonprivileged - own one. In this case I can configure MPU_S in clear way when privileged and nonprivileged data is clearly separated.

What do you think about it ?

Regards !
Eugene

Thank you for the suggestion. As you rightly said, currently the same heap memory array is used for both privileged and non-privileged tasks. We will look into how can these two be separated.

Thanks.

Hi !

I try to prototype issue and create separate arrays for prin and non-priv tasks.
Looks like array for privileged heap need to be allocated in non-privileged sram memory.
In other case I have hardfault with verdict “Another secure bus error”.
The same fault I have when try to allocate heap in privileged memory on non-secure side ( I have created separate discussion some time ago as well)

Looks like fault happens somewhere in SVC handler(s) and heap can’t be privileged even according RTOS arch, it should be. But for some reason array in heap_4.c also non set as privileged.

Is any idea what can have effect for this issue ?
Looks like in both cases only privileged code have access to those heaps.

Regards,
Eugene

Hi Eugene,

Just for my understanding - are you saying that you observe a Fault when you put the heap memory in the privileged section? This is on the non-secure side?

Thanks,
Gaurav

Hi Gaurav !
One of cases,yes.
In this case I have only 3 privileged tasks : idle, timer and own one.
Heap_4 code and data are relocated by linker scripts to privileged sections and heap array is defined as external for be able to relocate it to privileged/unprivileged section.
If heap array in nonprivileged data everything works fine, if in privileged - hardfault happens
in vRestoreContextOfFirstTask() handler.

Create IdleTask, stack size - 256
Create TimerTask, stack size - 256
Start first task …
SecureContext_Init()
vRestoreContextOfFirstTask() …

May be first should be Timer task as task with high priority.

Even I add more unprivileged tasks and be sure if no any direct accesses to heap and IPC handlers anywhere - result is the same.
privileged heap cause hardfault, even all tasks are privileged.
Major handlers priorities:
SVCall_IRQn prio - 0
PendSV_IRQn prio - 7
SysTick_IRQn prio - 7


In other case, I have tried to allocate secure context of privileged task in privileged memory
and nonprivileged in nonprivileged. And First call from nonprivileged task to secure world cause Hardfault. If context for privileged tasks allocated in nonprivileged memory - no problem. Calls from privileged tasks to secure world is not cause any problem.

Looks like in both cases some problem with heap array privileges but no clear what can be dependencies and what need to be checked.

Regards,
Eugene

I tried to repro it with our this demo: https://github.com/FreeRTOS/FreeRTOS/tree/master/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso

But I am not able to repro it. Am I missing something as compared to your environment? Is it possible for you to share a small project which I can use to repro the problem?

Thanks.

Hi Gaurav !

I try to minimize my enviroment and disable all task creation + timer task.
Only idle task remain without secure task context creation ( idle hook just call _WFI).
But result is the same - idle task is not start and Hardfault happens somewhere when call vRestoreContextOfFirstTask() is executed.

So it is only depends from from heap array privilege attributes.
But idle task stack is allocated from heap and it show some dependency. In other restricted task stack array is given outside.

Is any idea what can be checked ?

I will compare NXP’s 10.2.1 based code with master branch. Let’ s see what I can find.
I try to disable secure context usage completely but flag configENABLE_TRUSTZONE ==0 is not implemented in correct way and I have create issue about it.

Regards,
Eugene

But idle task stack is allocated from heap and it show some dependency. In other restricted task stack array is given outside.

I realized the difference is that I am using configSUPPORT_STATIC_ALLOCATION as 1 and as a result, Idle and Timer task’s stack and TCB are provided by the application: https://github.com/FreeRTOS/FreeRTOS/blob/master/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/Projects/MCUXpresso/NonSecure/main_ns.c#L114

Once I set configSUPPORT_STATIC_ALLOCATION to 0, I am able to repro the fault. I am debugging this and will get back to you.

Thanks.

Hi Gaurav !

Yes I’m using dynamic allocation of memory.

Please take in mind that similar issue exists on Secure side as well.
I clone secure heap implementation and in secure context allocation
call like this
if(ulIsTaskPrivileged)
{
pucStackMemory = _pvPortMalloc( ulSecureStackSize );
}
else
{
pucStackMemory = pvPortMalloc( ulSecureStackSize );
}
And privileged tasks ( idle, timer and etc. ) should get memory from own privileged heap array. And it Hardfault with the same reason.
But if memory for privileged tasks allocated from nonprivileged array also - everything works fine.

On secure side I have static MPU_S configuration where all code and data have separate privileged and nonprivileged sections.

Regards,
Eugene

Hi Gaurav !

I forgot to mentioned that I also have changed in portmacro.h

#define portBYTE_ALIGNMENT /8/32

I expect that some allocation will be mapped as separate MPU section.
But I haven’t check if this really applicable for my configuration.
But idle and timer tasks take stack from heap and it might be need.

Regards,
Eugene

One important thing to think about, if you really are concerned about security, is that by having secure tasks use unsecured memory for their stacks, you are compromising security. I would think that you would really want secure tasks to have there stacks in secure memory, which since FreeRTOS as built won’t use different heaps for secure or unsecured tasks, must use the unsecured heap to allocate stacks, means using static allocations.

If FreeRTOS was designed from the ground up for this type of processor, things might be different (and there would be secure and unsecured heaps) but that is one of the limitations from a project designed for wide portability.

Hi Richard !

Task on nonsecure side what running with user privileges have well defined NSC API and actual functionality executed on secure side. Secure side have own stack allocator from non-privileged secure memory.
On Secure side some data copied to/from nonsecure side. This memory window allocated in separate memory range and mapped by MPU only to one nonsecure task.
On secure side memory window accessibility checked by cmse_check_address_range((void*) buf, buf_len, CMSE_NONSECURE | CMSE_MPU_UNPRIV | CMSE_MPU_READWRITE);
Other tasks ( except idle and timer) are non-privileged and even dosn’t have secure context.
I assume only one non-secure/nonprivileged task can call those NSC APIs.
Idle task is privileged and control power management on secure side.
It also can’t call those NSC API, it not pass cmse_checks.
Secure context of this task ( stack )can’t be accessed by any other tasks from non-secure side.
Or what you mean “is that by having secure tasks use unsecured memory for their stacks” ?
Or “secure tasks” have different meaning in this context. Please clarify.
I really worry about absolute address of secure context what stored in TCB on nonsecure side.
I hope it will be replaced to some id in some version of RTOS.

Regards,
Eugene

I understand the cause of fault. We use the following MPU regions:

  1. Privileged Code - Privileged Read Only.
  2. Unprivileged Code - Read Only Any.
  3. System Calls - Read Only Any.
  4. Privileged Data - Privileged Read Write, Execute Never.
  5. Task’s Stack - Read Write, Execute Never.

When xTaskCreate API is used, task’s stack is allocated using pvPortMalloc. If the heap memory lies in privileged data region (number 4 above), the stack region will overlap privileged data region and will cause fault because overlapping regions are not allowed in v8M MPU.

We are working on fixing this issue - meanwhile will you be able to use static allocation to unblock yourself.

Thanks,
Gaurav

Hi Gaurav !

Thank you !

Juts about theory.

I think it is demanding configuration fro FreeRTOS when all code/data/heap of it is fully isolated from non-privileged tasks. For use IPC , task should have copy if handlers in own memory ( as usually there are passed via parameters.) If task require heap like allocator, it should have own one where all heap memory allocated in task’s private memory. RTOS is not provide APIs for local heap allocators but as usually they coming with other components. For example mbedTLS has own one.

Regards,
Eugene

One BIG thing to remember for this, FreeRTOS starts as a general purpose library to handle many different machines, many without these things like secure context or MPUs, and wants to be efficient (and simple) on those. It bolts on capability to use, to a degree, those addition features, but likely may fall short of fully utilizing them.

Hi Richard !

One big problem is possibility to enforce secure/non-secure privilege check on LPC55 ( see misc register AHB_SECURE_CTRL->MISC_CTRL_REG ).
In this case MPU sections should much with MPC sections and non-privileged code can’t be executed with privilege rights.
Do you have idea if with current RTOS structure, code and data can be rearranged for keep this kind of isolation and separation ?

Regards,
Eugene

Agreed. And we are looking into this.

Thanks.

Hi Gaurav !

Static allocation of Idle/Timer task resolve problem becouse their stack mapped from privileged backgrouns area to separate section of MPU and no any overlaping.

But it dosn’t help with secure side and HardFault is happens in any case if securecontext for Idle is allocated from privileged MPU area ( background or separate section).
But it have effect for execute nonprivileged tasks only. Idle work fine and perform power management on Secure side without problems.

How allocation of secure context for Idle in privileged memory can effect for execution of nonprivileged tasks ? Nonprivileged tasks have context in nonprivileged memory.

Could you point me to start point what to look into code. Routines quite small and transparent but this kind of dependencies are confuse me a bit.

Regards,
Eugene

If I understand correctly, you have programmed Secure side MPU to divide secure RAM into privileged and unprivileged:

        Secure Memory
     +------------------+
     |                  |
     |                  |
     |    Privileged    |
     |                  |
     |                  |
     |                  |
     +------------------+
     |                  |
     |                  |
     |                  |
     |   Unprivileged   |
     |                  |
     |                  |
     |                  |
     +------------------+
  • Privileged - Contains secure context for privileged tasks.
  • Unrivileged - Contains secure context for unprivileged tasks.

And you are getting a fault when unprivileged task calls a NSC function. Is this is correct understanding?

Have you divided secure flash into privileged and unprivileged to ensure that unprivileged task can execute code? Would you share your secure MPU configuration? Can you step through the assembly to determine the exact instruction where you are getting a fault?

Thanks.

Hi Gaurav !

Yes, flash and sram have privileged and nonprivileged areas what are separate MPU sections with attributes like in MPU_NS in RTOS. SG veneere area in non-privileged flash section.
Privileged and nonprivileged tasks can execute relevant NSC calls.
Privileged NSC call always works and non-privileged only if privileged task have context in non-privileged SRAM ( Secure context structure and ucHeap array).

SecureContext/secure heap code allocated in privileged Flash. Static heap control variables in privileged SRAM as well. Context/Heap called in SVC what is privileged mode.

Secure implementation heap cloned and ulIsTaskPrivileged variable is used for select appropriate Heap for allocate Context and stack for it.

Heap array defined in other file :

uint8_t ucHeap[secureconfigTOTAL_HEAP_SIZE] __attribute__((aligned(32))) __attribute__ ((section(".unprivileged_data")));
uint8_t ucHeapPriv[secureconfigTOTAL_PRIV_HEAP_SIZE] __attribute__((aligned(32))) __attribute__ ((section(".unprivileged_data")));  // OK

if

uint8_t ucHeapPriv[secureconfigTOTAL_PRIV_HEAP_SIZE] __attribute__((aligned(32))) __attribute__ ((section(".privileged_data")));  // Hardfaut

Is enough Stack space for sure because with both unprivileged arrays everything work fine.
I have generated symbol file and all variables in sections where there should be.

I just manipulate with ucHeapPriv attributes and test result.

I haven’t debug this on assembler level. I try to understand if it should work by design.
May be I try to do something what is not fit in any “gate”.

Regards,
Eugene