From 44ce89ca535147683f13e301a2fcd43cb6fe72a6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 9 Nov 2025 06:14:12 -0800 Subject: [PATCH] Rudimentary `sanitize_memory` support. This adds a simple mechanism for informing msan of memory initializations that happen within `asm` blocks, and uses it in `fstat`, `read`, `pread`, and `getrandom`. More functions can be added in the future. Fixes #1531. --- Cargo.toml | 1 + src/backend/linux_raw/fs/syscalls.rs | 4 ++ src/backend/linux_raw/io/syscalls.rs | 60 +++++++++++++++----------- src/backend/linux_raw/rand/syscalls.rs | 9 +++- src/lib.rs | 2 + src/msan.rs | 12 ++++++ 6 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 src/msan.rs diff --git a/Cargo.toml b/Cargo.toml index 18579fcf4..7b8c33d52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -262,6 +262,7 @@ check-cfg = [ 'cfg(linux_raw)', 'cfg(linux_raw_dep)', 'cfg(lower_upper_exp_for_non_zero)', + 'cfg(sanitize_memory)', 'cfg(netbsdlike)', 'cfg(rustc_attrs)', 'cfg(rustc_diagnostics)', diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs index 872dd8e35..695af6abe 100644 --- a/src/backend/linux_raw/fs/syscalls.rs +++ b/src/backend/linux_raw/fs/syscalls.rs @@ -509,6 +509,10 @@ pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result { unsafe { let mut result = MaybeUninit::::uninit(); ret(syscall!(__NR_fstat, fd, &mut result))?; + + #[cfg(sanitize_memory)] + crate::msan::unpoison_maybe_uninit(&result); + Ok(result.assume_init()) } } diff --git a/src/backend/linux_raw/io/syscalls.rs b/src/backend/linux_raw/io/syscalls.rs index f40dfe5e2..527f5fe94 100644 --- a/src/backend/linux_raw/io/syscalls.rs +++ b/src/backend/linux_raw/io/syscalls.rs @@ -33,7 +33,14 @@ use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD}; #[inline] pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: (*mut u8, usize)) -> io::Result { - ret_usize(syscall!(__NR_read, fd, buf.0, pass_usize(buf.1))) + let r = ret_usize(syscall!(__NR_read, fd, buf.0, pass_usize(buf.1))); + + #[cfg(sanitize_memory)] + if let Ok(len) = r { + crate::msan::unpoison(buf.0, len); + } + + r } #[inline] @@ -52,17 +59,16 @@ pub(crate) unsafe fn pread( target_arch = "powerpc" ), ))] - { - ret_usize(syscall!( - __NR_pread64, - fd, - buf.0, - pass_usize(buf.1), - zero(), - hi(pos), - lo(pos) - )) - } + let r = ret_usize(syscall!( + __NR_pread64, + fd, + buf.0, + pass_usize(buf.1), + zero(), + hi(pos), + lo(pos) + )); + #[cfg(all( target_pointer_width = "32", not(any( @@ -72,24 +78,30 @@ pub(crate) unsafe fn pread( target_arch = "powerpc" )), ))] - { - ret_usize(syscall!( - __NR_pread64, - fd, - buf.0, - pass_usize(buf.1), - hi(pos), - lo(pos) - )) - } + let r = ret_usize(syscall!( + __NR_pread64, + fd, + buf.0, + pass_usize(buf.1), + hi(pos), + lo(pos) + )); + #[cfg(target_pointer_width = "64")] - ret_usize(syscall!( + let r = ret_usize(syscall!( __NR_pread64, fd, buf.0, pass_usize(buf.1), loff_t_from_u64(pos) - )) + )); + + #[cfg(sanitize_memory)] + if let Ok(len) = r { + crate::msan::unpoison(buf.0, len); + } + + r } #[inline] diff --git a/src/backend/linux_raw/rand/syscalls.rs b/src/backend/linux_raw/rand/syscalls.rs index acea3968c..ad5a657ef 100644 --- a/src/backend/linux_raw/rand/syscalls.rs +++ b/src/backend/linux_raw/rand/syscalls.rs @@ -11,5 +11,12 @@ use crate::rand::GetRandomFlags; #[inline] pub(crate) unsafe fn getrandom(buf: (*mut u8, usize), flags: GetRandomFlags) -> io::Result { - ret_usize(syscall!(__NR_getrandom, buf.0, pass_usize(buf.1), flags)) + let r = ret_usize(syscall!(__NR_getrandom, buf.0, pass_usize(buf.1), flags)); + + #[cfg(sanitize_memory)] + if let Ok(len) = r { + crate::msan::unpoison(buf.0, len); + } + + r } diff --git a/src/lib.rs b/src/lib.rs index 77f8a2158..d219a4c55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -178,6 +178,8 @@ pub(crate) mod maybe_polyfill; pub(crate) mod check_types; #[macro_use] pub(crate) mod bitcast; +#[cfg(sanitize_memory)] +pub(crate) mod msan; // linux_raw: Weak symbols are used by the use-libc-auxv feature for // glibc 2.15 support. diff --git a/src/msan.rs b/src/msan.rs new file mode 100644 index 000000000..027ad09e3 --- /dev/null +++ b/src/msan.rs @@ -0,0 +1,12 @@ +use core::ffi::c_void; +use core::mem::size_of; + +extern "C" { + /// + #[link_name = "__msan_unpoison"] + pub(crate) fn unpoison(a: *const c_void, size: usize); +} + +pub(crate) fn unpoison_maybe_uninit(t: &MaybeUninit) { + unpoison(t.as_ptr(), size_of::()) +}