Issue #12945 has been updated by Nobuyoshi Nakada.

Status changed from Assigned to Closed

----------------------------------------
Bug #12945: Use-after-free in vm_trace.c
https://bugs.ruby-lang.org/issues/12945#change-62152

* Author: Jeremy Evans
* Status: Closed
* Priority: Normal
* Assignee: Nobuyoshi Nakada
* Target version: 
* ruby -v: ruby 2.4.0preview3 (2016-11-07 trunk 56661) [x86_64-openbsd]
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
When running ruby 2.4's tests on OpenBSD amd64, I've been getting occasional bus errors.  I've only been getting them when running the full test suite, and they don't happen every time, and lowering the optimization level and adding debugging information usually makes them go away.  Thankfully, today I was finally able to generate one with debugging information.  Here's the gdb backtrace:

~~~
#0  0x0000068b8061b67a in thrkill () at <stdin>:2
#1  0x0000068b8066fdb9 in *_libc_abort () at /usr/src/lib/libc/stdlib/abort.c:52
#2  0x0000068b6d14e747 in die () at error.c:410
#3  0x0000068b6d14ea1f in rb_bug_context (ctx=Could not find the frame base for "rb_bug_context".
) at error.c:440
#4  0x0000068b6d2412a9 in sigbus (sig=Could not find the frame base for "sigbus".
) at signal.c:873
#5  <signal handler called>
#6  0x0000068b6d2d27c1 in exec_hooks_body (th=0x68be7a6d400, list=0x68bf84c7b18, trace_arg=0x68b5e26cbf0) at vm_trace.c:254
#7  0x0000068b6d2d29f3 in exec_hooks_protected (th=0x68be7a6d400, list=0x68bf84c7b18, trace_arg=0x68b5e26cbf0) at vm_trace.c:298
#8  0x0000068b6d2d2c9f in rb_threadptr_exec_event_hooks_orig (trace_arg=0x68b5e26cbf0, pop_p=0) at vm_trace.c:348
#9  0x0000068b6d2d2e2c in rb_threadptr_exec_event_hooks (trace_arg=0x68b5e26cbf0) at vm_trace.c:383
#10 0x0000068b6d2b18a7 in ruby_exec_event_hook_orig (th=0x68be7a6d400, flag=32, self=7198159641560, id=3009, called_id=3009, klass=7194852439200, data=52, pop_p=0) at vm_core.h:1622
#11 0x0000068b6d2b164f in vm_call_cfunc_with_frame (th=0x68be7a6d400, reg_cfp=0x68b6dc61dc0, calling=0x68b5e26ced0, ci=0x68bbf15b830, cc=0x68b32671a78) at vm_insnhelper.c:1742
#12 0x0000068b6d2b1940 in vm_call_cfunc (th=0x68be7a6d400, reg_cfp=0x68b6dc61dc0, calling=0x68b5e26ced0, ci=0x68bbf15b830, cc=0x68b32671a78) at vm_insnhelper.c:1847
~~~

In frame 6:

~~~
#6  0x0000068b6d2d27c1 in exec_hooks_body (th=0x68be7a6d400, list=0x68bf84c7b18, trace_arg=0x68b5e26cbf0) at vm_trace.c:254
254             if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) && (trace_arg->event & hook->events)) {
(gdb) info locals
hook = (rb_event_hook_t *) 0xdfdfdfdfdfdfdfdf
~~~

This `0xdfdfdfdfdfdfdfdf` pointer is the data OpenBSD's free(3) implementation writes to freed data, specifically designed to catch use-after-free errors such as this one.  Unfortunately, not being familiar with vm_trace.c, I'm unable to figure out how this is happening. It looks like the hooks are only freed in one place, and are removed from the rb_hook_list_t before they are freed. If you'd like more detail from the core dump, please let me know.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>