Changes

Jump to navigation Jump to search
18,737 bytes added ,  02:33, 18 June 2019
Line 1: Line 1:  +
Exploits are used to execute unofficial code (homebrew) on the Nintendo Switch. This page is a list of publicly known Switch system flaws.
   −
System Flaws are used to execute unofficial code (homebrew) on the Nintendo Switch. This page is a list of known and public Switch System Flaws.
+
For userland applications/applets flaws see [[Switch_Userland_Flaws|here]].  
   −
=List of Switch System Flaws=
+
= System flaws =
 +
== Hardware ==
 +
Flaws in this category pertain to the underlying hardware that powers the Switch.
 +
 
 +
This includes components shared across Tegra based devices such as the [[TSEC]], the [[Security_Engine|Security Engine]], the [[GPU]] and so on.
   −
== Hardware ==
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Summary
 
!  Summary
Line 13: Line 17:  
!  Public disclosure timeframe
 
!  Public disclosure timeframe
 
!  Discovered by
 
!  Discovered by
 +
|-
 +
| CVE-2018-6242 (leveraged by the ShofEL2 and Fusée Gelée exploits)
 +
| The USB software stack provided inside the boot instruction rom (IROM/bootROM) contains a copy operation whose length can be controlled by an attacker. By carefully constructing a USB control request, an attacker can leverage this vulnerability to copy the contents of an attacker-controlled buffer over the active execution stack, gaining control of the Boot and Power Management processor (BPMP) before any lock-outs or privilege reductions occur. This execution can then be used to exfiltrate secrets and to load arbitrary code onto the main CPU Complex (CCPLEX) "application processors" at the highest possible level of privilege (typically as the TrustZone Secure Monitor at PL3/EL3).
 +
| Unknown (Tegra186 and Tegra214)
 +
| HAC-001 (Tegra210)
 +
| January 2018
 +
| April 23, 2018
 +
| [[User:Shuffle2|shuffle2]] and fail0verflow (originally),<br> [[User:Ktemkin|ktemkin]] and ReSwitched Team (independently),<br> [[User:Naehrwert|naehrwert]] (independently),<br> [[User:Hexkyz|hexkyz]] (independently),<br> st4rk with [[User:Shinyquagsire23|Shiny Quagsire]] and Dazzozo (independently),<br> and many others (independently).
 
|-
 
|-
 
| GMMU DMA attack
 
| GMMU DMA attack
Line 19: Line 31:  
[5.0.0+] Works around this hardware flaw by using memory pool partitioning. You can no longer escalate into sysmodules with GPU DMA because all their memory is allocated using heap that's carved out.
 
[5.0.0+] Works around this hardware flaw by using memory pool partitioning. You can no longer escalate into sysmodules with GPU DMA because all their memory is allocated using heap that's carved out.
 
| None
 
| None
| HAC-001
+
| HAC-001 (Tegra210)
 
| Summer 2017
 
| Summer 2017
 
| December 28, 2017
 
| December 28, 2017
Line 28: Line 40:     
With a way to modify the encrypted state buffer, one can thus dump keys from "write-only" keyslots, etc.
 
With a way to modify the encrypted state buffer, one can thus dump keys from "write-only" keyslots, etc.
 +
 +
This also bypasses the SBK protection of the bootROM: indeed, at warmboot, bootROM will always clear keyslot 0xE to prevent malicious code from saving the SBK. Moving the SBK to another keyslot in the saved context renders this protection moot.
 
| None
 
| None
| HAC-001
+
| HAC-001 (Tegra210)
 
| December 2017
 
| December 2017
 
| January 20, 2018
 
| January 20, 2018
Line 44: Line 58:  
However, the Security Engine flushes writes to the internal key tables immediately when AES_KEYTABLE_DATA is written -- this allows one to overwrite a single dword of a key at a time, and thus brute force the contents of keyslots in time (2^32 * 8) = 2^35 instead of 2^256.
 
