Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline RB_VM_SAVE_MACHINE_CONTEXT into BLOCKING_REGION #10795

Merged

Conversation

KJTsanaktsidis
Copy link
Contributor

There's an exhaustive explanation of this in the linked redmine bug, but the short version is as follows:

blocking_region_begin can spill callee-saved registers to the stack for its own use. That means they're not saved to ec->machine by the call to setjmp, since by that point they're already on the stack and new, different values are in the real registers. ec->machine's end-of-stack pointer is also bumped to accomodate this, BUT, after blocking_region_begin returns, that points past the end of the stack!

As far as C is concerned, that's fine; the callee-saved registers are restored when blocking_region_begin returns. But, if another thread triggers GC, it is relying on finding references to Ruby objects by walking the stack region pointed to by ec->machine.

If the C code in exec; subsequently does things that use that stack memory, then the value will be overwritten and the GC might prematurely collect something it shouldn't.

[Bug #20493]

There's an exhaustive explanation of this in the linked redmine bug, but
the short version is as follows:

blocking_region_begin can spill callee-saved registers to the stack for
its own use. That means they're not saved to ec->machine by the call to
setjmp, since by that point they're already on the stack and new,
different values are in the real registers. ec->machine's end-of-stack
pointer is also bumped to accomodate this, BUT, after
blocking_region_begin returns, that points past the end of the stack!

As far as C is concerned, that's fine; the callee-saved registers are
restored when blocking_region_begin returns. But, if another thread
triggers GC, it is relying on finding references to Ruby objects by
walking the stack region pointed to by ec->machine.

If the C code in exec; subsequently does things that use that stack
memory, then the value will be overwritten and the GC might prematurely
collect something it shouldn't.

[Bug #20493]
@KJTsanaktsidis KJTsanaktsidis force-pushed the ktsanaktsidis/fix_bundler_crash branch from aa7eca2 to aed11a1 Compare May 18, 2024 13:08
@KJTsanaktsidis KJTsanaktsidis merged commit 7afc16a into ruby:master May 19, 2024
100 checks passed
@KJTsanaktsidis KJTsanaktsidis deleted the ktsanaktsidis/fix_bundler_crash branch May 19, 2024 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants