A pointer is dangling when it references freed memory. Typical examples can be foundhere.
Dangling pointers are not a problem unless they are subsequently dereferenced and/or used for other purposes. Proving that pointers are unused has turned out to be difficult in general, especially in face of future modifications to the code. Hence, they are a source of UaF bugs and highly discouraged unless you are able to ensure that they can never be used after the pointed-to objects are freed.
See also theDangling Pointers Guide for how to fix cases where dangling pointers occur.
Behind build flags, Chrome implements a dangling pointer detector. It causes Chrome to crash, whenever a raw_ptr becomes dangling:
raw_ptr<T> ptr_never_dangling;
On the other hand, we cannot simply ban all the usage of dangling pointers because there are valid use cases. TheDisableDanglingPtrDetection
option can be used to annotate “intentional-and-safe” dangling pointers. It is meant to be used as a last resort, only if there is no better way to re-architecture the code.
raw_ptr<T,DisableDanglingPtrDetection> ptr_may_dangle;
TheDanglingUntriaged
option has been used to annotate pre-existing dangling pointers in Chrome:
raw_ptr<T,DanglingUntriaged> ptr_dangling_mysteriously;
Contrary toDisableDanglingPtrDetection
, we don't know yet why it dangles. It is meant to be either refactored to avoid dangling, or turned into “DisableDanglingPtrDetection” with a comment explaining what happens.
OnLinux, it isenabled by default on most configurations. To be precise: (is_debug
ordcheck_always_on
) and nonis_official
builds.
For the other operating systems, this is gated by both build and runtime flags:
gn args./out/dangling/
use_remoteexec=trueis_debug=false# Important! (*)is_component_build=false# Important! (*)dcheck_always_on=trueenable_backup_ref_ptr_support=true# true by default on some platformsenable_dangling_raw_ptr_checks=true
(*) We want to emphasize that setting eitheris_debug = false
oris_component_build = false
is important. It is a common mistake to setis_debug
totrue
, which in turn turns on component builds, which disables PartitionAlloc-Everywhere.enable_backup_ref_ptr_support = true
can't be used without PartitionAlloc-Everywhere, and is silently set tofalse
.
./out/dangling/content_shell \--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr
By default, Chrome will crash on the first dangling raw_ptr detected.
--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/crash
Example usage:
./out/dangling/content_shell \--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/log_only \|& tee output
The logs can be filtered and transformed into a tab separated table:
cat output \| grep"[DanglingSignature]" \| cut-f2,3,4,5 \| sort \| uniq-c \| sed-E's/^ *//; s/ /\t/' \| sort-rn
This is used to list issues and track progresses.
The option:type/all
selects every dangling pointer.
Example usage:
./out/dangling/content_shell \--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:type/all
The option:type/cross_task
selects dangling pointers that are released in a different task than the one where the memory was freed. Those are more likely to cause UAF.
Example usage:
./out/dangling/content_shell \--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:type/cross_task
Both parameters can be combined, example usage:
./out/dangling/content_shell \--enable-features=PartitionAllocBackupRefPtr,PartitionAllocDanglingPtr:mode/log_only/type/cross_task \|& tee output
The dangling pointer detector above works only against certain heap allocated objects, but there is an alternate form that catches other cases such as pointers to out-of-scope stack variables or pointers to deallocated shared memory regions. The GN arguments to enable it are:
enable_backup_ref_ptr_support=falseis_asan=trueis_component_build=falseuse_asan_backup_ref_ptr=falseuse_raw_ptr_asan_unowned_impl=true
This will crash when the object containing the dangling ptr is destructed, giving the usual three-stack trace from ASAN showing where the deleted object was allocated and freed.
When running under this mode, there is no need to specify any --enable-features flag as above.