2026-07-04
The asker is doing Android Binder vulnerability research and wants to observe the reference count on struct binder_node as it changes at runtime. The concern is real: Binder refcount bugs (UAF via binder_inc_ref/binder_dec_ref mismatches) have produced some of the most impactful Android LPEs of the last decade (CVE-2019-2215, CVE-2022-20421). Verifying that strong and weak counters increment/decrement symmetrically is exactly the kind of question that separates a curious researcher from a shipped exploit.
Why it's hard: Binder is hot. Every IPC on Android touches it, so naive instrumentation floods your logs and changes timing enough to hide races. binder_node lives inside binder_proc, guarded by proc->inner_lock, and refs come in four flavors (strong/weak, internal/user-visible). You have to distinguish them or your data is noise.
Approach — layered, from cheapest to heaviest:
/sys/kernel/debug/binder/proc/<pid> and /sys/kernel/debug/binder/state already dump every node with its s (strong) and w (weak) counts. Snapshot in a loop — cheap, no rebuild.binder_transaction, binder_transaction_ref_to_node, binder_transaction_node_to_ref, and refcount-adjacent events. Turn them on via /sys/kernel/tracing/events/binder/ and filter by pid to keep the volume sane.binder_inc_ref_for_node, binder_dec_ref_olocked, binder_inc_node_nilocked, binder_dec_node_nilocked. Log the binder_node*, the delta, and a stack. bpftrace one-liners get you 80% of the way; a full BPF program with a hash keyed on node* gets you a running total per node without leaving the kernel.node->internal_strong_refs. Cuttlefish is the sane environment here — real hardware KGDB on a phone is possible but painful.Gotchas:
binder_inc_ref vs binder_inc_ref_for_node differ. Check your source before probing.proc->inner_lock, node->lock) mean a naive snapshot can catch a torn state; read counters under the same lock or accept the fuzziness.