Skip to content

Commit 2cdf331

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

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

src/util_libc.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,29 @@ 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!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<*mut core::ffi::c_void>());
116+
let ptr = buf.as_mut_ptr().cast::<core::ffi::c_void>();
117+
118+
// usize values can be passed to libc::syscall.
119+
const _: () =
120+
assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<libc::ssize_t>());
121+
let len: usize = buf.len();
122+
123+
const ZERO: libc::c_ulong = 0;
124+
125+
let res: libc::c_long = unsafe { libc::syscall(libc::SYS_getrandom, ptr, len, ZERO) };
126+
127+
// c_long to ssize_t conversion is lossless.
128+
const _: () =
129+
assert!(core::mem::size_of::<libc::c_long>() == core::mem::size_of::<libc::ssize_t>());
130+
#[allow(clippy::cast_possible_truncation)]
131+
let res = res as libc::ssize_t;
132+
res
116133
}

0 commit comments

Comments
 (0)