diff --git a/src/use_file.rs b/src/use_file.rs index d2fe244f2..9167445eb 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -16,7 +16,7 @@ use core::{ /// - On Redox, only /dev/urandom is provided. /// - On AIX, /dev/urandom will "provide cryptographically secure output". /// - On Haiku and QNX Neutrino they are identical. -const FILE_PATH: &str = "/dev/urandom\0"; +const FILE_PATH: &[u8] = b"/dev/urandom\0"; const FD_UNINIT: usize = usize::max_value(); pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { @@ -57,7 +57,7 @@ fn get_rng_fd() -> Result { #[cfg(any(target_os = "android", target_os = "linux"))] wait_until_rng_ready()?; - let fd = unsafe { open_readonly(FILE_PATH)? }; + let fd = open_readonly(FILE_PATH)?; // The fd always fits in a usize without conflicting with FD_UNINIT. debug_assert!(fd >= 0 && (fd as usize) < FD_UNINIT); FD.store(fd as usize, Relaxed); @@ -69,7 +69,7 @@ fn get_rng_fd() -> Result { #[cfg(any(target_os = "android", target_os = "linux"))] fn wait_until_rng_ready() -> Result<(), Error> { // Poll /dev/random to make sure it is ok to read from /dev/urandom. - let fd = unsafe { open_readonly("/dev/random\0")? }; + let fd = open_readonly(b"/dev/random\0")?; let mut pfd = libc::pollfd { fd, events: libc::POLLIN, diff --git a/src/util_libc.rs b/src/util_libc.rs index 1d6bf9a2c..add966dea 100644 --- a/src/util_libc.rs +++ b/src/util_libc.rs @@ -70,14 +70,22 @@ pub fn sys_fill_exact( Ok(()) } -// SAFETY: path must be null terminated, FD must be manually closed. -pub unsafe fn open_readonly(path: &str) -> Result { - debug_assert_eq!(path.as_bytes().last(), Some(&0)); +/// Open a file in read-only mode. +/// +/// # Panics +/// If `path` does not contain any zeros. +// TODO: Move `path` to `CStr` and use `CStr::from_bytes_until_nul` (MSRV 1.69) +// or C-string literals (MSRV 1.77) for statics +#[inline(always)] +pub fn open_readonly(path: &[u8]) -> Result { + assert!(path.iter().any(|&b| b == 0)); loop { - let fd = libc::open( - path.as_ptr().cast::(), - libc::O_RDONLY | libc::O_CLOEXEC, - ); + let fd = unsafe { + libc::open( + path.as_ptr().cast::(), + libc::O_RDONLY | libc::O_CLOEXEC, + ) + }; if fd >= 0 { return Ok(fd); }