/rust/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.3.4/src/backends/sanitizer.rs
Line  | Count  | Source  | 
1  |  | use core::mem::MaybeUninit;  | 
2  |  |  | 
3  |  | /// Unpoisons `buf` if MSAN support is enabled.  | 
4  |  | ///  | 
5  |  | /// Most backends do not need to unpoison their output. Rust language- and  | 
6  |  | /// library- provided functionality unpoisons automatically. Similarly, libc  | 
7  |  | /// either natively supports MSAN and/or MSAN hooks libc-provided functions  | 
8  |  | /// to unpoison outputs on success. Only when all of these things are  | 
9  |  | /// bypassed do we need to do it ourselves.  | 
10  |  | ///  | 
11  |  | /// The call to unpoison should be done as close to the write as possible.  | 
12  |  | /// For example, if the backend partially fills the output buffer in chunks,  | 
13  |  | /// each chunk should be unpoisoned individually. This way, the correctness of  | 
14  |  | /// the chunking logic can be validated (in part) using MSAN.  | 
15  | 0  | pub unsafe fn unpoison(buf: &mut [MaybeUninit<u8>]) { | 
16  |  |     cfg_if! { | 
17  |  |         if #[cfg(getrandom_msan)] { | 
18  |  |             extern "C" { | 
19  |  |                 fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);  | 
20  |  |             }  | 
21  |  |             let a = buf.as_mut_ptr().cast();  | 
22  |  |             let size = buf.len();  | 
23  |  |             #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.  | 
24  |  |             unsafe { | 
25  |  |                 __msan_unpoison(a, size);  | 
26  |  |             }  | 
27  |  |         } else { | 
28  | 0  |             let _ = buf;  | 
29  |  |         }  | 
30  |  |     }  | 
31  | 0  | }  | 
32  |  |  | 
33  |  | /// Interprets the result of the `getrandom` syscall of Linux, unpoisoning any  | 
34  |  | /// written part of `buf`.  | 
35  |  | ///  | 
36  |  | /// `buf` must be the output buffer that was originally passed to the `getrandom`  | 
37  |  | /// syscall.  | 
38  |  | ///  | 
39  |  | /// `ret` must be the result returned by `getrandom`. If `ret` is negative or  | 
40  |  | /// larger than the length of `buf` then nothing is done.  | 
41  |  | ///  | 
42  |  | /// Memory Sanitizer only intercepts `getrandom` on this condition (from its  | 
43  |  | /// source code):  | 
44  |  | /// ```c  | 
45  |  | /// #define SANITIZER_INTERCEPT_GETRANDOM \  | 
46  |  | ///   ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD || SI_SOLARIS)  | 
47  |  | /// ```  | 
48  |  | /// So, effectively, we have to assume that it is never intercepted on Linux.  | 
49  |  | #[cfg(any(target_os = "android", target_os = "linux"))]  | 
50  | 0  | pub unsafe fn unpoison_linux_getrandom_result(buf: &mut [MaybeUninit<u8>], ret: isize) { | 
51  | 0  |     if let Ok(bytes_written) = usize::try_from(ret) { | 
52  | 0  |         if let Some(written) = buf.get_mut(..bytes_written) { | 
53  |  |             #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.  | 
54  |  |             unsafe { | 
55  | 0  |                 unpoison(written)  | 
56  |  |             }  | 
57  | 0  |         }  | 
58  | 0  |     }  | 
59  | 0  | }  |