-
Notifications
You must be signed in to change notification settings - Fork 219
Use libc::getrandom on Solaris and update docs. #420
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
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
//! Solaris implementation using getrandom(2). | ||
//! | ||
//! While getrandom(2) has been available since Solaris 11.3, it has a few | ||
//! quirks not present on other OSes. First, on Solaris 11.3, calls will always | ||
//! fail if bufsz > 1024. Second, it will always either fail or completely fill | ||
//! the buffer (returning bufsz). Third, error is indicated by returning 0, | ||
//! rather than by returning -1. Finally, "if GRND_RANDOM is not specified | ||
//! then getrandom(2) is always a non blocking call". This _might_ imply that | ||
//! in early-boot scenarios with low entropy, getrandom(2) will not properly | ||
//! block. To be safe, we set GRND_RANDOM, mirroring the man page examples. | ||
//! | ||
//! For more information, see the man page linked in lib.rs and this blog post: | ||
//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2 | ||
//! which also explains why this crate should not use getentropy(2). | ||
use crate::{util_libc::last_os_error, Error}; | ||
use core::mem::MaybeUninit; | ||
|
||
const MAX_BYTES: usize = 1024; | ||
|
||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { | ||
for chunk in dest.chunks_mut(MAX_BYTES) { | ||
let ptr = chunk.as_mut_ptr() as *mut libc::c_void; | ||
let ret = unsafe { libc::getrandom(ptr, chunk.len(), libc::GRND_RANDOM) }; | ||
// In case the man page has a typo, we also check for negative ret. | ||
if ret <= 0 { | ||
return Err(last_os_error()); | ||
} | ||
// If getrandom(2) succeeds, it should have completely filled chunk. | ||
if (ret as usize) != chunk.len() { | ||
return Err(Error::UNEXPECTED); | ||
} | ||
} | ||
Ok(()) | ||
} |
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.
Uh oh!
There was an error while loading. Please reload this page.
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 it's better to write the
ret
check like this:Uh oh!
There was an error while loading. Please reload this page.
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.
It also may be worth to add a note that
getrandom_inner
never receives an empty buffer because of the check inlib.rs
.Uh oh!
There was an error while loading. Please reload this page.
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.
Fixed, but I made the error check
ret < 0
, as it's negative values which indicates errors forgetrandom
. Then we also don't have to think about zero-length buffer handling here. (though i agree it's fine).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 weird it seems like the docs contradict themselves:
"Upon successful completion, the getrandom() function returns the number of bytes written to buf. Otherwise, it returns 0 and sets errno to indicate the error."
"the function returns -1 and errno is set to EAGAIN."
Uh oh!
There was an error while loading. Please reload this page.
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.
No, the check should be
ret == 0
as per the cited man quote (yeah, I was surprised as well...).UPD: Maybe we should check both 0 and -1 to be extra safe? :)
Uh oh!
There was an error while loading. Please reload this page.
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.
Updated to check for negative and zero values and to document the weirdness with the error return value.
Uh oh!
There was an error while loading. Please reload this page.
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.
It could be worth to slightly modify the check to have only one branch in the happy path:
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 that is harder to read (and will probably get compiled to the same thing regardless).
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.
You can tweak formatting to your liking.
It does not: https://rust.godbolt.org/z/G6d1zq4hs But it's a small enough difference, so I do not insist on this change.
Uh oh!
There was an error while loading. Please reload this page.
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 interesting. I'll leave it as-is, but that's good to know.
I think only casting
ret
(which isssize_t
) tousize
once we know it's not negative is more consistent with how we handle those sorts of values elsewhere.