[ruby-core:94057] [Ruby master Bug#14834] rb_profile_frames SEGV when PC adjusted on IFUNC
From:
john@...
Date:
2019-07-30 16:04:22 UTC
List:
ruby-core #94057
Issue #14834 has been updated by jhawthorn (John Hawthorn).
Status changed from Closed to Open
I believe since r64737 this is an issue again.
On Ruby 2.6.3 I get an almost identical stacktrace as before
```
Thread 1 "ruby" received signal SIGSEGV, Segmentation fault.
0x00005555555cac9e in succ_index_lookup (x=<optimized out>, sd=0x10c483485c750000) at iseq.c:3357
3357 return imm_block_rank_get(sd->imm_part[i], j);
(gdb) bt
#0 0x00005555555cac9e in succ_index_lookup (x=<optimized out>, sd=0x10c483485c750000) at iseq.c:3357
#1 get_insn_info_succinct_bitvector (iseq=<optimized out>, pos=<optimized out>) at iseq.c:1593
#2 get_insn_info (pos=<optimized out>, iseq=<optimized out>) at iseq.c:1601
#3 rb_iseq_line_no (iseq=<optimized out>, pos=<optimized out>) at iseq.c:1669
#4 0x000055555571cf83 in calc_lineno (pc=<optimized out>, iseq=<optimized out>) at vm_backtrace.c:47
#5 rb_profile_frames (start=start@entry=0, limit=limit@entry=2048, buff=buff@entry=0x7fffffff86f0,
lines=lines@entry=0x7fffffff66f0) at vm_backtrace.c:1308
#6 0x00007ffff5532e83 in newobj (tpval=<optimized out>, ptr=0x555555feb610)
at ../../../../ext/allocation_sampler/allocation_sampler.c:227
#7 0x000055555571dc49 in tp_call_trace (tpval=<optimized out>, trace_arg=<optimized out>) at vm_trace.c:1194
#8 0x000055555571e206 in exec_hooks_body (ec=ec@entry=0x5555558c13b8, trace_arg=0x7fffffffc7d0, trace_arg@entry=0x7fffffffc790,
list=<optimized out>) at vm_trace.c:304
#9 0x0000555555720ebc in exec_hooks_unprotected (trace_arg=0x7fffffffc790, list=0x5555558c0e08, ec=<optimized out>)
at vm_trace.c:333
#10 rb_exec_event_hooks (trace_arg=trace_arg@entry=0x7fffffffc7d0, hooks=<optimized out>, pop_p=pop_p@entry=0) at vm_trace.c:378
#11 0x000055555558f72f in rb_exec_event_hook_orig (pop_p=0, data=<optimized out>, klass=0, called_id=0, id=0,
self=<optimized out>, flag=<optimized out>, hooks=<optimized out>, ec=0x5555558c13b8) at vm_core.h:1870
#12 gc_event_hook_body (ec=0x5555558c13b8, event=<optimized out>, data=<optimized out>, objspace=<optimized out>) at gc.c:1805
#13 0x0000555555599cf8 in newobj_slowpath (wb_protected=1, objspace=0x5555558c1140, v3=0, v2=<optimized out>, v1=0, flags=8199,
klass=<optimized out>) at vm_core.h:1735
#14 newobj_slowpath_wb_protected (klass=<optimized out>, flags=8199, v1=0, v2=<optimized out>, v3=0, objspace=0x5555558c1140)
at gc.c:1929
```
----------------------------------------
Bug #14834: rb_profile_frames SEGV when PC adjusted on IFUNC
https://bugs.ruby-lang.org/issues/14834#change-80285
* Author: kivikakk (Ashe Connor)
* Status: Open
* Priority: Normal
* Assignee: shyouhei (Shyouhei Urabe)
* Target version:
* ruby -v: ruby 2.6.0dev (2018-06-08 trunk 63606) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Since r62052, we increment `ec->cfp->pc` by one pointer width (e.g. 8 bytes) in `gc_event_hook_body` around the `EXEC_EVENT_HOOK` call.
This becomes a problem when the hook is on an IFUNC: in this case, `pc == 0x0`, meaning we increment it to a non-zero value during that call.
`rb_profile_frames` uses the following check to determine if frame info should be recorded:
~~~ c
if (cfp->iseq && cfp->pc) {
~~~
The example here is [`stackprof`](https://github.com/tmm1/stackprof/blob/58d65ffa801ed27f013d573148783694526c7426/ext/stackprof/stackprof.c#L486), which calls `rb_profile_frames` in a gc event hook. This will segfault currently, as the above check will pass.
`calc_lineno` then attempts to calculate the line number:
~~~ c
size_t pos = (size_t)(pc - iseq->body->iseq_encoded);
~~~
This fails for a variety of reasons: `iseq_encoded` isn't valid because `iseq` isn't an `rb_iseq_t` underneath, producing an essentially random value, and `pc` is 0x8, so we underflow and eventually cause an overrun in `succ_index_lookup` with a huge `pos` argument.
We instead only adjust PC if it appears to be a valid pointer in the first place.
---Files--------------------------------
pc-treatment.diff (777 Bytes)
--
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>