Skip to content

Commit 0afdaf1

Browse files
authored
Tweak util_libc::open_readonly (#434)
`open_readonly` now accepts `&[u8]` instead of `&str` for path and asserts that it contains at least one zero byte. This allows to make the function safe. The compiler should be able to remove the assert since we use static paths.
1 parent 875081b commit 0afdaf1

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

src/use_file.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use core::{
1616
/// - On Redox, only /dev/urandom is provided.
1717
/// - On AIX, /dev/urandom will "provide cryptographically secure output".
1818
/// - On Haiku and QNX Neutrino they are identical.
19-
const FILE_PATH: &str = "/dev/urandom\0";
19+
const FILE_PATH: &[u8] = b"/dev/urandom\0";
2020
const FD_UNINIT: usize = usize::max_value();
2121

2222
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
@@ -57,7 +57,7 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
5757
#[cfg(any(target_os = "android", target_os = "linux"))]
5858
wait_until_rng_ready()?;
5959

60-
let fd = unsafe { open_readonly(FILE_PATH)? };
60+
let fd = open_readonly(FILE_PATH)?;
6161
// The fd always fits in a usize without conflicting with FD_UNINIT.
6262
debug_assert!(fd >= 0 && (fd as usize) < FD_UNINIT);
6363
FD.store(fd as usize, Relaxed);
@@ -69,7 +69,7 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
6969
#[cfg(any(target_os = "android", target_os = "linux"))]
7070
fn wait_until_rng_ready() -> Result<(), Error> {
7171
// Poll /dev/random to make sure it is ok to read from /dev/urandom.
72-
let fd = unsafe { open_readonly("/dev/random\0")? };
72+
let fd = open_readonly(b"/dev/random\0")?;
7373
let mut pfd = libc::pollfd {
7474
fd,
7575
events: libc::POLLIN,

src/util_libc.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,22 @@ pub fn sys_fill_exact(
7070
Ok(())
7171
}
7272

73-
// SAFETY: path must be null terminated, FD must be manually closed.
74-
pub unsafe fn open_readonly(path: &str) -> Result<libc::c_int, Error> {
75-
debug_assert_eq!(path.as_bytes().last(), Some(&0));
73+
/// Open a file in read-only mode.
74+
///
75+
/// # Panics
76+
/// If `path` does not contain any zeros.
77+
// TODO: Move `path` to `CStr` and use `CStr::from_bytes_until_nul` (MSRV 1.69)
78+
// or C-string literals (MSRV 1.77) for statics
79+
#[inline(always)]
80+
pub fn open_readonly(path: &[u8]) -> Result<libc::c_int, Error> {
81+
assert!(path.iter().any(|&b| b == 0));
7682
loop {
77-
let fd = libc::open(
78-
path.as_ptr().cast::<libc::c_char>(),
79-
libc::O_RDONLY | libc::O_CLOEXEC,
80-
);
83+
let fd = unsafe {
84+
libc::open(
85+
path.as_ptr().cast::<libc::c_char>(),
86+
libc::O_RDONLY | libc::O_CLOEXEC,
87+
)
88+
};
8189
if fd >= 0 {
8290
return Ok(fd);
8391
}

0 commit comments

Comments
 (0)