Skip to content

Commit f9f7af9

Browse files
committed
util_unix: Move dependency on libc's errno to callers.
Make progress on reoving the libc dependency from util_unix, so we can remove the libc dependency for x86_64-unknown-linux-none.
1 parent c05a907 commit f9f7af9

6 files changed

+41
-36
lines changed

src/getrandom.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does
1616
//! nothing. On illumos, the default pool is used to implement getentropy(2),
1717
//! so we assume it is acceptable here.
18-
use crate::{util_unix::sys_fill_exact, Error};
18+
use crate::{util_libc::last_os_error, util_unix::sys_fill_exact, Error};
1919
use core::{ffi::c_void, mem::MaybeUninit};
2020

2121
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
2222
sys_fill_exact(dest, |buf| unsafe {
23-
libc::getrandom(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
23+
let ret: isize = libc::getrandom(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0);
24+
usize::try_from(ret).map_err(|_| last_os_error())
2425
})
2526
}

src/linux_android.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
77
}
88

99
// Also used by linux_android_with_fallback to check if the syscall is available.
10-
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
11-
unsafe {
10+
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
11+
use crate::util_libc::last_os_error;
12+
13+
let ret: libc::c_long = unsafe {
1214
libc::syscall(
1315
libc::SYS_getrandom,
1416
buf.as_mut_ptr().cast::<core::ffi::c_void>(),
1517
buf.len(),
1618
0,
17-
) as libc::ssize_t
18-
}
19+
)
20+
};
21+
const _: () = assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<isize>());
22+
usize::try_from(ret as isize).map_err(|_| last_os_error())
1923
}

src/linux_android_with_fallback.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Implementation for Linux / Android with `/dev/urandom` fallback
2-
use crate::{lazy::LazyBool, linux_android, use_file, util_libc::last_os_error, Error};
2+
use crate::{lazy::LazyBool, linux_android, use_file, Error};
33
use core::mem::MaybeUninit;
44

55
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
@@ -13,17 +13,13 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
1313
}
1414

1515
fn is_getrandom_available() -> bool {
16-
if linux_android::getrandom_syscall(&mut []) < 0 {
17-
match last_os_error().raw_os_error() {
18-
Some(libc::ENOSYS) => false, // No kernel support
19-
// The fallback on EPERM is intentionally not done on Android since this workaround
20-
// seems to be needed only for specific Linux-based products that aren't based
21-
// on Android. See https://github.com/rust-random/getrandom/issues/229.
22-
#[cfg(target_os = "linux")]
23-
Some(libc::EPERM) => false, // Blocked by seccomp
24-
_ => true,
25-
}
26-
} else {
27-
true
16+
match linux_android::getrandom_syscall(&mut []) {
17+
Err(err) if err.raw_os_error() == Some(libc::ENOSYS) => false, // No kernel support
18+
// The fallback on EPERM is intentionally not done on Android since this workaround
19+
// seems to be needed only for specific Linux-based products that aren't based
20+
// on Android. See https://github.com/rust-random/getrandom/issues/229.
21+
#[cfg(target_os = "linux")]
22+
Err(err) if err.raw_os_error() == Some(libc::EPERM) => false, // Blocked by seccomp
23+
_ => true,
2824
}
2925
}

src/netbsd.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Implementation for NetBSD
2-
use crate::{lazy::LazyPtr, util_unix::sys_fill_exact, Error};
2+
use crate::{lazy::LazyPtr, util_libc::last_os_error, util_unix::sys_fill_exact, Error};
33
use core::{ffi::c_void, mem::MaybeUninit, ptr};
44

5-
fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
5+
fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
66
static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND];
77
let mut len = buf.len();
88
let ret = unsafe {
@@ -16,9 +16,9 @@ fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
1616
)
1717
};
1818
if ret == -1 {
19-
-1
19+
Err(last_os_error())
2020
} else {
21-
len as libc::ssize_t
21+
Ok(len)
2222
}
2323
}
2424

@@ -38,7 +38,8 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
3838
if !fptr.is_null() {
3939
let func: GetRandomFn = unsafe { core::mem::transmute(fptr) };
4040
return sys_fill_exact(dest, |buf| unsafe {
41-
func(buf.as_mut_ptr().cast::<u8>(), buf.len(), 0)
41+
let ret: isize = func(buf.as_mut_ptr().cast::<u8>(), buf.len(), 0);
42+
usize::try_from(ret as isize).map_err(|_| last_os_error())
4243
});
4344
}
4445

src/use_file.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
//! Implementations that just need to read from a file
2-
use crate::{util_libc::open_readonly, util_unix::sys_fill_exact, Error};
2+
use crate::{
3+
util_libc::{last_os_error, open_readonly},
4+
util_unix::sys_fill_exact,
5+
Error,
6+
};
37
use core::{
48
cell::UnsafeCell,
59
ffi::c_void,
@@ -22,7 +26,8 @@ const FD_UNINIT: usize = usize::max_value();
2226
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
2327
let fd = get_rng_fd()?;
2428
sys_fill_exact(dest, |buf| unsafe {
25-
libc::read(fd, buf.as_mut_ptr().cast::<c_void>(), buf.len())
29+
let ret: isize = libc::read(fd, buf.as_mut_ptr().cast::<c_void>(), buf.len());
30+
usize::try_from(ret).map_err(|_| last_os_error())
2631
})
2732
}
2833

src/util_unix.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
#![allow(dead_code)]
2-
use crate::{util_libc::last_os_error, Error};
2+
use crate::Error;
33
use core::mem::MaybeUninit;
44

5-
// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function:
6-
// - should return -1 and set errno on failure
7-
// - should return the number of bytes written on success
5+
// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function
6+
// must return `Ok(written)` where `written` is the number of bytes written,
7+
// or otherwise an error.
88
pub fn sys_fill_exact(
99
mut buf: &mut [MaybeUninit<u8>],
10-
sys_fill: impl Fn(&mut [MaybeUninit<u8>]) -> libc::ssize_t,
10+
sys_fill: impl Fn(&mut [MaybeUninit<u8>]) -> Result<usize, Error>,
1111
) -> Result<(), Error> {
1212
while !buf.is_empty() {
13-
let res = sys_fill(buf);
14-
match res {
15-
res if res > 0 => buf = buf.get_mut(res as usize..).ok_or(Error::UNEXPECTED)?,
16-
-1 => {
17-
let err = last_os_error();
13+
match sys_fill(buf) {
14+
Ok(res) if res > 0 => buf = buf.get_mut(res..).ok_or(Error::UNEXPECTED)?,
15+
Err(err) => {
1816
// We should try again if the call was interrupted.
1917
if err.raw_os_error() != Some(libc::EINTR) {
2018
return Err(err);

0 commit comments

Comments
 (0)