-
Notifications
You must be signed in to change notification settings - Fork 36
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
Fundamental Soundness Problem #88
Comments
Rustsec PR: rustsec/advisory-db#1707 |
Did you consider transmuting to an array of MaybeUninit<u8> instead to avoid the padding/unitialized bytes problem? |
Hey, I just wanted to say thank you for all the hard work you put into ouroboros. |
Is it clear that self_cell does not have this issue, or is it possible that it just did not get the same amount of scrutiny? |
@rklaehn from what I can tell it doesn't have the same issue because it doesn't store the values as |
@joshua-maros wrapping in
Until then, // passes miri:
let b = Box::into_raw(Box::new(42_u8));
let r = ::core::mem::MaybeUninit::new(unsafe { &*b });
(|b, _r| {
drop(unsafe { Box::from_raw(b) });
})(b, r); |
I picked ouroborous originally because the API was a bit nicer than that in self_cell (we get to pick our own field names with ouroborous, but don't in self_cell). However, ouroboros is now unmaintained and has a soundness issue. The recommendation is to migrate, so that's what this commit is. refs: https://rustsec.org/advisories/RUSTSEC-2023-0042.html refs: someguynamedjosh/ouroboros#88 closes: https://github.com/KumoCorp/kumomta/security/dependabot/8
Hey @joshua-maros, thanks for the efforts of maintaining |
Any suggestions for alternatives that allow generics? |
ManuallyDrop is not currently specified to have the MaybeDangling behavior, and in the codegen backend (to my knowledge) there is no exception for ManuallyDrop. So this is not a bug, Miri is behaving as intended (and it would be bad for Miri to make an exception here if codegen doesn't also have such an exception). This looks like a good use-case to add to rust-lang/rfcs#3336. Would it be possible for someone to prepare a brief writeup of what ouroboros needs, and how MaybeDangling is required to achieve that goal?
FWIW, there is currently one exception to this, and that is a |
To be clear, when I said "intended behavior" I meant that this is not a Miri bug. I do think we should change this. But I can't just change this in Miri, codegen needs to be adjusted first, and that probably needs an RFC, and that's why I wrote rust-lang/rfcs#3336. |
Thank you @Bwallker and @danielhenrymantilla for the suggestion, I've tried it out and it appears to make the test suite pass under miri. It still won't support template parameters, but it's enough for now. I'll be publishing a version of the library that uses this fix soon and update the security advisory accordingly. |
@joshua-maros, do you mind clarifying if you intend to continue working on |
I intend to continue now that a fix has been found. I was planning on leaving due to there being nothing else I could do, since that is no longer the case I will keep working on it. |
@joshua-maros given the issued rustsec advisory I wonder if previous versions should be yanked from crates.io, what do you think? |
I will be doing that but only after people have had a chance to migrate. I had previously yanked a version too soon after uploading a fix, and it caused a lot of chaos as many libraries were suddenly broken and unable to compile. Especially since the compiler does not currently actually produce unsound code, this issue is not pressing. |
Thanks for clarifying. |
IMO yanking is entirely unnecessary here, given there are (AFAIK) no reports of this unsoundness causing a concrete issue.
|
Out of genuine interest, and having been in the same situation before. My understanding behind the motivation to yank in such situations was that it sends a clear signal to users, which might also run tests with miri, that their current version of the crate may cause issues with future compilers and that upgrading is necessary to avoid those issues. |
🤷 IMO the advisory is good enough, people that care enough will see the warning in That's just my opinion though. |
Fixes a soundness issue. See: https://rustsec.org/advisories/RUSTSEC-2023-0042.html someguynamedjosh/ouroboros#88
Fixes a soundness issue. See: https://rustsec.org/advisories/RUSTSEC-2023-0042.html someguynamedjosh/ouroboros#88
Miri enforces that references passed to functions are valid during the entire execution of the function, even when those references are passed inside a struct. See someguynamedjosh/ouroboros#88 for a similar issue and discussion on that topic.
Miri enforces that references passed to functions are valid during the entire execution of the function, even if they are not dereferenced, and even when those references are passed inside a struct. This was not satisfied for `single_object_encoding::Reader` because the `SerializerState` held a `ref` to the `Schema`, so the property was breaking during calls to drop. See someguynamedjosh/ouroboros#88 for a similar issue and discussion on that topic.
UPDATE: A fix has been implemented. 0.16.0+ is no longer unsound in the described way, but support for template parameters had to be cut in the process.
TL;DR: Ouroboros has a soundness problem. A fix has been attempted but it was also unsound. Currently the compiler does not actually produce unsound machine code, but it may begin doing so at any point in the future. Migrate code to use self_cell instead.
More details:
Currently, Ouroboros works internally by creating a struct where all uses of
'this
are replaced by'static
. However, a recent addition to Miri checks that references passed to functions are valid during the entire execution of the function, even when those references are passed inside a struct. This poses an issue for dropping self-referencing values, as the reference becomes invalid during the dropping process. Effectively, since self-referencing structs are not allowed in vanilla Rust, there is no allowance for dropping data during a function that has also been given a reference to that data. There's usually no way to passa
and&a
to the same function.A fix was attempted, where the struct would be turned in to a raw byte array and only transformed back into the underlying data type inside each function. This is allowable as a reference can be created and die over the body of a function, as long as the reference was created inside the function. However, this is also not sound if the original struct contains padding. There is no way to initialize padding bytes to a known value that Miri will accept, so when it is cast to an array some of the bytes contain uninitialized values. This is not acceptable (despite the fact that these bytes are never read) due to the potential for optimizations that may read from the uninitialized bytes. Besides which, this fix does not allow for template or constant parameters as there is no way to check the size of a templated type without giving specific, concrete values for the template parameters.
At this point, I'm just going to move on to other things. self_cell appears to be an excellent alternative for anyone using this crate.
The text was updated successfully, but these errors were encountered: