-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add HostAlignedByteCount to enforce alignment at compile time #9620
Conversation
let stack_size = self.stack_size.byte_count() - self.page_size.byte_count(); | ||
let bottom_of_stack = top - stack_size; | ||
let start_of_stack = bottom_of_stack - self.page_size; | ||
let start_of_stack = bottom_of_stack - self.page_size.byte_count(); | ||
assert!(start_of_stack >= base && start_of_stack < (base + len)); | ||
assert!((start_of_stack - base) % self.stack_size == 0); | ||
assert!((start_of_stack - base) % self.stack_size.byte_count() == 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code and the similar section below would be good to convert over, but I decided to do this in a followup.
a64e06d
to
7546b03
Compare
I started working on a followup as well: 03efe42 Unfortunately GitHub's review flow does not let you manage stacked PRs unless you have push access to the destination repo, so I'll have to put these up one at a time. Sigh :( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this!
As a heads up I'm adding #9614 to the merge queue which is going to have a number of conflicts with this. It should (hopefully) be just a few |
…maps In the wasmtime codebase there are two kinds of mmaps: those that are always backed by anonymous memory and are always aligned, and those that are possibly file-backed and so the length might be unaligned. In bytecodealliance#9620 I accidentally mixed the two up in a way that was a ticking time bomb. To resolve this, add a type parameter to `Mmap` to distinguish between the cases. All of wasmtime's users are clearly either one or the other, so it's quite simple in the end.
…maps (#9639) In the wasmtime codebase there are two kinds of mmaps: those that are always backed by anonymous memory and are always aligned, and those that are possibly file-backed and so the length might be unaligned. In #9620 I accidentally mixed the two up in a way that was a ticking time bomb. To resolve this, add a type parameter to `Mmap` to distinguish between the cases. All of wasmtime's users are clearly either one or the other, so it's quite simple in the end.
9070ae2
to
ef285a4
Compare
(Apologies for the force push -- had to do it as part of the rebase. GH makes me cry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for this!
ef285a4
to
277670b
Compare
All right, think I fixed the Miri issue. |
|
||
// If the Wasm memory's page size is smaller than the host's page | ||
// size, then we might not need to actually change permissions, | ||
// since we are forced to round our accessible range up to the | ||
// host's page size. | ||
if new_accessible > self.accessible() { | ||
if let Ok(difference) = new_accessible.checked_sub(self.accessible()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be the source of the bug, albeit it's a bit indirect. Previously the >
condition is now morally becoming >=
since new_accessible == self.accessible()
didn't run this block before but it's now running this block with difference == 0
. I think then it may be the case that mprotect for 0 bytes is succeeding on unix but failing on Windows.
On Linux I see mprotect(0x740d36001000, 0, PROT_READ|PROT_WRITE) = 0
in strace with this patch when running the failing spec test and while I haven't executed this on Windows this is what I would suspect is going on.
Another option is to update the Mmap
type to skip make_accessible
when the byte size is zero which I think would also be reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's terrifying -- I'm going to fix this (probably by making make_accessible
ignore zero-sized regions) and go through this code again to make sure I didn't miss any other sign changes. Thanks for diagnosing this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made make_accessible
a no-op on zero-length allocations, as well as the other mprotect calls (make_executable
and make_readonly
). They also had this as a lurking bug because they had assertions that range.start <= range.end
, not range.start < range.end
.
I've also added tests for zero-length calls, and re-reviewed all of the sign changes -- didn't see any other errors.
As part of the work to allow mmaps to be backed by other implementations, I realized that we didn't have any way to track whether a particular usize is host-page-aligned at compile time. Add a `HostAlignedByteCount` which tracks that a particular usize is aligned to the host page size. This also does not expose safe unchecked arithmetic operations, to ensure that overflows always error out. With `HostAlignedByteCount`, a lot of runtime checks can go away thanks to the type-level assertion. In the interest of keeping the diff relatively small, I haven't converted everything over yet. More can be converted over as time permits.
277670b
to
93e23db
Compare
As part of the work to allow mmaps to be backed by other implementations (#9544), I realized that we didn't have any way to track whether a particular usize is host-page-aligned at compile time.
Add a
HostAlignedByteCount
which tracks that a particular usize is aligned to the host page size. This also does not expose safe unchecked arithmetic operations, to ensure that overflows are always handled.With
HostAlignedByteCount
, a lot of runtime checks can go away thanks to the type-level assertion.In the interest of keeping the diff relatively small, I haven't converted everything over yet. More code can be converted over as we go along.