Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=979

As part of Samsung KNOX, Samsung phones include a security hypervisor called RKP (Real-time Kernel Protection), running in EL2. This hypervisor is meant to ensure that the HLOS kernel running in EL1 remains protected from exploits and aims to prevent privilege escalation attacks by "shielding" certain data structures within the hypervisor.

One of the features supported by RKP (but not yet supported by the Linux Kernel), is a form of control flow protection which is meant to mitigate the ROP and JOP exploitation techniques. This mitigation leverages a 64-bit key stored in the hypervisor in order to encrypt the return addresses and frame pointers stored on a given kernel task's stack.

RKP provides two commands which produce a value using the 64-bit hypervisor key, namely:
  -cfp_ropp_new_key (RKP command 0x91)
  -cfp_ropp_new_key_reenc (RKP command 0x92)

Both of these commands convert the given virtual address from the kernel VAS to a physical address, but fail to verify the resulting address either via "physmap", or by checking that the given address does not reside in the physical address range of RKP itself.

This means an attacker can issue these RKP calls in order to corrupt RKP memory or write to regions which are S2-protected by EL2 (for example, the EL0/1 translation tables).

When the aforementioned commands are executed, they read the value of the HYP-mode physical timer (CNTHP_TVAL_EL2) and then write the value (timer_value XOR 64bit_cfpropp_key) into the attacker-controlled memory location. Note that the 64-bit key is not secret, as it can be deduced by the attacker by requesting the hypervisor to "encrypt" a given 64-bit value, and then XOR-ing it back again with the original value to obtain the key. Furthermore, the key is currently not even randomly generated, but rather hard-coded into the hypervisor (the current key embedded in the hypervisor is 0xDB551FCBF3F95C53).

Here is an outline of an attack scenario in which an attacker can gain code execution within RKP (EL2) from EL1:

  1. Get code execution in EL1
  2. Locate the PTE/PMD/PGD in TTBR1_EL1 pointing to an RKP code page
  3. Call "cfp_ropp_new_key_reenc" repeatedly to modify the translation table entry's AP bits to allow it to be writable
  4. (In case the region is S2-protected, do the same for the entries in VTTBR)
  5. Write directly to RKP's code segment from EL1

Lastly, it seems as though the RKP code pages are mapped as writable in TTBR_EL2 (and TCR_EL2.WXN is not set) - allowing the attacker to use these commands (or any other RKP memory corruption) in order to directly modify RKP code.

Proof of concept for the RKP CFP_ROPP_* memory corruption issue.

This PoC uses the CFP_ROPP_* commands to modify a kernel address in the kernel VAS.


Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/41211.zip