Skip to content

Commit 44ce89c

Browse files
committed
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.
1 parent 5245b81 commit 44ce89c

File tree

6 files changed

+63
-25
lines changed

6 files changed

+63
-25
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ check-cfg = [
262262
'cfg(linux_raw)',
263263
'cfg(linux_raw_dep)',
264264
'cfg(lower_upper_exp_for_non_zero)',
265+
'cfg(sanitize_memory)',
265266
'cfg(netbsdlike)',
266267
'cfg(rustc_attrs)',
267268
'cfg(rustc_diagnostics)',

src/backend/linux_raw/fs/syscalls.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result<Stat> {
509509
unsafe {
510510
let mut result = MaybeUninit::<Stat>::uninit();
511511
ret(syscall!(__NR_fstat, fd, &mut result))?;
512+
513+
#[cfg(sanitize_memory)]
514+
crate::msan::unpoison_maybe_uninit(&result);
515+
512516
Ok(result.assume_init())
513517
}
514518
}

src/backend/linux_raw/io/syscalls.rs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD};
3333

3434
#[inline]
3535
pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: (*mut u8, usize)) -> io::Result<usize> {
36-
ret_usize(syscall!(__NR_read, fd, buf.0, pass_usize(buf.1)))
36+
let r = ret_usize(syscall!(__NR_read, fd, buf.0, pass_usize(buf.1)));
37+
38+
#[cfg(sanitize_memory)]
39+
if let Ok(len) = r {
40+
crate::msan::unpoison(buf.0, len);
41+
}
42+
43+
r
3744
}
3845

3946
#[inline]
@@ -52,17 +59,16 @@ pub(crate) unsafe fn pread(
5259
target_arch = "powerpc"
5360
),
5461
))]
55-
{
56-
ret_usize(syscall!(
57-
__NR_pread64,
58-
fd,
59-
buf.0,
60-
pass_usize(buf.1),
61-
zero(),
62-
hi(pos),
63-
lo(pos)
64-
))
65-
}
62+
let r = ret_usize(syscall!(
63+
__NR_pread64,
64+
fd,
65+
buf.0,
66+
pass_usize(buf.1),
67+
zero(),
68+
hi(pos),
69+
lo(pos)
70+
));
71+
6672
#[cfg(all(
6773
target_pointer_width = "32",
6874
not(any(
@@ -72,24 +78,30 @@ pub(crate) unsafe fn pread(
7278
target_arch = "powerpc"
7379
)),
7480
))]
75-
{
76-
ret_usize(syscall!(
77-
__NR_pread64,
78-
fd,
79-
buf.0,
80-
pass_usize(buf.1),
81-
hi(pos),
82-
lo(pos)
83-
))
84-
}
81+
let r = ret_usize(syscall!(
82+
__NR_pread64,
83+
fd,
84+
buf.0,
85+
pass_usize(buf.1),
86+
hi(pos),
87+
lo(pos)
88+
));
89+
8590
#[cfg(target_pointer_width = "64")]
86-
ret_usize(syscall!(
91+
let r = ret_usize(syscall!(
8792
__NR_pread64,
8893
fd,
8994
buf.0,
9095
pass_usize(buf.1),
9196
loff_t_from_u64(pos)
92-
))
97+
));
98+
99+
#[cfg(sanitize_memory)]
100+
if let Ok(len) = r {
101+
crate::msan::unpoison(buf.0, len);
102+
}
103+
104+
r
93105
}
94106

95107
#[inline]

src/backend/linux_raw/rand/syscalls.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,12 @@ use crate::rand::GetRandomFlags;
1111

1212
#[inline]
1313
pub(crate) unsafe fn getrandom(buf: (*mut u8, usize), flags: GetRandomFlags) -> io::Result<usize> {
14-
ret_usize(syscall!(__NR_getrandom, buf.0, pass_usize(buf.1), flags))
14+
let r = ret_usize(syscall!(__NR_getrandom, buf.0, pass_usize(buf.1), flags));
15+
16+
#[cfg(sanitize_memory)]
17+
if let Ok(len) = r {
18+
crate::msan::unpoison(buf.0, len);
19+
}
20+
21+
r
1522
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ pub(crate) mod maybe_polyfill;
178178
pub(crate) mod check_types;
179179
#[macro_use]
180180
pub(crate) mod bitcast;
181+
#[cfg(sanitize_memory)]
182+
pub(crate) mod msan;
181183

182184
// linux_raw: Weak symbols are used by the use-libc-auxv feature for
183185
// glibc 2.15 support.

src/msan.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use core::ffi::c_void;
2+
use core::mem::size_of;
3+
4+
extern "C" {
5+
/// <https://github.com/gcc-mirror/gcc/blob/28219f7f99a80519d1c6ab5e5dc83b4c7f8d7251/libsanitizer/include/sanitizer/msan_interface.h#L40>
6+
#[link_name = "__msan_unpoison"]
7+
pub(crate) fn unpoison(a: *const c_void, size: usize);
8+
}
9+
10+
pub(crate) fn unpoison_maybe_uninit<T>(t: &MaybeUninit<T>) {
11+
unpoison(t.as_ptr(), size_of::<T>())
12+
}

0 commit comments

Comments
 (0)