However, the Security Engine flushes writes to the internal key tables immediately when AES_KEYTABLE_DATA is written -- this allows one to overwrite a single dword of a key at a time, and thus brute force the contents of keyslots in time (2^32 * 8) = 2^35 instead of 2^256.
 
| None
 
| None
| HAC-001
+
| HAC-001 (Tegra210)
 
| Theorized Summer 2017 due to suggestive syntax, confirmed April 9, 2018
 
| Theorized Summer 2017 due to suggestive syntax, confirmed April 9, 2018
 
| April 9, 2018
 
| April 9, 2018
 
| [[User:SciresM|SciresM]], almost surely others (independently).
 
| [[User:SciresM|SciresM]], almost surely others (independently).
 +
|-
 +
| Poor validation of bootrom SDRAM configuration parameters leads to arbitrary writes in bootrom
 +
|
 +
The Tegra X1 bootrom supports saving SDRAM parameters to scratch registers, and using the saved configuration to enable DRAM during warmboot.
 +
 +
The code that parses these parameters does if (params->EmcBctSpareN) *params->EmcBctSpareN = params->EmcBctSpareNPlusOne for most N, without validating either the address or value written to it.
 +
There are other arbitrary writes in this code, as well (e.g. BootromPatch parameters intended for patching MISC registers do not check a relative offset to 0x7000000, etc).
 +
 +
This allows a user with access to the PMC registers (via pre-sleep bpmp execution, or otherwise) to gain arbitrary bootrom code execution.
 +
| None
 +
| HAC-001 (Tegra210)
 +
| 2017
 +
| December 16, 2018
 +
| Everyone (independently).
 
|}
 
|}
   −
== System software ==
+
== Software ==
 +
=== Bootloader ===
 +
Flaws in this category pertain to any bootloader component such as the [[Package1#Package1ldr|package1ldr]], the [[Package1#Section_1|NX bootloader]] or the [[Package1#Section_0|warmboot binary]].
   −
  −
=== Stage 1 Bootloader ===
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 66: Line 94:  
|-
 
|-
 
|  Null-dereference in panic()
 
|  Null-dereference in panic()
|  The Switch's stage 1 bootloader, on panic(), clears the stack and then attempts to clear the Security Engine. However, it does so by dereferencing a pointer to the SE in .bss (initially NULL), and this pointer doesn't get initialized until partway into the bootloader's main() after several functions that might panic() are called. Thus, a panic() caused prior to SE initialization would result in the SE pointer still being NULL when dereferenced. This would cause a data abort, causing the bootloader to clear the stack and then try to clear the security engine...dereferencing NULL again, over and over in a loop.
+
|  The Switch's stage 1 bootloader, on panic(), clears the stack and then attempts to clear the Security Engine. However, it does so by dereferencing a pointer to the SE in .bss (initially NULL), and this pointer doesn't get initialized until partway into the bootloader's main() after several functions that might panic() are called. Thus, a panic() caused prior to SE initialization would result in the SE pointer still being NULL when dereferenced.  
 +
The BPMP doesn't have an active MPU and the bus won't data abort on an invalid address, so no exception will be entered: it'll end up overwriting some exception vectors with NULL before halting.
    
In 3.0.0, this was fixed by moving the security engine initialization earlier in main(), before the first function that could potentially panic().
 
In 3.0.0, this was fixed by moving the security engine initialization earlier in main(), before the first function that could potentially panic().
Infinite clear-the-stack-then-data-abort loop very early in boot, before SBK/other keyslots are cleared. Probably useless for anything more interesting.
+
Some exception vectors overwritten with NULL, before SBK/other keyslots are cleared. Probably useless for anything more interesting.
 
|  [[3.0.0]]
 
|  [[3.0.0]]
 
|  [[3.0.0]]
 
|  [[3.0.0]]
Line 91: Line 120:  
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]]
 
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]]
 
|-
 
|-
 +
|  maconstack (TSEC firmware leaves MAC on the stack)
 +
