Hi Raghu,
For reclaiming, do we need to disable the mmu ? can we not mark the page as RW and write nop's into it(and flush icache etc etc) like we do with RECLAIM_INIT_CODE?
In that particular case mentioned in my message, reclaim_init_code was called after make_xlat_tables_readonly, therefore the tables are now protected, so if we wanted to mark anything RW (or make any change) the MMU would kick us out when trying to modify the level 3 page descriptor(s). So, in that case, we would have to disable the MMU. I apologize if I created confusion. I was just trying to highlight one of the many chicken-and-egg problems which seem to appear for this change. If we reclaim first, then we do not need to disable the MMU.
I think we might want to reclaim the disable_mmu_el3() as well, since an attacker could jump to a gadget disable mmu and bypass all protections(might require a cache flush).
I agree that disable_mmu_el3() is potentially dangerous. Some investigation/exploration would also be needed to find the best way to split the enable_mmu_elx() helpers. Also, the init code reclaiming feature needs to become more mature IMO (to get a better idea of how it is used by platforms), as currently it is only enabled on FVP and has some limitations (e.g. doesn't work with clang).
Therefore, I say we keep this for the future, see how things evolve, and right now focus on getting the basic RO tables feature ready to be merged.
Thanks Petre ________________________________ From: Raghu Krishnamurthy raghu.ncstate@icloud.com Sent: 18 February 2020 19:51 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
Hi Petre,
Your approach sounds reasonable. I was thinking something along the lines of splitting the code into 2 parts as well, one that writes to ttbr0_elx, and the other that does what the enable_mmu_direct_elx() minus writing to ttbr. I think both approaches may work out the same, code wise.
- If we make the tables read-only first, then if we want to reclaim
we must bypass the MMU.
For reclaiming, do we need to disable the mmu ? can we not mark the page as RW and write nop's into it(and flush icache etc etc) like we do with RECLAIM_INIT_CODE?
I think we might want to reclaim the disable_mmu_el3() as well, since an attacker could jump to a gadget disable mmu and bypass all protections(might require a cache flush). Anyway, not to cause distractions, i think it is reasonable to do this in multiple patches as opposed to doing it in this patch.
Thanks Raghu
On 2/18/20 10:07 AM, Petre-Ionut Tudor wrote:
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