Charlie Reis | 6d494327 | 2023-01-25 22:46:31 | [diff] [blame] | 1 | # Dangling Pointer Detector |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 2 | |
Arthur Sonzogni | 3fe4b9c0 | 2023-06-02 11:50:38 | [diff] [blame] | 3 | A pointer is dangling when it references freed memory. Typical examples can be |
| 4 | found [here](https://docs.google.com/document/d/11YYsyPF9rQv_QFf982Khie3YuNPXV0NdhzJPojpZfco/edit?resourcekey=0-h1dr1uDzZGU7YWHth5TRAQ#heading=h.wxt96wl0k0sq). |
| 5 | |
Tom Sepez | 17cf6ea | 2023-02-07 17:11:35 | [diff] [blame] | 6 | Dangling pointers are not a problem unless they are subsequently dereferenced |
| 7 | and/or used for other purposes. Proving that pointers are unused has turned out |
| 8 | to be difficult in general, especially in face of future modifications to |
| 9 | the code. Hence, they are a source of UaF bugs and highly discouraged unless |
| 10 | you are able to ensure that they can never be used after the pointed-to objects |
| 11 | are freed. |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 12 | |
Charlie Reis | 6d494327 | 2023-01-25 22:46:31 | [diff] [blame] | 13 | See also the [Dangling Pointers Guide](./dangling_ptr_guide.md) for how to fix |
| 14 | cases where dangling pointers occur. |
Arthur Sonzogni | c66acfe6 | 2022-12-08 14:27:28 | [diff] [blame] | 15 | |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 16 | Behind build flags, Chrome implements a dangling pointer detector. It causes |
| 17 | Chrome to crash, whenever a raw_ptr becomes dangling: |
| 18 | ```cpp |
| 19 | raw_ptr<T> ptr_never_dangling; |
| 20 | ``` |
| 21 | |
| 22 | On the other hand, we cannot simply ban all the usage of dangling pointers |
| 23 | because there are valid use cases. The `DisableDanglingPtrDetection` option can |
| 24 | be used to annotate "intentional-and-safe" dangling pointers. It is meant to be |
| 25 | used as a last resort, only if there is no better way to re-architecture the |
| 26 | code. |
| 27 | ```cpp |
| 28 | raw_ptr<T, DisableDanglingPtrDetection> ptr_may_dangle; |
| 29 | ``` |
| 30 | |
Charlie Reis | 6d494327 | 2023-01-25 22:46:31 | [diff] [blame] | 31 | The `DanglingUntriaged` option has been used to annotate pre-existing dangling |
Arthur Sonzogni | c66acfe6 | 2022-12-08 14:27:28 | [diff] [blame] | 32 | pointers in Chrome: |
| 33 | ```cpp |
| 34 | raw_ptr<T, DanglingUntriaged> ptr_dangling_mysteriously; |
| 35 | ``` |
| 36 | Contrary to `DisableDanglingPtrDetection`, we don't know yet why it dangles. It |
| 37 | is meant to be either refactored to avoid dangling, or turned into |
| 38 | "DisableDanglingPtrDetection" with a comment explaining what happens. |
| 39 | |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 40 | # How to check for dangling pointers? |
| 41 | |
Arthur Sonzogni | 591d14e | 2023-08-08 17:03:03 | [diff] [blame] | 42 | On **Linux**, it is **enabled by default** on most configurations. |
| 43 | To be precise: (`is_debug` or `dcheck_always_on`) and non `is_official` builds. |
| 44 | |
| 45 | For the other operating systems, this is gated by both build and runtime flags: |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 46 | |
| 47 | ## Build flags |
| 48 | |
| 49 | ```bash |
| 50 | gn args ./out/dangling/ |
| 51 | ``` |
| 52 | |
| 53 | ```gn |
Takuto Ikuta | 7e61637 | 2024-05-15 06:00:42 | [diff] [blame] | 54 | use_remoteexec = true |
Bartek Nowierski | e1038613 | 2022-10-25 01:16:14 | [diff] [blame] | 55 | is_debug = false # Important! (*) |
danakj | d8d332e | 2023-02-06 19:37:59 | [diff] [blame] | 56 | is_component_build = false # Important! (*) |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 57 | dcheck_always_on = true |
danakj | d8d332e | 2023-02-06 19:37:59 | [diff] [blame] | 58 | enable_backup_ref_ptr_support = true # true by default on some platforms |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 59 | enable_dangling_raw_ptr_checks = true |
| 60 | ``` |
| 61 | |
danakj | d8d332e | 2023-02-06 19:37:59 | [diff] [blame] | 62 | (*) We want to emphasize that setting either `is_debug = false` or |
| 63 | `is_component_build = false` is important. It is a common mistake to set |
| 64 | `is_debug` to `true`, which in turn turns on component builds, which |
Bartek Nowierski | e1038613 | 2022-10-25 01:16:14 | [diff] [blame] | 65 | disables PartitionAlloc-Everywhere. `enable_backup_ref_ptr_support = true` can't |
| 66 | be used without PartitionAlloc-Everywhere, and is silently set to `false`. |
Bartek Nowierski | 4cb2631 | 2022-07-14 08:56:10 | [diff] [blame] | 67 | |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 68 | ## Runtime flags |
| 69 | |
| 70 | ```bash |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 71 | ./out/dangling/content_shell \ |
Paul Semel | 4218462 | 2022-07-07 16:10:19 | [diff] [blame] | 72 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 73 | ``` |
| 74 | |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 75 | By default, Chrome will crash on the first dangling raw_ptr detected. |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 76 | |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 77 | # Runtime flags options: |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 78 | |
Pâris | e90af2c | 2023-01-30 14:22:41 | [diff] [blame] | 79 | ## Mode parameter |
| 80 | |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 81 | ### Crash (default) |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 82 | |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 83 | ```bash |
Paul Semel | 4218462 | 2022-07-07 16:10:19 | [diff] [blame] | 84 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/crash |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 85 | ``` |
| 86 | |
Bartek Nowierski | 4cb2631 | 2022-07-14 08:56:10 | [diff] [blame] | 87 | ### Record a list of signatures |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 88 | |
| 89 | Example usage: |
| 90 | ```bash |
| 91 | ./out/dangling/content_shell \ |
Pâris | e90af2c | 2023-01-30 14:22:41 | [diff] [blame] | 92 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/log_only \ |
Arthur Sonzogni | be6f013 | 2022-07-06 13:54:12 | [diff] [blame] | 93 | |& tee output |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 94 | ``` |
| 95 | |
| 96 | The logs can be filtered and transformed into a tab separated table: |
| 97 | ```bash |
| 98 | cat output \ |
Pâris | 5ec36bb | 2023-07-24 13:07:41 | [diff] [blame] | 99 | | grep "[DanglingSignature]" \ |
Pâris | e90af2c | 2023-01-30 14:22:41 | [diff] [blame] | 100 | | cut -f2,3,4,5 \ |
Arthur Sonzogni | c59a2cc | 2022-05-13 18:01:14 | [diff] [blame] | 101 | | sort \ |
| 102 | | uniq -c \ |
| 103 | | sed -E 's/^ *//; s/ /\t/' \ |
| 104 | | sort -rn |
| 105 | ``` |
| 106 | |
| 107 | This is used to list issues and track progresses. |
Pâris | e90af2c | 2023-01-30 14:22:41 | [diff] [blame] | 108 | |
| 109 | ## Type parameter |
| 110 | ### Select all dangling raw_ptr (default) |
| 111 | |
| 112 | The option: `type/all` selects every dangling pointer. |
| 113 | |
| 114 | Example usage: |
| 115 | ```bash |
| 116 | ./out/dangling/content_shell \ |
| 117 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:type/all |
| 118 | ``` |
| 119 | |
| 120 | ### Select cross tasks dangling raw_ptr |
| 121 | |
| 122 | The option: `type/cross_task` selects dangling pointers that are released in a |
| 123 | different task than the one where the memory was freed. Those are more likely to |
| 124 | cause UAF. |
| 125 | |
| 126 | Example usage: |
| 127 | ```bash |
| 128 | ./out/dangling/content_shell \ |
| 129 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:type/cross_task |
| 130 | ``` |
| 131 | |
Tom Sepez | 17cf6ea | 2023-02-07 17:11:35 | [diff] [blame] | 132 | ### Combination |
Pâris | e90af2c | 2023-01-30 14:22:41 | [diff] [blame] | 133 | |
| 134 | Both parameters can be combined, example usage: |
| 135 | ```bash |
| 136 | ./out/dangling/content_shell \ |
| 137 | --enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/log_only/type/cross_task \ |
| 138 | |& tee output |
| 139 | ``` |
Tom Sepez | 17cf6ea | 2023-02-07 17:11:35 | [diff] [blame] | 140 | |
| 141 | # Alternative dangling pointer detector (experimental) |
| 142 | |
| 143 | The dangling pointer detector above works only against certain heap allocated |
| 144 | objects, but there is an alternate form that catches other cases such as |
| 145 | pointers to out-of-scope stack variables or pointers to deallocated shared |
| 146 | memory regions. The GN arguments to enable it are: |
| 147 | |
| 148 | ```gn |
| 149 | enable_backup_ref_ptr_support=false |
| 150 | is_asan=true |
| 151 | is_component_build=false |
| 152 | use_asan_backup_ref_ptr=false |
Kalvin Lee | 3f1e9eda | 2024-07-18 21:53:23 | [diff] [blame] | 153 | use_raw_ptr_asan_unowned_impl=true |
Tom Sepez | 17cf6ea | 2023-02-07 17:11:35 | [diff] [blame] | 154 | ``` |
| 155 | |
| 156 | This will crash when the object containing the dangling ptr is destructed, |
| 157 | giving the usual three-stack trace from ASAN showing where the deleted object |
| 158 | was allocated and freed. |
Tom Sepez | 8fd417867 | 2023-02-14 02:36:18 | [diff] [blame] | 159 | |
| 160 | When running under this mode, there is no need to specify any --enable-features |
| 161 | flag as above. |