struct rb_callcache * point to an imemo object on the GC heap when
pushed into struct rb_class_cc_entries, but by the time vm_ccs_free()
runs, the entire GC page the imemo was on could already be deallocated.
With the right conditions, vm_ccs_free() wrote to freed memory.
rb_objspace_garbage_object_p() by itself is not enough to determine
liveness.
Use rb_gc_pointer_to_heap_p(). Other uses of
rb_objspace_garbage_object_p() could be making the same mistake, but
correcting them might introduce serious performance regressions, so
leave them alone for now.
Fix use-after-free in vm_ccs_free()
struct rb_callcache *
point to an imemo object on the GC heap whenpushed into
struct rb_class_cc_entries
, but by the time vm_ccs_free()runs, the entire GC page the imemo was on could already be deallocated.
With the right conditions, vm_ccs_free() wrote to freed memory.
rb_objspace_garbage_object_p() by itself is not enough to determine
liveness.
I conjectured this situation to be possible in
https://github.com/ruby/ruby/pull/11995 using hints from crashes
in the wild. With c37bdfa5311be0aa8503b995299fb9547cede0a6 ("Make
asan_poison_object poison the whole slot"), the in-tree test suite
now recreates this scenario123.
Use rb_gc_pointer_to_heap_p(). Other uses of
rb_objspace_garbage_object_p() could be making the same mistake, but
correcting them might introduce serious performance regressions, so
leave them alone for now.
http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477412 ↩
http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477445 ↩
http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477448 ↩