-
Notifications
You must be signed in to change notification settings - Fork 199
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
MSRV 1.59: Remove libc requirement for x86_64-*-linux-none #461
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
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 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 |
---|---|---|
@@ -1 +1 @@ | ||
msrv = "1.57" | ||
msrv = "1.59" |
This file contains 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 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 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 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 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 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 |
---|---|---|
@@ -1,19 +1,84 @@ | ||
//! Implementation for Linux / Android without `/dev/urandom` fallback | ||
use crate::{util_libc, Error}; | ||
use crate::{util_unix::sys_fill_exact, Error}; | ||
use core::mem::MaybeUninit; | ||
|
||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { | ||
util_libc::sys_fill_exact(dest, getrandom_syscall) | ||
sys_fill_exact(dest, getrandom_syscall) | ||
} | ||
|
||
// The value of `EINTR` is not architecture-specific. It is checked against | ||
// `libc::EINTR` by linux_android_with_fallback.rs. | ||
pub const EINTR: i32 = 4; | ||
|
||
// Also used by linux_android_with_fallback to check if the syscall is available. | ||
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t { | ||
unsafe { | ||
libc::syscall( | ||
libc::SYS_getrandom, | ||
buf.as_mut_ptr().cast::<core::ffi::c_void>(), | ||
buf.len(), | ||
0, | ||
) as libc::ssize_t | ||
cfg_if! { | ||
// TODO: Expand inilne assembly to other architectures to avoid depending | ||
// on libc on Linux. | ||
if #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] { | ||
type Word = u64; | ||
type IWord = i64; | ||
|
||
// TODO(MSRV(1.78 feature(target_abi))): Enable this and remove `target_pointer_width` | ||
// restriction above. | ||
// | ||
// #[cfg(target_abi = "x32")] | ||
// const __X32_SYSCALL_BIT: Word = 0x40000000; | ||
// | ||
// #[cfg(target_abi = "x832")] | ||
// #[allow(non_upper_case_globals)] | ||
// pub const SYS_getrandom: IWord = 318 | __X32_SYSCALL_BIT; | ||
|
||
// #[cfg(not(target_abi = "x832"))] | ||
#[allow(non_upper_case_globals)] | ||
pub const SYS_getrandom: IWord = 318; | ||
|
||
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> { | ||
// Clamp request length to word size; no-op on regular (non-x32) x86_64. | ||
assert!(core::mem::size_of::<usize>() <= core::mem::size_of::<Word>()); | ||
let buflen: Word = buf.len() as Word; | ||
let mut ret: IWord; | ||
let flags = 0; | ||
unsafe { | ||
core::arch::asm!( | ||
"syscall", | ||
inout("rax") SYS_getrandom => ret, | ||
in("rdi") buf.as_mut_ptr(), | ||
in("rsi") buflen, | ||
in("rdx") flags, | ||
lateout("rcx") _, | ||
lateout("r11") _, | ||
options(nostack), | ||
briansmith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
} | ||
match Word::try_from(ret) { | ||
Ok(written) => { | ||
// `buflen` can from a usize and the return value won't be | ||
// larger than what we requested (otherwise that would be a | ||
// buffer overflow), so this cast is lossless even if | ||
// `usize` is smaller. | ||
Ok(written as usize) | ||
}, | ||
Err(_) => { | ||
Err(u32::try_from(ret.unsigned_abs()).map_or( | ||
Error::UNEXPECTED, Error::from_os_error)) | ||
} | ||
} | ||
} | ||
} else { | ||
use crate::util_libc::last_os_error; | ||
pub use libc::SYS_getrandom; | ||
|
||
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> { | ||
let ret: libc::c_long = unsafe { | ||
libc::syscall( | ||
SYS_getrandom, | ||
buf.as_mut_ptr().cast::<core::ffi::c_void>(), | ||
buf.len(), | ||
0, | ||
) | ||
}; | ||
const _:() = assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<isize>()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and here. |
||
usize::try_from(ret as isize).map_err(|_| last_os_error()) | ||
} | ||
} | ||
} |
This file contains 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 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 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 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 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 @@ | ||
#![allow(dead_code)] | ||
use crate::Error; | ||
use core::mem::MaybeUninit; | ||
|
||
// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function | ||
// must return `Ok(written)` where `written` is the number of bytes written, | ||
// or otherwise an error. | ||
pub fn sys_fill_exact( | ||
mut buf: &mut [MaybeUninit<u8>], | ||
sys_fill: impl Fn(&mut [MaybeUninit<u8>]) -> Result<usize, Error>, | ||
) -> Result<(), Error> { | ||
// Avoid depending on libc for Linux/Android. | ||
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
use crate::linux_android::EINTR; | ||
#[cfg(not(any(target_os = "android", target_os = "linux")))] | ||
use libc::EINTR; | ||
|
||
while !buf.is_empty() { | ||
match sys_fill(buf) { | ||
Ok(res) if res > 0 => buf = buf.get_mut(res..).ok_or(Error::UNEXPECTED)?, | ||
Err(err) => { | ||
// We should try again if the call was interrupted. | ||
if err.raw_os_error() != Some(EINTR) { | ||
return Err(err); | ||
} | ||
} | ||
// Negative return codes not equal to -1 should be impossible. | ||
// EOF (ret = 0) should be impossible, as the data we are reading | ||
// should be an infinite stream of random bytes. | ||
_ => return Err(Error::UNEXPECTED), | ||
} | ||
} | ||
Ok(()) | ||
} |
Oops, something went wrong.
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.
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 isn't clear to me that we actually need to use
__X32_SYSCALL_BIT
forx86_64-unknown-linux-gnux32
and other x32 targets. It seems like we could just use the 64-bit version of the syscall instead (i.e. same syscall number). But I am not so sure and it's hard for me to test x32.