Skip to content

Commit 7449af3

Browse files
committed
util_libc: Clarify type safety of libc::syscall usage.
1 parent 74cd1ed commit 7449af3

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

src/util_libc.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,31 @@ pub fn open_readonly(path: &[u8]) -> Result<libc::c_int, Error> {
105105
/// Thin wrapper around the `getrandom()` Linux system call
106106
#[cfg(any(target_os = "android", target_os = "linux"))]
107107
pub fn getrandom_syscall(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
108-
unsafe {
109-
libc::syscall(
110-
libc::SYS_getrandom,
111-
buf.as_mut_ptr().cast::<core::ffi::c_void>(),
112-
buf.len(),
113-
0,
114-
) as libc::ssize_t
115-
}
108+
// Rust requires object to be smaller than `isize::MAX` bytes, so there is
109+
// no real truncation here, even when running
110+
debug_assert!(buf.len() <= isize::MAX.unsigned_abs());
111+
112+
// TODO: Add support for x32 and similar ABIs?
113+
114+
// pointers can be passed to libc::syscall.
115+
const _: () = assert!(
116+
core::mem::size_of::<libc::c_long>() == core::mem::size_of::<*mut core::ffi::c_void>()
117+
);
118+
let ptr = buf.as_mut_ptr().cast::<core::ffi::c_void>();
119+
120+
// usize values can be passed to libc::syscall.
121+
const _: () =
122+
assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<libc::ssize_t>());
123+
let len: usize = buf.len();
124+
125+
const ZERO: libc::c_ulong = 0;
126+
127+
let res: libc::c_long = unsafe { libc::syscall(libc::SYS_getrandom, ptr, len, ZERO) };
128+
129+
// c_long to ssize_t conversion is lossless.
130+
const _: () =
131+
assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<libc::ssize_t>());
132+
#[allow(clippy::cast_possible_truncation)]
133+
let res = res as libc::ssize_t;
134+
res
116135
}

0 commit comments

Comments
 (0)