Add guard pages to the front of linear memories - #2977
Merged
Conversation
Subscribe to Label Actioncc @fitzgen, @peterhuene DetailsThis issue or pull request has been labeled: "fuzzing", "wasmtime:api"Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
peterhuene
reviewed
Jun 17, 2021
peterhuene
reviewed
Jun 17, 2021
peterhuene
reviewed
Jun 17, 2021
peterhuene
reviewed
Jun 17, 2021
peterhuene
reviewed
Jun 17, 2021
peterhuene
reviewed
Jun 17, 2021
peterhuene
approved these changes
Jun 17, 2021
peterhuene
left a comment
Member
There was a problem hiding this comment.
This looks great!
Just the one question about what to do regarding 32-bit default values for static memory sizes and a few nits.
This commit implements a safety feature for Wasmtime to place guard pages before the allocation of all linear memories. Guard pages placed after linear memories are typically present for performance (at least) because it can help elide bounds checks. Guard pages before a linear memory, however, are never strictly needed for performance or features. The intention of a preceding guard page is to help insulate against bugs in Cranelift or other code generators, such as CVE-2021-32629. This commit adds a `Config::guard_before_linear_memory` configuration option, defaulting to `true`, which indicates whether guard pages should be present both before linear memories as well as afterwards. Guard regions continue to be controlled by `{static,dynamic}_memory_guard_size` methods. The implementation here affects both on-demand allocated memories as well as the pooling allocator for memories. For on-demand memories this adjusts the size of the allocation as well as adjusts the calculations for the base pointer of the wasm memory. For the pooling allocator this will place a singular extra guard region at the very start of the allocation for memories. Since linear memories in the pooling allocator are contiguous every memory already had a preceding guard region in memory, it was just the previous memory's guard region afterwards. Only the first memory needed this extra guard. I've attempted to write some tests to help test all this, but this is all somewhat tricky to test because the settings are pretty far away from the actual behavior. I think, though, that the tests added here should help cover various use cases and help us have confidence in tweaking the various `Config` settings beyond their defaults. Note that this also contains a semantic change where `InstanceLimits::memory_reservation_size` has been removed. Instead this field is now inferred from the `static_memory_maximum_size` and guard size settings. This should hopefully remove some duplication in these settings, canonicalizing on the guard-size/static-size settings as the way to control memory sizes and virtual reservations.
Makes the pooling allocator a bit more reasonable by default on 32-bit with these settings.
uweigand
reviewed
Jun 21, 2021
| (2, &["i32.load16_s"]), | ||
| (4, &["i32.load" /*, "f32.load"*/]), | ||
| (8, &["i64.load" /*, "f64.load"*/]), | ||
| (16, &["v128.load"]), |
Member
There was a problem hiding this comment.
This unconditionally adds a SIMD operation, which we don't support on s390x yet, causing the test to fail.
Can we make this part architecture-dependent for now?
Member
Author
There was a problem hiding this comment.
Oh sure yeah, it's also fine to just comment this out since it's not really the most critical part of the test anyway
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This commit implements a safety feature for Wasmtime to place guard
pages before the allocation of all linear memories. Guard pages placed
after linear memories are typically present for performance (at least)
because it can help elide bounds checks. Guard pages before a linear
memory, however, are never strictly needed for performance or features.
The intention of a preceding guard page is to help insulate against bugs
in Cranelift or other code generators, such as CVE-2021-32629.
This commit adds a
Config::guard_before_linear_memoryconfigurationoption, defaulting to
true, which indicates whether guard pages shouldbe present both before linear memories as well as afterwards. Guard
regions continue to be controlled by
{static,dynamic}_memory_guard_sizemethods.The implementation here affects both on-demand allocated memories as
well as the pooling allocator for memories. For on-demand memories this
adjusts the size of the allocation as well as adjusts the calculations
for the base pointer of the wasm memory. For the pooling allocator this
will place a singular extra guard region at the very start of the
allocation for memories. Since linear memories in the pooling allocator
are contiguous every memory already had a preceding guard region in
memory, it was just the previous memory's guard region afterwards. Only
the first memory needed this extra guard.
I've attempted to write some tests to help test all this, but this is
all somewhat tricky to test because the settings are pretty far away
from the actual behavior. I think, though, that the tests added here
should help cover various use cases and help us have confidence in
tweaking the various
Configsettings beyond their defaults.Note that this also contains a semantic change where
InstanceLimits::memory_reservation_sizehas been removed. Instead thisfield is now inferred from the
static_memory_maximum_sizeand guardsize settings. This should hopefully remove some duplication in these
settings, canonicalizing on the guard-size/static-size settings as the
way to control memory sizes and virtual reservations.