Hi Guys,
I am working on enabling BTI (and PAC) in trusted-services and I have a question about the topic.
If BTI is disabled in OPTEE, but someone tries to load an SP which was compiled with BTI (contains the related gnu note property) it will be successful. This seems to be a security rish and I am thinking of either panicking or at least sending an error message to remind the user that the requested protection will not be enabled.
As I know there are common parts between TA-s and SP-s loaded by ldelf so I am not sure whether panicking in this scenario will result in any problems or not. What do you think of this proposal? Do you know of any reasons why BTI protected SP-s should be loadable by BTI disabled OPTEE?
Thanks in advance!
Gábor
Hi Gabor,
On Mon, Jun 17, 2024 at 12:25 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
I am working on enabling BTI (and PAC) in trusted-services and I have a question about the topic.
If BTI is disabled in OPTEE, but someone tries to load an SP which was compiled with BTI (contains the related gnu note property) it will be successful. This seems to be a security rish and I am thinking of either panicking or at least sending an error message to remind the user that the requested protection will not be enabled.
As I know there are common parts between TA-s and SP-s loaded by ldelf so I am not sure whether panicking in this scenario will result in any problems or not. What do you think of this proposal?
Couldn't this be dealt with entirely within the SP? I assume there's a way for an SP to test if BTI is enabled
Do you know of any reasons why BTI protected SP-s should be loadable by BTI disabled OPTEE?
BTI and PAC are another layer of protection, security can be maintained without it. I assume that BTI and PAC are more important in some deployments than in others so from OP-TEE point of view we can't generally say which cause of action makes the most sense. If for some reason an SP absolutely must use these security features, then I think the SP should test for that itself and panic or such if needed.
That said, the way that SPs are embedded inside the OP-TEE binary speaks for OP-TEE and SPs to always be in sync, including BTI and PAC.
Cheers, Jens
Hello Jens,
In this case the information whether pac/bti features are enabled will be passed to the SP via manifest, the same way as crc32 or passed and the SP can act depending on this information. Thank you for your answer!
Br, Gábor
-----Original Message----- From: Jens Wiklander jens.wiklander@linaro.org Sent: Monday, June 17, 2024 3:57 PM To: Gabor Toth Gabor.Toth2@arm.com Cc: op-tee@lists.trustedfirmware.org Subject: Re: BTI in OPTEE
Hi Gabor,
On Mon, Jun 17, 2024 at 12:25 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
I am working on enabling BTI (and PAC) in trusted-services and I have a question about the topic.
If BTI is disabled in OPTEE, but someone tries to load an SP which was compiled with BTI (contains the related gnu note property) it will be successful. This seems to be a security rish and I am thinking of either panicking or at least sending an error message to remind the user that the requested protection will not be enabled.
As I know there are common parts between TA-s and SP-s loaded by ldelf so I am not sure whether panicking in this scenario will result in any problems or not. What do you think of this proposal?
Couldn't this be dealt with entirely within the SP? I assume there's a way for an SP to test if BTI is enabled
Do you know of any reasons why BTI protected SP-s should be loadable by BTI disabled OPTEE?
BTI and PAC are another layer of protection, security can be maintained without it. I assume that BTI and PAC are more important in some deployments than in others so from OP-TEE point of view we can't generally say which cause of action makes the most sense. If for some reason an SP absolutely must use these security features, then I think the SP should test for that itself and panic or such if needed.
That said, the way that SPs are embedded inside the OP-TEE binary speaks for OP-TEE and SPs to always be in sync, including BTI and PAC.
Cheers, Jens
Hi Guys,
Currently pointer authentication is disabled at the beginning of the SP-s and is enabled after boot_init_primary_late here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/entry_a6...
We would like to have it already enabled when the SP starts running to protect all the code and to also avoid problems like having the feature enabled between a paciasp-autiasp pair. I tried moving the feature enablement right before the initialization of the SP-s, here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/boot.c#L...
When __thread_enter_user_mode is called thread_core_local[0] keys are used by the feature, but before switching to user mode the related registers are set to threads[0].keys and not returned to the original values resulting in exception.
I see three possible ways to solve this:
* Enable PAC before SP initialization is started and restore the original keys in functions that change them if the feature is enabled. * Enable PAC before SP initialization is started and disable the protection (by attribute) for functions that change keys to avoid such issues. * Keep enablement like this and disable the protection for the related functions in trusted-services. We would like to avoid this solution due to compatibility issues with other SPMC implementations.
My problem is that I do not understand the purpose of thread_core_local[n].keys and threads[n].keys, why are there two different key pairs? Is it a bug that the original keys are not restored or is intentional like this? Do you have an idea what would be the best solution for implementing this change?
Thanks in advance!
Gábor
Hi Gabor,
On Tue, Jun 25, 2024 at 1:16 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
Currently pointer authentication is disabled at the beginning of the SP-s and is enabled after boot_init_primary_late here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/entry_a6...
We would like to have it already enabled when the SP starts running to protect all the code and to also avoid problems like having the feature enabled between a paciasp-autiasp pair. I tried moving the feature enablement right before the initialization of the SP-s, here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/boot.c#L...
When __thread_enter_user_mode is called thread_core_local[0] keys are used by the feature, but before switching to user mode the related registers are set to threads[0].keys and not returned to the original values resulting in exception.
I see three possible ways to solve this:
- Enable PAC before SP initialization is started and restore the original keys in functions that change them if the feature is enabled.
- Enable PAC before SP initialization is started and disable the protection (by attribute) for functions that change keys to avoid such issues.
- Keep enablement like this and disable the protection for the related functions in trusted-services. We would like to avoid this solution due to compatibility issues with other SPMC implementations.
My problem is that I do not understand the purpose of thread_core_local[n].keys and threads[n].keys, why are there two different key pairs?
Each execution context has its own pair of PAC keys to make it harder for one execution context to write something useful into the stack of another execution context.
Is it a bug that the original keys are not restored or is intentional like this?
During boot, until the first exit into the normal world, OP-TEE doesn't have a clear difference between preemptible thread and atomic contexts. Until now we have used a thread-like context when needed by certain functions and then switched back to an atomic context. SPs are initialized during this phase so which context is used is more by chance than by design.
Do you have an idea what would be the best solution for implementing this change?
SPs should be initialized at a later step when SCTLR_ENIA has been enabled. Each SP should use its own pair of PAC keys, they should not try to reuse anything from the thread context or atomic per CPU context.
Cheers, Jens
Hi Jens,
As I see after the SP-s return to SEL1 the context is restored and the pauth keys are set to the keys of the atomic context (kernels[n].keys). So the only problem is that at initialization the keys of the thread-line context (thread_core_local[n].keys) are used instead of the atomic ones.
Since " which context is used is more by chance than by design", do you see anything against initializing the pauth keys to the keys of the atomic context instead of the kernel-like ones here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/entry_a6... ?
With this change and moving the SP initialization right after enabling SCTLR_ENIA the feature seems to be working properly and the protection is already enabled when the sp boot starts.
Br, Gábor
-----Original Message----- From: Jens Wiklander jens.wiklander@linaro.org Sent: Tuesday, June 25, 2024 3:21 PM To: Gabor Toth Gabor.Toth2@arm.com Cc: op-tee@lists.trustedfirmware.org Subject: Re: Enable pointer authentication for the SP initialization
Hi Gabor,
On Tue, Jun 25, 2024 at 1:16 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
Currently pointer authentication is disabled at the beginning of the SP-s and is enabled after boot_init_primary_late here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/en try_a64.S#L385
We would like to have it already enabled when the SP starts running to protect all the code and to also avoid problems like having the feature enabled between a paciasp-autiasp pair. I tried moving the feature enablement right before the initialization of the SP-s, here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/bo ot.c#L1064
When __thread_enter_user_mode is called thread_core_local[0] keys are used by the feature, but before switching to user mode the related registers are set to threads[0].keys and not returned to the original values resulting in exception.
I see three possible ways to solve this:
- Enable PAC before SP initialization is started and restore the original keys in functions that change them if the feature is enabled.
- Enable PAC before SP initialization is started and disable the protection (by attribute) for functions that change keys to avoid such issues.
- Keep enablement like this and disable the protection for the related functions in trusted-services. We would like to avoid this solution due to compatibility issues with other SPMC implementations.
My problem is that I do not understand the purpose of thread_core_local[n].keys and threads[n].keys, why are there two different key pairs?
Each execution context has its own pair of PAC keys to make it harder for one execution context to write something useful into the stack of another execution context.
Is it a bug that the original keys are not restored or is intentional like this?
During boot, until the first exit into the normal world, OP-TEE doesn't have a clear difference between preemptible thread and atomic contexts. Until now we have used a thread-like context when needed by certain functions and then switched back to an atomic context. SPs are initialized during this phase so which context is used is more by chance than by design.
Do you have an idea what would be the best solution for implementing this change?
SPs should be initialized at a later step when SCTLR_ENIA has been enabled. Each SP should use its own pair of PAC keys, they should not try to reuse anything from the thread context or atomic per CPU context.
Cheers, Jens
Hi Gabor,
On Wed, Jun 26, 2024 at 12:29 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Jens,
As I see after the SP-s return to SEL1 the context is restored and the pauth keys are set to the keys of the atomic context (kernels[n].keys). So the only problem is that at initialization the keys of the thread-line context (thread_core_local[n].keys) are used instead of the atomic ones.
Since " which context is used is more by chance than by design", do you see anything against initializing the pauth keys to the keys of the atomic context instead of the kernel-like ones here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/entry_a6... ?
No, at the point where this macro is used we're definitely in an atomic context. I meant before that we're emulating a threaded context to the extent it's needed at some places, for instance, to keep mutex_lock() happy.
With this change and moving the SP initialization right after enabling SCTLR_ENIA the feature seems to be working properly and the protection is already enabled when the sp boot starts.
TAs use their own pauth keys, I think SPs should do the same. Or we're exposing keys that shouldn't be exposed to SPs.
Cheers, Jens
Br, Gábor
-----Original Message----- From: Jens Wiklander jens.wiklander@linaro.org Sent: Tuesday, June 25, 2024 3:21 PM To: Gabor Toth Gabor.Toth2@arm.com Cc: op-tee@lists.trustedfirmware.org Subject: Re: Enable pointer authentication for the SP initialization
Hi Gabor,
On Tue, Jun 25, 2024 at 1:16 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
Currently pointer authentication is disabled at the beginning of the SP-s and is enabled after boot_init_primary_late here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/en try_a64.S#L385
We would like to have it already enabled when the SP starts running to protect all the code and to also avoid problems like having the feature enabled between a paciasp-autiasp pair. I tried moving the feature enablement right before the initialization of the SP-s, here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/bo ot.c#L1064
When __thread_enter_user_mode is called thread_core_local[0] keys are used by the feature, but before switching to user mode the related registers are set to threads[0].keys and not returned to the original values resulting in exception.
I see three possible ways to solve this:
- Enable PAC before SP initialization is started and restore the original keys in functions that change them if the feature is enabled.
- Enable PAC before SP initialization is started and disable the protection (by attribute) for functions that change keys to avoid such issues.
- Keep enablement like this and disable the protection for the related functions in trusted-services. We would like to avoid this solution due to compatibility issues with other SPMC implementations.
My problem is that I do not understand the purpose of thread_core_local[n].keys and threads[n].keys, why are there two different key pairs?
Each execution context has its own pair of PAC keys to make it harder for one execution context to write something useful into the stack of another execution context.
Is it a bug that the original keys are not restored or is intentional like this?
During boot, until the first exit into the normal world, OP-TEE doesn't have a clear difference between preemptible thread and atomic contexts. Until now we have used a thread-like context when needed by certain functions and then switched back to an atomic context. SPs are initialized during this phase so which context is used is more by chance than by design.
Do you have an idea what would be the best solution for implementing this change?
SPs should be initialized at a later step when SCTLR_ENIA has been enabled. Each SP should use its own pair of PAC keys, they should not try to reuse anything from the thread context or atomic per CPU context.
Cheers, Jens
Hi Jens,
" TAs use their own pauth keys, I think SPs should do the same. Or we're exposing keys that shouldn't be exposed to SPs." Yes I am implementing the same behavior as in case of TA-s. The SP-s have own keys which are used when they are running.
Now everything is clear, thank you for the help!
Br, Gábor
-----Original Message----- From: Jens Wiklander jens.wiklander@linaro.org Sent: Wednesday, June 26, 2024 3:03 PM To: Gabor Toth Gabor.Toth2@arm.com Cc: op-tee@lists.trustedfirmware.org Subject: Re: Enable pointer authentication for the SP initialization
Hi Gabor,
On Wed, Jun 26, 2024 at 12:29 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Jens,
As I see after the SP-s return to SEL1 the context is restored and the pauth keys are set to the keys of the atomic context (kernels[n].keys). So the only problem is that at initialization the keys of the thread-line context (thread_core_local[n].keys) are used instead of the atomic ones.
Since " which context is used is more by chance than by design", do you see anything against initializing the pauth keys to the keys of the atomic context instead of the kernel-like ones here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/entry_a6... ?
No, at the point where this macro is used we're definitely in an atomic context. I meant before that we're emulating a threaded context to the extent it's needed at some places, for instance, to keep mutex_lock() happy.
With this change and moving the SP initialization right after enabling SCTLR_ENIA the feature seems to be working properly and the protection is already enabled when the sp boot starts.
TAs use their own pauth keys, I think SPs should do the same. Or we're exposing keys that shouldn't be exposed to SPs.
Cheers, Jens
Br, Gábor
-----Original Message----- From: Jens Wiklander jens.wiklander@linaro.org Sent: Tuesday, June 25, 2024 3:21 PM To: Gabor Toth Gabor.Toth2@arm.com Cc: op-tee@lists.trustedfirmware.org Subject: Re: Enable pointer authentication for the SP initialization
Hi Gabor,
On Tue, Jun 25, 2024 at 1:16 PM Gabor Toth Gabor.Toth2@arm.com wrote:
Hi Guys,
Currently pointer authentication is disabled at the beginning of the SP-s and is enabled after boot_init_primary_late here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/ en try_a64.S#L385
We would like to have it already enabled when the SP starts running to protect all the code and to also avoid problems like having the feature enabled between a paciasp-autiasp pair. I tried moving the feature enablement right before the initialization of the SP-s, here: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/ bo ot.c#L1064
When __thread_enter_user_mode is called thread_core_local[0] keys are used by the feature, but before switching to user mode the related registers are set to threads[0].keys and not returned to the original values resulting in exception.
I see three possible ways to solve this:
- Enable PAC before SP initialization is started and restore the original keys in functions that change them if the feature is enabled.
- Enable PAC before SP initialization is started and disable the protection (by attribute) for functions that change keys to avoid such issues.
- Keep enablement like this and disable the protection for the related functions in trusted-services. We would like to avoid this solution due to compatibility issues with other SPMC implementations.
My problem is that I do not understand the purpose of thread_core_local[n].keys and threads[n].keys, why are there two different key pairs?
Each execution context has its own pair of PAC keys to make it harder for one execution context to write something useful into the stack of another execution context.
Is it a bug that the original keys are not restored or is intentional like this?
During boot, until the first exit into the normal world, OP-TEE doesn't have a clear difference between preemptible thread and atomic contexts. Until now we have used a thread-like context when needed by certain functions and then switched back to an atomic context. SPs are initialized during this phase so which context is used is more by chance than by design.
Do you have an idea what would be the best solution for implementing this change?
SPs should be initialized at a later step when SCTLR_ENIA has been enabled. Each SP should use its own pair of PAC keys, they should not try to reuse anything from the thread context or atomic per CPU context.
Cheers, Jens
op-tee@lists.trustedfirmware.org