Paul Semel | f6756e8 | 2024-03-08 13:28:22 | [diff] [blame] | 1 | # Unretained dangling pointers. |
| 2 | |
| 3 | *See also the main document about [dangling pointers](./dangling_ptr.md)* |
| 4 | |
| 5 | **Background** |
| 6 | 37.5% of Use-After-Free (UAF) vulnerabilities in Chrome stemmed from callbacks using dangling `base::Unretained` pointers. |
| 7 | |
| 8 | **Mitigation:** |
| 9 | Runtime checks now help prevent callbacks with dangling pointers. A callback |
| 10 | invoked with dangling pointers is now turned into a crash. |
| 11 | |
| 12 | **Note:** BackupRefPtr mitigates the security impact of accessing those dangling |
| 13 | pointers. Still, they are the source of crashes and indicate the memory |
| 14 | ownership is not tracked properly in Chrome. Don't rely solely on pointer values |
| 15 | without dereferencing, as addresses might be reused. |
| 16 | |
| 17 | ## Fixing the Unretained Dangling Pointer |
| 18 | |
| 19 | 1. **Ideal Solution:** Refactor the code to ensure callbacks cannot be invoked |
| 20 | after their argument is freed. |
| 21 | 2. **WeakPtr<T>** If the argument's lifetime is not guaranteed to exceed the |
| 22 | callback, the `WeakPtr<T>` is a good alternative, provided you can find a |
| 23 | implement a reasonable fallback when the object is gone. |
| 24 | 3. **Unique Identifiers:** Opt for unique identifiers (e.g., `base::IdType`) |
| 25 | instead of pointers when the object is known to be freed. Unique identified |
| 26 | are better than pointer, as addresses might be reused. |
| 27 | |
| 28 | ## Annotations |
| 29 | |
| 30 | ### `base::UnsafeDangling` |
| 31 | |
| 32 | Opt-out of the check. Avoid if at all possible. Only for rare scenarios when you |
| 33 | are certain the pointer is dangling with no better alternatives. |
| 34 | |
| 35 | When using `UnsafeDangling()`, the receiver must be of type |
| 36 | `MayBeDangling<>`. Example: |
| 37 | |
| 38 | ```cpp |
| 39 | void MyCallback(MayBeDangling<int> ptr); |
| 40 | |
| 41 | int* may_be_dangling_ptr; |
| 42 | base::BindOnce(&MyCallback, base::UnsafeDangling(may_be_dangling_ptr)); |
| 43 | ``` |
| 44 | |
| 45 | ### `base::UnsafeDanglingUntriaged` |
| 46 | |
| 47 | Same as `UnsafeDangling()`, but with a different meaning: |
| 48 | |
| 49 | - **Temporary Triage:** Used for flagging pre-existing issues needing migration |
| 50 | to safer ownership. Chrome engineers still need to investigate the root cause. |
| 51 | Those pointers might be unsafe. |
| 52 | - **Do NOT Use For New Code:** Only acceptable for release-impacting issues. |
| 53 | Please prefer triaging pointers, as opposed to disabling the whole check |
| 54 | globally. |