Arthur Sonzogni | e17a10f | 2024-01-19 12:57:24 +0000 | [diff] [blame] | 1 | # Dangling Pointer Detector |
| 2 | |
| 3 | A pointer is dangling when it references freed memory. Typical examples can be found |
| 4 | [here](https://docs.google.com/document/d/11YYsyPF9rQv_QFf982Khie3YuNPXV0NdhzJPojpZfco/edit?resourcekey=0-h1dr1uDzZGU7YWHth5TRAQ#heading=h.wxt96wl0k0sq). |
| 5 | |
| 6 | Dangling pointers are not a problem unless they are subsequently dereferenced and/or used for other |
| 7 | purposes. Proving that dangling pointers are unused has turned out to be difficult in general, |
| 8 | especially in face of future modifications to the code. Hence, they are a source of UaF bugs and |
| 9 | highly discouraged unless you are able to ensure that they can never be used after the pointed-to |
| 10 | objects are freed. |
| 11 | |
| 12 | Dawn tests are configured to detect dangling pointers. |
| 13 | |
| 14 | ## Level of support |
| 15 | |
| 16 | The dangling pointer detector is an optional dependency of Dawn. It is enabled only when running |
| 17 | tests in the dawn_standalone configuration. It is also enforced as part of Chrome's tests. |
| 18 | |
| 19 | It is currently enforced under this configuration: |
| 20 | |
| 21 | | System | Compiler | Build system | Directory | Final embedder | Misc | |
| 22 | | ----------- | -------- | ------------ | ----------- | -------------------- | ---------------------------- | |
| 23 | | ✅ Android | ✅ Clang | ✅ GN | ✅ src/dawn | ✅ Dawn (standalone) | ❌ windows + debug | |
| 24 | | ✅ Windows | ✅ GCC | ❌ CMake | ❌ src/tint | ❌ Skia | ❌ windows + component_build | |
| 25 | | ✅ Mac | ❌ MSVC | ❌ Bazel | | ✅ Chrome | ❌ sanitizers | |
| 26 | | ✅ Linux | ❌ _ | ❌ _ | | ❌ _ | ✅ _ | |
| 27 | | ✅ ChromeOS | | | | | | |
| 28 | | ✅ Fuchsia | | | | | | |
| 29 | | ❌ iOS | | | | | | |
| 30 | | ❌ _ | | | | | | |
| 31 | |
| 32 | ## raw_ptr<> |
| 33 | |
| 34 | A `raw_ptr<T>` is a non-owning pointer. When using this kind of pointer, the severity of UAFs can be |
| 35 | reduced, because they are protected by |
| 36 | [MiraclePtr/BackupRefPtr](https://security.googleblog.com/2022/09/use-after-freedom-miracleptr.html) |
| 37 | |
| 38 | A `raw_ptr<T>` is transparently usable as a `T*`. It should be used in class and struct member |
| 39 | variable. |
| 40 | |
| 41 | In general, it shouldn't be used elsewhere: local variable, function arguments, etc... |
| 42 | |
| 43 | ## raw_ptr flavors |
| 44 | |
| 45 | `raw_ptr<T>` comes in 3 main flavors: |
| 46 | ```cpp |
| 47 | raw_ptr<T> ptr_never_dangling; |
| 48 | raw_ptr<T, DisableDanglingPtrDetection> ptr_allowed_to_dangle; |
| 49 | raw_ptr<T, DanglingUntriaged> ptr_dangling_to_investigate; |
| 50 | ``` |
| 51 | |
| 52 | The `DisableDanglingPtrDetection` option can be used to annotate “intentional-and-safe” dangling |
| 53 | pointers. It is meant to be used as a last resort, only if there is no better way to re-architecture |
| 54 | the code. |
| 55 | |
| 56 | The `DanglingUntriaged` means the pointer was dangling at the time of the |
| 57 | initial rewrite. We should investigate why. No new occurences should be added. |
| 58 | |
| 59 | ## Pointer arithmetic |
| 60 | |
| 61 | The use of pointer arithmetic with `raw_ptr<T>` is discouraged and disabled by default. Usually a |
| 62 | container like `std::span<>` should be used instead of the `raw_ptr`. |
| 63 | |
| 64 | The `AllowPtrArithmetic` option can be used to enable pointer arithmetic. For instance: |
| 65 | ``` |
| 66 | raw_ptr<T, AllowPtrArithmetic> artihmetic_ptr. |
| 67 | ``` |
| 68 | |
| 69 | ## Chrome's documentation |
| 70 | |
| 71 | The dangling pointer detector is part of Chrome too. You can use the main |
| 72 | documentation: |
| 73 | - [Dangling pointers detector](https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md) |
| 74 | - [Fixing dangling pointers guide](https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md) |
| 75 | |
| 76 | ## Dawn's specificities. |
| 77 | |
| 78 | Contrary to chrome, Dawn is not yet configured to display useful StackTraces and TaskTraces. It displays the error: |
| 79 | ``` |
| 80 | DanglingPointerDetector: A pointer was dangling! |
| 81 | Documentation: https://source.chromium.org/chromium/chromium/src/+/main:third_party/dawn/docs/dangling-pointer-detector.md |
| 82 | ``` |
| 83 | |
| 84 | To debug you can: |
| 85 | - **remotely**: Find a failing bot on the CQ running tests inside Chrome. You |
| 86 | will find useful debugging informations. |
| 87 | - **locally**: Use a debugger to display the StackTrace. Dawn is configured to crash when the |
| 88 | dangling raw_ptr is released. If needed, you can also understand where the memory was freed by |
| 89 | replacing `SetDanglingRawPtrReleasedFn` by `SetDanglingRawPtrDetectedFn` in |
| 90 | src/dawn/tests/PartitionAllocSupport.cpp`. |
| 91 | |
| 92 | ## Other resources |
| 93 | - [MiraclePtr in Dawn design doc](https://docs.google.com/document/d/1wz45t0alQthsIU9P7_rQcfQyqnrBMXzrOjSzdQo-V-A/edit#heading=h.vn4i6wy373x7) |
| 94 | - [MiraclePtr in chrome](https://chromium.googlesource.com/chromium/src/+/ddc017f9569973a731a574be4199d8400616f5a5/base/memory/raw_ptr.md) |
| 95 | - [Use-after-freedom: MiraclePtr](https://security.googleblog.com/2022/09/use-after-freedom-miracleptr.html) |
| 96 | - [MiraclePtr: protecting users from use-after-free vulnerabilities on more platforms](https://security.googleblog.com/2024/01/miracleptr-protecting-users-from-use.html) |