|  Package1ldr loads a firmware blob into TSEC early on boot. This piece of code runs on the TSEC in Authenticated Mode and has the sole purpose of generating the per-console TSEC key (see [[Cryptosystem]]).
 +
 +
As a way to mitigate attacks, the TSEC firmware blob is split into 3 stages: [[TSEC_Firmware#Boot|Boot]] which is unencrypted and unsigned, [[TSEC_Firmware#KeygenLdr|KeygenLdr]] which is unencrypted but signed and [[TSEC_Firmware#Keygen|Keygen]] which is encrypted and signed.
 +
Boot loads a static pre-generated signature into the Falcon's CPU crypto registers, loads KeygenLdr into the Falcon's CODE region and jumps to it. Execution will proceed into KeygenLdr in Heavy Secure Mode if, and only if, the loaded signature matches the one Falcon calculates internally for KeygenLdr.
 +
 +
Among various things, KeygenLdr will attempt to do a "backwards" security check by calculating a CMAC over Boot and comparing it with a known hash stored in the TSEC firmware's key data (a small buffer stored after Boot's code). If the hashes don't match, execution aborts.
 +
 +
KeygenLdr stores the calculated Boot's CMAC in the stack, but forgets to clear it. Since the stack is located in Falcon's DATA region, loading the TSEC firmware blob and dumping the DATA region afterwards (via MMIO) will reveal the calculated hash.
 +
This allows using KeygenLdr as an oracle to generate a valid CMAC for arbitrary Boot code. Replacing the CMAC in the TSEC firmware's key data region results in KeygenLdr accepting any Boot code, thus rendering this security measure useless.
 +
 +
Additionally, since signed Falcon code can't be revoked without an hardware revision, an attacker can always reuse the flawed KeygenLdr code even if a fix is issued.
 +
|  Running TSEC firmware's KeygenLdr in a user controlled environment.
 +
|  None
 +
|  [[5.0.2]]
 +
|  January 2018
 +
|  April 29, 2018
 +
|  [[User:Hexkyz|hexkyz]], [[User:Rei|Reisyukaku]] (independently), probably others (independently).
 +
|-
 +
|  Stack smash in TSEC firmware's KeygenLdr
 +
|  Given that we can control the [[TSEC_Firmware#Key_data|key data]] (which is not authenticated) and the [[TSEC_Firmware#Boot|Boot]] blob (see "maconstack"), as well as the fact Non-secure and Heavy Secure code share the same stack, we can use this to attack KeygenLdr. KeygenLdr uses memcpy to copy over a payload to DMEM to verify it, which can be abused to smash the stack (in DMEM) and write over the return address of said function.
 +
|  ROP under KeygenLdr in Heavy Secure mode.
 +
|  None
 +
|  [[8.0.1]]
 +
|  Early 2018
 +
|  May 21, 2019
 +
|  Everyone (independently).
 +
|-
 +
|  pk1ldrhax
 +
|  Package1ldr decrypts and verifies the keyblob inside of the current BCT in order to get the package1 key, and then uses the package1 key to decrypt package1. It then validates package1 before jumping to it by checking the PK11 magic number, and that the section sizes sum to the expected size (and are individually less than the expected size).
 +
 +
However, package1ldr does not actually validate the package1 key against a fixed vector (much like kernel9loader forgot to do so on the 3ds). This would normally not matter, as keyblobs are validated -- however, with bootrom code execution one can dump SBK and forge keyblobs, and thus control the package1 key.
 +
 +
Thus ('''in theory, but not in practice due to the size of the brute force required''') one can replace the package1 key with garbage, causing package1 to decrypt into garbage, and hope that this garbage passes validation checks and that package1ldr jumping into the garbage will do something useful.
 +
 +
This was fixed incidentally in [[6.2.0]], as pk1ldr does not use keyblob data to decrypt package1 any more.
 +
 +
|  With a large enough brute force: arbitrary package1 code execution from coldboot.
 +
 +
However, a usable brute force is on the order of >= ~2^80, so '''this is almost certainly not actually usable in any meaningful context'''.
 +
|  [[6.2.0]]
 +
|  [[6.2.0]]
 +
|  Early 2017 (as soon as plaintext package1ldr was first dumped)
 +
|  November 20, 2018
 +
|  Everyone
 
|}
 
|}
    +
=== TrustZone ===
 +
Flaws in this category pertain exclusively to the [[Package1#Section_2|Secure Monitor]].
   −
=== TrustZone ===
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 115: Line 190:  
| December 2017 (Probably earlier by others)
 
| December 2017 (Probably earlier by others)
 
| January 18, 2018
 
| January 18, 2018
| [[User:SciresM|SciresM]], probably others.
+
| [[User:SciresM|SciresM]], probably others (independently).
 
|-
 
|-
 
|  jamais vu (non-secure world access to PMC MMIO and pre-deep sleep firmware)
 
|  jamais vu (non-secure world access to PMC MMIO and pre-deep sleep firmware)
Line 139: Line 214:  
|  January, 2018
 
|  January, 2018
 
|  February 23, 2018
 
|  February 23, 2018
|  [[User:SciresM|SciresM]] and [[User:motezazer|motezazer]], [[User:Naehrwert|naehrwert]], [[User:Hexkyz|hexkyz]], probably others, independently.
+
|  [[User:SciresM|SciresM]] and [[User:motezazer|motezazer]], [[User:Naehrwert|naehrwert]], [[User:Hexkyz|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
 +
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]] and ktemkin,  [[User:Naehrwert|naehrwert]] (independently), almost certainly others (independently)
 
|}
 
|}
    
=== Kernel ===
 
=== Kernel ===
 +
Flaws in this category pertain exclusively to the [[Package2#Section_0|HorizonOS Kernel]].
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 158: Line 271:  
| Many syscalls leaked kernel pointers on sad paths (for example svcSetHeapSize and svcQueryMemory), until they landed a bunch of fixes in 2.0.0.
 
| Many syscalls leaked kernel pointers on sad paths (for example svcSetHeapSize and svcQueryMemory), until they landed a bunch of fixes in 2.0.0.
 
| Nothing really.
 
| Nothing really.
| 2.0.0
+
| [[2.0.0]]
| 2.0.0
+
| [[2.0.0]]
 
|  
 
|  
 
|  
 
|  
 
| ?
 
| ?
 
|-
 
|-
| GetLastThreadInfo UAF
+
| svcWaitSynchronization/svcReplyAndReceive bad cleanup on error
| GetLastThreadInfo syscall gets last-scheduled-KThread pointer from KScheduler object. This pointer is not reference counted, and can be pointing to a freed KThread.
+
| If there is a page fault when fetching handles from the userspace array, it cleans up by dereferencing all objects despite having only loaded first N. Allows the attacker to make arbitrary decrefs on any kernel synchronization object, and thus can be used to get UAF. Haven't actually been tried on real HW though, but should work (tm).
| Nothing. There is a theoretical race that might leak from a KThread from a different process, but it's impossible to trigger practically.
+
| Kernel code execution
| Unfixed
+
| [[2.0.0]]
 +
| [[2.0.0]]
 
|  
 
|  
| 15 October
+
| 24 April
| 17 October
   
| [[User:qlutoo|qlutoo]]
 
| [[User:qlutoo|qlutoo]]
 
|-
 
|-
Line 177: Line 290:  
On 1.0.0 you could supply irq_id < 32 and it would write outside the SharedIrqs table.
 
On 1.0.0 you could supply irq_id < 32 and it would write outside the SharedIrqs table.
 
| You can register irq's in the Core3Irqs table, and thus register per-core irqs for core3, that are normally reserved for kernel. Useless.
 
| You can register irq's in the Core3Irqs table, and thus register per-core irqs for core3, that are normally reserved for kernel. Useless.
| 2.0.0
+
| [[2.0.0]]
| 2.0.0
+
| [[2.0.0]]
 
| ~October
 
| ~October
 
| 17 October
 
| 17 October
Line 202: Line 315:  
| January 2018
 
| January 2018
 
| [[User:SciresM|SciresM]], [[User:Yellows8|yellows8]]
 
| [[User:SciresM|SciresM]], [[User:Yellows8|yellows8]]
 +
|-
 +
| Potential [[SVC|svcWaitForAddress]] thread use-after-free
 +
| Between [[4.0.0]], where svcWaitForAddress was introduced, and [[7.0.0]], there was a second intrusive rbtree node in KThread for the WaitForAddress tree (the key being (address, priority), sorted lexicographically). Unlike the WaitProcessWideKeyAtomic tree, the kernel forgot to reinsert the WaitForAddress node when the thread's priority changed (priority inheritance and/or SetPriority), breaking the rbtree invariants; and since the kernel walks through the entire tree to remove intrusive nodes, you could cause threads to stay in the tree even after their deletion.
 +
 +
[[7.0.0]] fixed the issue by using the same intrusive node for both trees. The thread/node knows which tree it is in, and the latter is correctly updated when thread priority changes.
 +
| It unluckily didn't look exploitable
 +
| [[7.0.0]]
 +
| [[7.0.0]]
 +
| July 2018
 +
| February 2019
 +
| [[User:TuxSH|TuxSH]]
 
|-
 
|-
 
|}
 
|}
    
=== FIRM-package System Modules ===
 
=== FIRM-package System Modules ===
 +
Flaws in this category pertain to any of the [[Package2#Section_1|built-in system modules]].
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 247: Line 373:  
| May/June 2017 (basically immediately after smhax was discovered)
 
| May/June 2017 (basically immediately after smhax was discovered)
 
| December 30, 2017
 
| December 30, 2017
 +
| Everyone
 +
|-
 +
| nspwn
 +
| fsp-ldr command 0 "MountCode" takes in a Content Path (retrieved from NCM by Loader), and returns an IFileSystem for the resulting ExeFS. These content paths, are normally NCAs, but MountCode also supports a number of other formats, including ".nsp" -- which is just a PFS0.
 +
 +
When a path ending in ".nsp" is parsed by MountCode, the PFS0 is treated as a raw ExeFS. Because there is no NCA header, the ACID signatures are not validated -- and because there are no other signatures in a PFS0, this results in no signature checking happening at all.
 +
 +
The actual .nsp handling is eventually done by {content mounting function} called by MountCode and other FS commands.
 +
 +
Thus, by placing an ExeFS (NSOs + "main.npdm") and setting one's desired title ID to "@Sdcard:/some_title.nsp" or "@User:/some_title.nsp" etc one can launch arbitrary unsigned code, with arbitrary unsigned NPDMs.
 +
 +
This appears to have been fixed by only allowing .nsp when the input fstype==7 for the internal content-mounting function, returning 0x2EE202 otherwise.
 +
| With access to "lr": Arbitrary code execution with full system privileges.
 +
| [[5.0.0]]
 +
| [[5.0.0]]
 +
| Late 2017
 +
| April 23, 2018
 +
| Everyone
 +
|-
 +
| Single null-byte stack overflow in Loader ContentPath parsing
 +
| Previously, loader content path parsing looked like this, where path_from_lr was up to 0x300 bytes and not necessarily null-terminated:
 +
 +
  char nca_path[0x300] = {0};
 +
  strcat(nca_path, path_from_lr);
 +
  for (int i = 0; nca_path[i]; i++) {
 +
      if (nca_path[i] == '\\') { nca_path[i] = '/'); }
 +
  }
 +
 +
Thus, a content path of the maximum length (0x300 bytes) would result in strcat writing a NULL terminator past the end of the nca_path buffer.
 +
 +
This was fixed in [[6.0.0]], the new code looks like this:
 +
 +
  char nca_path[0x300];
 +
  strncpy(nca_path, path_from_lr, sizeof(nca_path));
 +
  for (int i = 0; i  < sizeof(nca_path) && nca_path[i]; i++) {
 +
      if (nca_path[i] == '\\') { nca_path[i] = '/'); }
 +
  }
 +
 +
 +
| With access to "lr": single null-byte stack overflow in Loader. Maybe (but probably not) loader code execution.
 +
| [[6.0.0]]
 +
| [[6.0.0]]
 +
| September 2, 2018
 +
| September 19, 2018
 +
| SciresM
 +
|-
 +
| System modules vulnerable to selective downgrade attacks
 +
| Horizon has no mechanism for specifying the specific title version to Loader on process creation.
 +
 +
Observing this, one can note that after a system update one could install a downgraded version of a specific system module (e.g. nvservices) while leaving the rest of the OS at the same version.
 +
 +
Unless there was some breaking API change, this allows one to make a console vulnerable once more to an exploit in a sysmodule by downgrading it and nothing else.
 +
 +
This was fixed in [[8.1.0]] by incrementing a version field in NPDM, and checking it against a hardcoded list for certain titles in Loader's process creation func.
 +
| With access to content installation commands (or a vulnerable lower version to selectively install newer titles), reintroducing bugs in vulnerable system modules on newer firmware versions.
 +
| [[8.1.0]]
 +
| [[8.1.0]]
 +
| When FIRM was first dumped in 2017.
 +
| June 17, 2019
 
| Everyone
 
| Everyone
 
|-
 
|-
Line 252: Line 437:     
=== System Modules ===
 
=== System Modules ===
 +
Flaws in this category pertain to any non-built-in system module.
 +
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 280: Line 467:  
|  April 2017
 
|  April 2017
 
|  On exploit's fix in [[3.0.0]]
 
|  On exploit's fix in [[3.0.0]]
|  [[User:qlutoo|qlutoo]], Reswitched team (independently)
+
|  [[User:qlutoo|qlutoo]], ReSwitched Team (independently)
 
|-
 
|-
 
| Unchecked domain ID in common IPC code
 
| Unchecked domain ID in common IPC code
 
| Prior to [[2.0.0]], object IDs in [[IPC_Marshalling#Domain_message|domain messages]] are not bounds checked. This out-of-bounds read could be exploited to brute-force ASLR and get PC control in some services that support domain messages.
 
| Prior to [[2.0.0]], object IDs in [[IPC_Marshalling#Domain_message|domain messages]] are not bounds checked. This out-of-bounds read could be exploited to brute-force ASLR and get PC control in some services that support domain messages.
 
|
 
|
| 2.0.0
+
| [[2.0.0]]
| 2.0.0
+
| [[2.0.0]]
 
| ~July 2017
 
| ~July 2017
 
| 20 July 2017‎
 
| 20 July 2017‎
Line 295: Line 482:  
| Sysmodule crashes.  Most usefully, crashing ldr allows access to fsp-ldr and crashing pm allows access to fsp-pr. Useless after [[4.0.0]], which mitigated a number of single-session service access issues.
 
| Sysmodule crashes.  Most usefully, crashing ldr allows access to fsp-ldr and crashing pm allows access to fsp-pr. Useless after [[4.0.0]], which mitigated a number of single-session service access issues.
 
| Unfixed
 
| Unfixed
| 4.1.0
+
| [[4.1.0]]
 
| 24 June 2017
 
| 24 June 2017
 
| 8 March 2018
 
| 8 March 2018
 
| [[User:daeken|daeken]]
 
| [[User:daeken|daeken]]
 +
|-
 +
| Transfer Memory leak in nvservices system module
 +
| The nvservices sysmodule does not clear most of its transfer memory prior to release.
 +
| The calling process can read key bits of memory, including breaking ASLR (by revealing the image base) and exposing the address of other transfer memory to set up attacks. More details here: [https://daeken.svbtle.com/nintendo-switch-nvservices-info-leak transfermeme (nvservices info leak)] by [[User:daeken|daeken]]
 +
| [[6.0.0]]
 +
| [[6.0.0]]
 +
| June 2017
 +
| 16 October 2018
 +
| [[User:qlutoo|qlutoo]] and [[User:hexkyz|hexkyz]],
 +
[[User:daeken|daeken]] (independently)
 +
|-
 +
| OOB write in audio system module
 +
| Prior to [[2.0.0]], the [[Audio_services#audout:u|AppendAudioOutBuffer]] and [[Audio_services#audin:u|AppendAudioInBuffer]] IPC commands would blindly increment the appended buffers' count while using said count value as an index to where the user data should be copied into. This resulted in an 0x28 bytes, user controlled, out-of-bounds memory write into the [[Audio_services|audio]] sysmodule's memory space.
 +
Combined with the [[Audio_services#audout:u|GetReleasedAudioOutBuffer]] or [[Audio_services#audin:u|GetReleasedAudioInBuffer]] commands, this could also be used as an 8 byte infoleak.
 +
 +
In [[2.0.0]], the commands now return error code 0x1099 if the number of unreleased buffers exceeds 0x1F.
 +
| Code execution under audio sysmodule
 +
| [[2.0.0]]
 +
| [[2.0.0]]
 +
|
 +
| November 2, 2018
 +
| [[User:hexkyz|hexkyz]], probably others (independently).
 +
|-
 +
| nvhax (memory corruption in nvservices system module)
 +
| Prior to [[6.2.0]], the [[NV_services|nvservices]] ioctl [[NV_services#.2Fdev.2Fnvhost-ctrl-gpu|NVGPU_GPU_IOCTL_WAIT_FOR_PAUSE]] would take a single "pwarpstate" argument which would be interpreted by nvservices as a memory pointer for writing 2 "warpstate" structs (one for each Streaming Multiprocessor).
 +
This resulted in nvservices attempting to blindly memcpy into this user supplied address and trigger a crash. However, if paired with an infoleak, this could be used to arbitrarily write 0x30 bytes anywhere in nvservices' memory space.
 +
Additionally, the "warpstate" struct itself was never initialized, which means nvservices would leak the 0x30 bytes from the stack. By invoking other ioctls it was also possible to partially control the stack contents and achieve a usable arbitrary memory write primitive.
 +
 +
In [[6.2.0]], [[NV_services#.2Fdev.2Fnvhost-ctrl-gpu|NVGPU_GPU_IOCTL_WAIT_FOR_PAUSE]] now takes 2 inline "warpstate" structs instead of a "pwarpstate" pointer, thus effectively avoiding the bad memcpy.
 +
| Code execution under nvservices sysmodule
 +
| [[6.2.0]]
 +
| [[6.2.0]]
 +
| April 5, 2017
 +
| November 24, 2018
 +
| [[User:hexkyz|hexkyz]]
 +
|-
 +
| Infoleak in nvservices system module
 +
| The [[NV_services|nvservices]] ioctl [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] takes an optional argument "addr" which allows the calling process to pass a pointer to user allocated memory for backing a nvmap object. If "addr" is left as 0, nvservices uses the transfer memory region (donated by the user during initialization) instead, when allocating memory for the nvmap object.
 +
By design, freeing the nvmap object by calling the ioctl [[NV_services#NVMAP_IOC_FREE|NVMAP_IOC_FREE]] returns, in its "refcount" argument, the user address previously supplied if the reference count reaches 0.
 +
However, prior to [[6.2.0]], the case where the transfer memory region is used to allocate the nvmap object was not taken into account, thus resulting in [[NV_services#NVMAP_IOC_FREE|NVMAP_IOC_FREE]] leaking back an address from within the transfer memory region mapped in nvservices' memory space.
 +
 +
In [[6.2.0]], [[NV_services#NVMAP_IOC_FREE|NVMAP_IOC_FREE]] no longer returns the address when the transfer memory region is used instead of user supplied memory.
 +
| Combined with other vulnerabilities: Defeating ASLR in nvservices sysmodule.
 +
| [[6.2.0]]
 +
| [[6.2.0]]
 +
| April 2017
 +
| November 24, 2018
 +
| Everyone
 +
|-
 
|}
 
|}

Navigation menu