forked from bytecodealliance/wasmtime
-
Notifications
You must be signed in to change notification settings - Fork 1
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
Limitations of wasmtime's existing stack limit checks #122
Comments
frank-emrich
changed the title
Limitations of wasmtime's stack limit checks
Limitations of wasmtime's existing stack limit checks
Mar 6, 2024
frank-emrich
added a commit
that referenced
this issue
Mar 21, 2024
…ns (#136) Currently, we can overflow the stack while running inside a continuation, without the runtime having any way of detecting this. This PR partially rectifies this, by making the existing stack limit checks that get emitted by cranelift in every wasm function prelude work correctly while running inside a continuation. All that was required to enable the stack limit checks was the following: 1. Stop zero-ing out the `stack_limit` value in `VMRuntimeLimits` whenever we `resume` a continuation. 2. When creating a continuation, set a reasonable value for the `stack_limits` value in its `StackLimits` object. Note that all the required infrastructure to make sure that whenever we switch stacks, we save and restore the `stack_limits` value inside `VMRuntimeLimits` and the `StackLimits` object of the involved stacks was already implemented in #98 and #99. In this sense, enabling these checks is "free": The limits were already checked, but previously using a limit of 0. The only remaining question is what the "reasonable value" for the stack limits value mentioned above is. As discussed in #122, the stack limit checks that cranelift emits in function preludes are rather limited, and these limitations are reflected in the checks that this PR provides: When entering a wasm function, they check that the current stack pointer is larger than the `stack_limit` value in `VMRuntimeLimits`. They do not take into account how much stack space the function itself will occupy. No stack limit checks are performed when calling a host function. Thus, this PR defines a config option `wasmfx_red_zone_size`. The idea is that we define the stack limit as `bottom_of_fiber_stack` + `wasmfx_red_zone_size`. Thus, the stack checks boil down to the following: Whenever we enter a wasm function while inside a continuation, we ensure that there are at least `wasmfx_red_zone_size` bytes of stack space left. I've set the default value for `wasmfx_red_zone_size` to 32k. To get a rough idea for a sensible value, I determined that a call to the `fd_write` WASI function occupies ~21k of stack space, and generously rounded this up to 32k. **Important**: This means that these stack limit checks are incomplete: Calling a wasm or host function that occupies more than `wasmfx_red_zone_size` of stack space may still result in an undetected stack overflow!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This issue discusses some limitations of the existing stack limit checks in wasmtime, independent from wasmfx.
Currently, wasmtime generates stack limit checks such that each function prelude includes a check that is equivalent to the following pseudo-code:
Here, the
stack_limit
value in theVMRuntimeLimits
is initialized whenever we enter wasm, to a value that is basically$RSP
- stack_size, where stack_size is the corresponding wasmtime configuration/CLI option.This shows that the existing stack limit checks are not designed to prevent stack overflows, as they don't prevent stack overflows in situations such as the following:
stack_limit
in theVMRuntimeLimits
gets re-initialized each time. Thus, if we perform enough nested (!) wasm->host->wasm calls, we may exhaust the underlying stack while always staying within thestack_limit
.This illustrates that the stack limit in wasmtime is currently intended not so much as a safety feature, but more like a resource limit: It ensures that you (roughly) stay within a certain amount of stack space, similar to the mechanism for tracking consumed "fuel". In order to reliably detect stack overflows, wasmtime relies on the existence of guard pages instead.
This shows that additional care is required if we want to re-purpose use the existing stack checks so that they do become the main safety check for preventing stack overflows.
The text was updated successfully, but these errors were encountered: