Summary Description Successful exploitation result Fixed in system version Last system version this flaw was checked for Timeframe this was discovered Public disclosure timeframe Discovered by

Non-atomic mutexes When an SMC is called, TrustZone sets a global variable to mark that an SMC is in progress, so that two SMCs using shared resources (like the security engine) do not trample on one another. On 1.0.0, this global variable was written using non-atomic writes, and thus a race condition is possible. However, the SMC handler enforces that all SMCs must be called from core #3, unless the top-level handler ID is 1 (SMCs internal to the kernel). Thus, the only SMCs that can be run side-by-side are [any userland smc] and smcGetRandomBytesForKernel, and this turns out to not really be abusable. Mostly useless. Maybe some oob-write into unused (and thus useless) memory if running smcGetRandomBytesForKernel and smcGetRandomBytesForUser at the same time. 2.0.0 2.0.0 December 2017 (Probably earlier by others) January 18, 2018 SciresM, probably others (independently).

jamais vu (non-secure world access to PMC MMIO and pre-deep sleep firmware) On 1.0.0, one could map in the PMC registers in userland. In addition, am ran a little-kernel based firmware on the BPMP at runtime. With code execution under am, one could modify the BPMP's little-kernel firmware to hook deep sleep entry, and modify TrustZone/Security engine state. This was fixed in 2.0.0 by making the PMC secure-world only, blacklisting the BPMP's exception vectors from being mapped, and thoroughly checking for malicious behavior on deep sleep entry. Arbitrary TrustZone code execution. 2.0.0 2.0.0 December, 2017 January 20, 2018 SciresM and motezazer

Missed BPMP Exception Vector Writes Starting in 2.0.0, the BPMP is asleep at runtime, and is turned on by TrustZone during smcCpuSuspend in order to initiate the deep sleep process. When it does so, it is held in RESET, and TrustZone attempts to write to the BPMP exception vectors at 0x6000F200 to register EVP_RESET = lp0_entry_fw_crt0, and all other EVPs to a function that simply reboots. However, while they successfully write EVP_RESET, they miss all the other vectors, accidentally writing to the 0x6000F004-0x6000F020 region instead of the 0x6000F204-0x6000F220 region they want to write to. This results in all the exception vectors for the BPMP other than RESET being "undefined" (attacker controlled). With some way of causing an exception vector to be taken at the right time, this would give pre-sleep code execution (and thus arbitrary TrustZone code execution, via the security engine flaw). However, none of the abort vectors are really triggerable, and interrupts are disabled for the BPMP when it is taken out of reset. Thus, this is useless in practice. This was fixed in 4.0.0 by writing to the correct registers. Theoretically: Arbitrary TrustZone code execution. In practice: Useless. 4.0.0 4.0.0 January, 2018 February 23, 2018 SciresM and motezazer, naehrwert, hexkyz, probably others (independently).

TSEC has access to the secure kernel carveout TrustZone is responsible for managing security carveouts to prevent DMA controllers from accessing the carveout which contains the kernel, sysmodules, and other critical operating system data. Until 8.0.0, the list of devices that could access the carveout included the TSEC. However, the TSEC can bypass the SMMU when in authenticated mode by writing to a certain register. Thus, pwning nvservices would allow one to take over the TSEC, and use it to write to normally protected mmio/memory. In 8.0.0, this was fixed by removing TSEC access, and adding TSECB access (TSECB cannot bypass the SMMU). With access to the TSEC mmio (nvservices ROP) and code execution in TSEC Heavy Secure mode, kernel code execution, probably. 8.0.0 8.0.0 2017 (when TrustZone code plaintext was first obtained). April 15, 2019 Everyone

deja vu (insufficient system state validation on suspend leads to pre-sleep BPMP code execution) Jamais Vu was fixed in 2.0.0 by making the PMC secure-world only, blacklisting the BPMP's exception vectors from being mapped, and thoroughly checking for malicious behavior on deep sleep entry, since gaining pre-sleep code execution on the BPMP compromises the system. However, the state validation performed by Nintendo's Secure Monitor was insufficient to prevent pre-sleep execution from being obtained. Prior to 6.0.0, one could use a DMA controller that had access to IRAM and was not held in reset (there were multiple) to race TrustZone's writes to the BPMP firmware in IRAM, and thus overwrite Nintendo's firmware with an attacker's to gain pre-sleep code execution. 6.0.0 addressed this by performing TrustZone state MAC writes and locking PMC scratch *before* turning on the BPMP, fixing the original Jamais Vu exploit entirely. In addition, the BPMP firmware in TrustZone's .rodata is now memcmp'd to the actual data after it is written to IRAM. This mitigates race attacks that modify the firmware. However, Nintendo both forgot to validate the BPMP exception vectors after writing them, and forgot to hold in reset a DMA controller that can write to the BPMP's exception vectors. AHB-DMA is not blacklisted by kernel mapping whitelist (Nintendo probably forgot it, because the TX1 TRM does not really document that it's present, although the MMIO works as documented in older (Tegra 3 and before) TRMs). Thus, with kernel code execution (or some other way of accessing AHB-DMA, e.g. nspwn on <= 4.1.0, TSEC hax, or other arbitrary mmio access flaws), one can DMA to the BPMP's exception vectors as they are written, causing TrustZone to start the BPMP executing an attacker's firmware at a different location than TrustZone intends/validates. This was fixed in 8.0.0 by blocking AHB-DMA arbitration and verifying it is held in reset during suspend, and thus there are no more devices that can write to the relevant MMIO at the right time. Arbitrary TrustZone/BootROM code execution, by using either the original Jamais Vu flaw (prior to 6.0.0 or a warmboot bootrom exploit (any firmware where pre-sleep execution can be gained). 8.0.0 8.0.0 December 2017 April 15, 2019 SciresM, motezazer and ktemkin, naehrwert (independently), almost certainly others (independently)