Hi Raghu,
You are right, it is easier (if we measure the difficulty in the number of required gadgets) to just remap the memory by corrupting the TTBR. I'm trying to think of a way to get both mitigations, but I always end up with a problem:
* If we reclaim the enable_mmu code, then this is done with the MMU enabled, so enable_mmu will be needed by make_tables_readonly but it will not be present at that time. So in this situation they end up mutually exclusive. * If we make the tables read-only first, then if we want to reclaim we must bypass the MMU. To do that, we disable it, but then we can't re-enable once we're done reclaiming the enable_mmu code. So, again, mutually exclusive.
The only thing I can think of to break this cycle is to have two versions of enable_mmu:
* The current one. This actually does some initialization of MMU control registers (among those, TTBR) besides enabling the M bit in SCTLR_ELx. * A second version, which does everything else except the initialization part and assumes that the control registers have been initialized.
That way, we can reclaim the first version, and APIs which may need to toggle the MMU can use the second version (and leave TTBR, TCR, MAIR alone, as they would have been initialized using the first version). I haven't investigated this, but I don't think there is any code which tries to change the configuration described by mmu_cfg_params? So, in theory, we might be able to get away with something like this?
So, a BL image setup sequence could include something like this: ...->init_xlat_tables->init_and_enable_mmu_elx->...->reclaim_init_code->xlat_apis(using second version of enable_mmu)
What do you think?
Thanks -Petre ________________________________ From: Raghu Krishnamurthy raghu.ncstate@icloud.com Sent: 18 February 2020 15:02 To: Petre-Ionut Tudor Petre-Ionut.Tudor@arm.com Cc: nd nd@arm.com; Raghu Krishnamurthy via TF-A tf-a@lists.trustedfirmware.org Subject: Re: [TF-A] Protecting Secure World Translation Tables
This means that we have to reclaim before using this API (otherwise we would have to choose between reclaiming and this feature since RO tables won't allow changing the memory map). I was afraid the change might impose too much rigidity on the initialization of platform BL images, so I went with this approach instead of making the tables read-only at creation by the init_xlat_tables* functions.
Thanks Petre! Agree with the approach. I was trying to see if we could take this mitigation one step further. If you have arbitrary write gadgets, apart from the "disable MMU->write to tables->propagate change->enable MMU" sequence you mentioned, an attacker could create new page tables with the write gadgets, and use another gadget that changes TTBR0_EL3 to point to the attacker created tables(and defeating this mitigation). That *seems* like a simpler attack than the above sequence since writes to TTBR0_EL3 will usually be followed by the required barriers, forming a nice gadget to change page tables. It would be nice to have the option to mitigate such an attack too, which I'm sure, will require choices from the platform like you mentioned in your response.
Thanks -Raghu
On 2/18/20 6:32 AM, Petre-Ionut Tudor wrote:
Hi Raghu,
Thank you for your comments. My own comments are inline.
*From:* TF-A tf-a-bounces@lists.trustedfirmware.org on behalf of Raghu Krishnamurthy via TF-A tf-a@lists.trustedfirmware.org *Sent:* 18 February 2020 00:16 *To:* tf-a@lists.trustedfirmware.org tf-a@lists.trustedfirmware.org *Subject:* Re: [TF-A] Protecting Secure World Translation Tables I think it is worth implementing this to raise the bar for successful attacks. To Varun's point, in today's systems without S-EL2(<v8.4), it would be less effective as pointed out, since EL3 memory can be completely accessed by SEL1 and SEL1 code tends to have a larger code base on mobile devices(OPTEE, tlk etc). However, on systems with very thin SEL1 shims(typically servers), this would definitely raise the bar for attacks, since you effectively only have SEL0 and EL3. SEL1 cannot be exploited practically.
For new SoCs with SEL2, this mitigation can still be very effective if we can ensure future SEL2 implementations have much smaller code bases and implements this mitigation itself. Effectively, i view SEL2 and EL3 as being equally privileged(it is no different than SEL1 because SEL2 can barf all over EL3 memory and TZ resources if exploited). SEL2 extensions, however, gives EL3 protection from SEL1 and can prevent SEL1 from accessing ALL TZ resources. If you view SEL2 and EL3 as equally privileged and view both together as a single entity, v8.4 systems effectively have EL3, SEL1, SEL0 AND the ability for EL3 to protect itself and other TZ resources from SEL1. In such a system, EL3(and SEL2) having this mitigation will definitely raise the bar for successful attacks.
Also, the cost to implement this mitigation is relatively low for a fairly significant raise in the bar for successful attacks.
PS - I say significantly raise the bar since an attacker will potentially require gadgets to modify TTBRx, invalidate TLB's, and enough gadgets in the code base to have a successful attack. If code in TF-A EL3 is fairly small, and code that writes to TTBR_EL3 can be in some section of the image that can be reclaimed/erased after initial setup, the attacker would have no gadget to modify TTBR_EL3, so there would be virtually no way to change TTBR_EL3. On a default build of FVP, there is a grand total of 1 instruction that writes to TTBR0_EL3 in enable_mmu_direct_el3. This might be a nice follow up change to this mitigation, if others think it is worth it. The same could be extended to other system registers that don't ever need to be changed(VBAR_EL3? SCTLR_EL3?).
Petre: enable_mmu_direct_el3 is also used in the read-only xlat tables API, because the change is made while the MMU is on (so it must be disabled first). I decided to implement it this way in order to allow a platform to make any changes it needs to the translation tables (e.g. for reclaiming initialization code) before calling this API. So, it is kind of "dynamic"...but after it is called nothing can be done to the tables from that EL. This means that we have to reclaim before using this API (otherwise we would have to choose between reclaiming and this feature since RO tables won't allow changing the memory map). I was afraid the change might impose too much rigidity on the initialization of platform BL images, so I went with this approach instead of making the tables read-only at creation by the init_xlat_tables* functions.
Thanks Raghu
On 2/17/20 12:35 PM, Varun Wadekar via TF-A wrote:
Hello Petre,
Thanks for the patch. Before I review the actual code, would like to understand how effective this patch will be and if you have seen a real world attack that this patch mitigates.
AFAIU, the ARM architecture provides the TZ bit as the only protection to create "partitions" on a CPU core. So, potentially S-EL1 can access almost all TZ resources that EL3 can access. Thus, creating a silo inside EL3 exception mode is not an effective mitigation against any other TZ component writing to the physical
memory where the page tables are stored. For the scope of this attack vector, are we assuming that the system cannot be compromised by attacking other TZ software components in the system?
I feel until we have a way to distinguish between CPU realms (EL3 v S-EL2 v S-EL1) at the hardware bus level (ARM v9?), these mitigations are not that effective.
Thoughts?
-Varun
-----Original Message----- From: TF-A tf-a-bounces@lists.trustedfirmware.org On Behalf Of Petre-Ionut Tudor via TF-A Sent: Monday, February 17, 2020 9:40 AM To: tf-a@lists.trustedfirmware.org Subject: [TF-A] Protecting Secure World Translation Tables
External email: Use caution opening links or attachments
Hello Everyone,
For quite some time I have been working on a security hardening feature that offers extra protection against tampering with the Secure world translation tables. An example would be using a gadget that can perform writes to arbitrary Secure memory locations to change memory attributes and/or the memory map.
A real world exploit that uses read/write gadgets to tamper with translation tables can be found here: https://vimeo.com/335948808. If you only want the slide deck, it's
available here: https://speakerdeck.com/hhj4ck/el3-tour-get-the-ultimate-privilege-of-androi....
A patch implementing this feature has been recently pushed upstream here: https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/3349. It
extends v2 of the translation tables library with an API that can be called by a BL image any time after the initialization of the xlat tables to make them read-only.
It would be great to hear your opinions about this, particularly whether or not it is a desirable feature to have in TF-A and what extra work needs to be done for it to meet the use cases that you consider most relevant.
Best wishes Petre IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. -- TF-A mailing list TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-- TF-A mailing list TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a