Bug #9249
closedRuby incorrectly inspects opaque libc jmp_buf for pointers to heap during GC.
Description
The garbage collector in Ruby inspects the opaque libc jmp_buf (as used by setjmp and longjmp) for pointers to heap during GC
This imposes an ABI requirement on glibc to keep the jmp_buf visible to Ruby. Ruby's inspection of the opaque jmp_buf goes against POSIX.
Recently the ARM glibc maintainer tried to encrypt more jmp_buf pointers (as part of the pointer mangling security work) on 32-bit ARM but Fedora Rawhide testing found that this broke Ruby's GC.
Ruby must not inspect jmp_buf. The buffer layout, size, and contents are subject to arbitrary change by the implementation.
It could be argued that if the jmp_buf were placed on the stack, that a stack scan would run into the same problems, but it doesn't from the standards perspective.
The point is that the entire jmp_buf could eventually be encrypted and the ruby gc scheme should continue to work.
If ruby needs anything from glibc we need to coordinate and make sure both communities stay on the same page.
This problem isn't unique to ruby, but it has recently caused us problems.
I fully understand that as a language implementation that ruby might need to do some things that are slightly outside of the standard. That's fine, but we need to talk them through and agree on them.
In the meantime we are likely going to encrypt less of the jmp_buf on ARM to keep ruby working.
While this bug is filed against 2.0.0-p353 the same code exists in trunk.
Ruby mailing list discussion:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/59052
glibc mailing list discussion:
https://sourceware.org/ml/libc-alpha/2013-12/msg00340.html
Updated by akr (Akira Tanaka) about 11 years ago
Is there an alternative function to dump registers for conservative GC?
I think Ruby (and other programs with conservative GC) can use such function if available.
Updated by Anonymous about 11 years ago
Is there an alternative function to dump registers for conservative GC?
On GCC, I think you can force registers to be saved to the stack before calling by marking a function with attribute((returns_twice))
Updated by mame (Yusuke Endoh) about 11 years ago
In principle, Boehm GC tries to use, in turn, getcontext, __builtin_unwind_init, and then setjmp.
The actual code has some assembly hacks to work around some platform bugs (?), though..
https://github.com/ivmai/bdwgc/blob/master/mach_dep.c#L213
--
Yusuke Endoh mame@tsg.ne.jp
Updated by vo.x (Vit Ondruch) about 11 years ago
Interestingly enough, I can't build Ruby 2.0.0 [1] but Ruby 2.1.0 [2] passes on the same configuration just fine. What was changed?
[1] http://koji.fedoraproject.org/koji/taskinfo?taskID=6309509
[2] http://koji.fedoraproject.org/koji/taskinfo?taskID=6308777
Updated by akr (Akira Tanaka) about 11 years ago
2013/12/15 mame (Yusuke Endoh) mame@tsg.ne.jp:
Issue #9249 has been updated by mame (Yusuke Endoh).
In principle, Boehm GC tries to use, in turn, getcontext, __builtin_unwind_init, and then setjmp.
I think they are not supposed to be used for conservative GC.
So they may encrypt pointers eventually.
Tanaka Akira
Updated by mame (Yusuke Endoh) about 11 years ago
akr (Akira Tanaka) wrote:
I think they are not supposed to be used for conservative GC.
So they may encrypt pointers eventually.
Of course. I think there is no "supposed" and portable way to get the content of the registers.
--
Yusuke Endoh mame@tsg.ne.jp
Updated by vo.x (Vit Ondruch) about 10 years ago
Was this resolved somehow? Testing this on Fedora 20, where the FP mangling was enabled [1], Ruby 2.0.0 fails:
https://kojipkgs.fedoraproject.org//work/tasks/1623/8321623/build.log
while the Ruby 2.2.0-preview2 passes:
https://kojipkgs.fedoraproject.org//work/tasks/1676/8321676/build.log
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- Status changed from Open to Closed
- Backport deleted (
1.9.3: UNKNOWN, 2.0.0: UNKNOWN)