# CVE-2020-16009: Chrome Turbofan Type Confusion after Map Deprecation
*Samuel Groß, Project Zero (Originally posted on [Project Zero blog](https://googleprojectzero.blogspot.com/p/rca.html) 2021-02-04)*

## The Basics

**Disclosure or Patch Date:** 2 November 2020

**Product:** Google Chrome

**Advisory:** https://chromereleases.googleblog.com/2020/11/stable-channel-update-for-desktop.html 

**Affected Versions:** 86.0.4240.111 and previous

**First Patched Version:** 86.0.4240.183

**Issue/Bug Report:**

* Project Zero: https://bugs.chromium.org/p/project-zero/issues/detail?id=2106 
* Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=1143772 

**Patch CL:** https://chromium.googlesource.com/v8/v8.git/+/3ba21a17ce2f26b015cc29adc473812247472776 

**Bug-Introducing CL:** N/A

**Reporter(s):** Clément Lecigne of Google's Threat Analysis Group and Samuel Groß of Google Project Zero

## The Code

**Proof-of-concept:** https://bugs.chromium.org/p/project-zero/issues/detail?id=2106 

**Exploit sample:** N/A

**Did you have access to the exploit sample when doing the analysis?** Yes

## The Vulnerability

**Bug class:** Type Confusion

**Vulnerability details:** Incorrect Map deprecation in V8, leading to type confusions

When Turbofan compiles code that performs a Map transition, it usually installs a `CodeDependency` so that the resulting code is deoptimized should the target Map ever be deprecated (meaning that the code should now transition to a different Map). This is done through the TransitionDependencyOffTheRecord function. This function will only install the dependency if the target Map can be deprecated, which is determined by `Map::CanBeDeprecated`. As shown below, `CanBeDeprecated` assumes that a Map storing only fields of type `Double` or `Tagged` can not be deprecated if `FLAG_unbox_double_fields` is false, which is the case if pointer compression is enabled (the default on x64):

```c++
bool Map::CanBeDeprecated() const {
  for (InternalIndex i : IterateOwnDescriptors()) {
    PropertyDetails details = instance_descriptors(kRelaxedLoad).GetDetails(i);
    if (details.representation().IsNone()) return true;
    if (details.representation().IsSmi()) return true;
    if (details.representation().IsDouble() && FLAG_unbox_double_fields)    <---
      return true;
    if (details.representation().IsHeapObject()) return true;
    if (details.kind() == kData && details.location() == kDescriptor) {
      return true;
    }
  }
  return false;
}
```

However, in certain scenarios (refer to the [PoC in the Project Zero](https://bugs.chromium.org/p/project-zero/issues/detail?id=2106) issue tracker for details), V8 would accidentally deprecate a Map containing only tagged and double properties. This bug can then be exploited when combined with the in-place field generalization mechanism. In short, the idea is to:

1. JIT compile a function that performs a transition from `map1{a:double}` to `map2{a:double,b:tagged}`. Turbofan will assume that `map2` can never be deprecated and will not install `CodeDependencies` to deoptimize the JIT code if it is.
2. Trigger the bug to deprecate `map2`. This does not deoptimize the JIT code.
3. In-place generalize `map1.a` to type `tagged`. This will not also generalize `map2` since it is deprecated.
4. Execute the JIT code. This will effectively transition from `map1{a:tagged}` to `map2{a:double,b:whatever}`, which is incorrect and results in a type confusion
 
**Patch analysis:** N/A

**Thoughts on how this vuln might have been found _(fuzzing, code auditing, variant analysis, etc.)_:**

 It is possible to find this bug through (targeted) fuzzing, although it is quite difficult to trigger it. As such, it is also (at least equally, in my opinion) possible that this bug would have been found through manual analysis, since the area of the code is known to be complex and security critical.

**(Historical/present/future) context of bug:** 

The Map transition/deprecation mechanism is fairly complex and various bugs have been found in it in the past, for example:

* https://bugs.chromium.org/p/chromium/issues/detail?id=746946
* https://bugs.chromium.org/p/project-zero/issues/detail?id=1923

Although these were related to element kinds and not property types/representations.

## The Exploit

(The terms *exploit primitive*, *exploit strategy*, *exploit technique*, and *exploit flow* are [defined here](https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html).)

**Exploit strategy (or strategies):** *Still under analysis*

**Exploit flow:** *Still under analysis*

**Known cases of the same exploit flow:** *Still under analysis*

**Part of an exploit chain?** This vulnerability was used as a Chrome RCE towards Android, but we do not know what exploits would be used after this. This vulnerability was used by the same actors during the same operation as [CVE-2020-15999](CVE-2020-15999.md), [CVE-2020-17087](CVE-2020-17087.md), [CVE-2020-16010](CVE-2020-16010.md), [CVE-2020-27930](CVE-2020-27930.md), [CVE-2020-27950](CVE-2020-27950.md), and [CVE-2020-27932](CVE-2020-27932.md).

## The Next Steps

### Variant analysis

**Areas/approach for variant analysis (and why):** Fuzzing or auditing the Map transition/deprecation logic.

**Found variants:**

### Structural improvements

* Build targeted fuzzers for the Map transition/deprecation logic, similar to [this one](https://github.com/googleprojectzero/fuzzilli/blob/ce4738fc571e2ef2aa5a30424f32f7957a70b5f3/Sources/FuzzilliCli/Profiles/V8Profile.swift#L28)
* Add a custom “sanitizer” to v8 that detects invalid Map deprecations. This can help fuzzers detect these kinds of issues earlier
* Simplifying Map operations, e.g. by [removing Map deprecations](https://docs.google.com/document/d/1VeKIskAakxQFnUBNkhBmVswgR7Vk6T1kAyKRLhqerb4/edit?usp=sharing)

### 0-day detection methods

N/A, likely hard to do generically. Triggers for JavaScript engine bugs are usually hard to distinguish from legitimate (and minified) JavaScript code. Especially for this type of bug, all the trigger code does is to create objects and load or store properties from/to them.

## Other References 
