-
Notifications
You must be signed in to change notification settings - Fork 70
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
Fix structs incorrect memory layout #208
Conversation
Wouldn't adding |
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 dislike how easy it is to use ByteValued insafely :/. Are we the only one doing this? Does the ecosystem maybe have safer alternatives?
Yes, but that requires changing the qemu's definition of this structure, and any other VMMs that use it. We can also fix it by adding a 4-byte explicit padding field to be always 0 (reading an uninitialized explicit padding field is also UB) |
Ah. So QEMU expects a size that includes padding? Adding explicit padding sounds good to me then (it is done in other places too). I do not understand the remark about it always being 0... Why does that matter? |
Because we will have the same UB problem if the VMM sends a struct with uninitialized padding fields, so we need a guarantee that those fields are initialized to 0 (or any other value) |
Hm... But for us, reading the memory, the padding will have some value. It may be any value, but it should not be undefined behavior (assuming it is an int type), right? Or do I misunderstand something here? I do not understand why we need to define this to be initialized with a specific value. In my understand we do not care where the memory comes from. We only care that we may access |
for rust "abstract machine" an area of memory with random bit pattern it's not the same as uninitialized memory |
Is the padding defined in the spec? |
Nop, is not defined in the spec, IMO the correct thing to do is to change the spec to packed as you said |
mmm, it looks QEMU is not using |
But this will break the compatibility with old version. Or should we support both here? |
Even if it is |
Well, the volatile-memory abstraction exists exactly because of that. So our read_obj() stuff accounts for Rust's memory rules. Anything (safe) that leaves the volatile-memory abstraction is a copy from the guest memory. So I see no problems from that - as long as it is repr(C) of course. |
Yes |
I thought it only took into account the "volatility" of memory, basically not being able to get a reference to memory that can change behind your back, and not elide the reads, etc. but I'm not sure if that allows operating with uninitialized memory, I think are different things. EDIT:
|
This PR LGTM, thanks!
I think we should discuss this in a separated Issue/PR, but we can't use |
Currently, some vhost-user-messages structs are defined with just 'repr(packed)', and also implement the 'ByteValue' trait implying that they can be initialized safely from an array of bytes. This is not safe, because the default memory representation does not guarantee that the fields will not be reordered. Signed-off-by: German Maglione <[email protected]>
af01b9d
to
605227c
Compare
Summary of the PR
Currently, some vhost-user-messages structs are defined with just
repr(packed)
, and also implement theByteValue
trait implying that they can be initialized safely from an array of bytes.This is not safe, because the default memory representation does not guarantee that the fields will not be reordered.
Note for reviewers
Another issue that I didn't address in this PR is the struct:
this struct implements
ByteValued
, but it has 4 bytes of padding at the end, so reading that uninitialized memory is UB.