Skip to content

Commit 5d21d39

Browse files
committed
switch to using u64s
1 parent 97a3725 commit 5d21d39

File tree

3 files changed

+91
-52
lines changed

3 files changed

+91
-52
lines changed

src/discrete_alloc.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::sync;
33

44
use nix::sys::mman::ProtFlags;
55

6+
use crate::helpers::ToU64;
7+
68
static ALLOCATOR: sync::Mutex<MachineAlloc> = sync::Mutex::new(MachineAlloc::empty());
79

810
/// A distinct allocator for the `MiriMachine`, allowing us to manage its
@@ -51,9 +53,9 @@ impl MachineAlloc {
5153
}
5254

5355
/// Returns a vector of page addresses managed by the allocator.
54-
pub fn pages() -> Vec<usize> {
56+
pub fn pages() -> Vec<u64> {
5557
let alloc = ALLOCATOR.lock().unwrap();
56-
alloc.pages.clone().into_iter().map(|p| p.addr()).collect()
58+
alloc.pages.clone().into_iter().map(|p| p.addr().to_u64()).collect()
5759
}
5860

5961
fn add_page(&mut self) {

src/shims/native_lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
180180
}
181181
}
182182

183-
// Prepare all exposed memory.
184-
this.prepare_exposed_for_native_call()?;
183+
if super::trace::Supervisor::init().is_err() {
184+
// Worst-case prepare all exposed memory.
185+
this.prepare_exposed_for_native_call()?;
186+
}
185187

186188
// Convert them to `libffi::high::Arg` type.
187189
let libffi_args = libffi_args
@@ -200,9 +202,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
200202
unsafe fn do_native_call<T: libffi::high::CType>(ptr: CodePtr, args: &[ffi::Arg<'_>]) -> T {
201203
use shims::trace::Supervisor;
202204

203-
let _ = Supervisor::init();
204205
let ret = unsafe {
205-
Supervisor::start_ffi().unwrap();
206+
Supervisor::start_ffi();
206207
let ret = ffi::call(ptr, args);
207208
Supervisor::end_ffi();
208209
ret

src/shims/trace.rs

Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use nix::sys::{ptrace, signal, wait};
33
use nix::unistd;
44

55
use crate::discrete_alloc;
6+
use crate::helpers::ToU64;
67

78
#[cfg(target_pointer_width = "64")]
89
const BITS: u32 = 64;
@@ -17,7 +18,7 @@ const BREAKPT_INSTR: i64 = 0xD420;
1718
// We do NOT ever want to block the child from accessing this!!
1819
static SUPERVISOR: std::sync::Mutex<Option<Supervisor>> = std::sync::Mutex::new(None);
1920
static mut PAGE_ADDR: *mut libc::c_void = std::ptr::null_mut();
20-
static mut PAGE_SIZE: usize = 4096;
21+
static mut PAGE_SIZE: u64 = 4096;
2122
static mut CLICK_HERE_4_FREE_STACK: [u8; 1024] = [0; 1024];
2223

2324
trait ArchIndependentRegs {
@@ -83,6 +84,16 @@ pub struct Supervisor {
8384

8485
impl Supervisor {
8586
pub fn init() -> Result<(), ()> {
87+
let ptrace_status = std::fs::read_to_string("/proc/sys/kernel/yama/ptrace_scope");
88+
if let Ok(stat) = ptrace_status {
89+
if let Some(stat) = stat.chars().next() {
90+
// Fast-error if ptrace is disabled on the system and it's linux
91+
if stat != '0' && stat != '1' {
92+
return Err(());
93+
}
94+
}
95+
}
96+
8697
let sv = SUPERVISOR.lock().map_err(|_| ())?;
8798
let is_none = sv.is_none();
8899

@@ -113,42 +124,42 @@ impl Supervisor {
113124
unistd::ForkResult::Child => {
114125
let mut sv = SUPERVISOR.lock().map_err(|_| ())?;
115126
*sv = Some(Supervisor { t_message, r_event });
116-
Ok(())
117127
}
118128
}
119129
}
120-
} else {
121-
Err(())
122130
}
131+
Ok(())
123132
}
124133

125-
pub unsafe fn start_ffi() -> Option<()> {
126-
let mut sv_guard = SUPERVISOR.lock().ok()?;
127-
let sv = sv_guard.take()?;
128-
let exposed = discrete_alloc::MachineAlloc::pages();
129-
sv.t_message.send(TraceRequest::BeginFfi(exposed)).ok()?;
130-
*sv_guard = Some(sv);
131-
unsafe {
132-
if discrete_alloc::MachineAlloc::prepare_ffi().is_err() {
133-
discrete_alloc::MachineAlloc::unprep_ffi();
134-
return None;
134+
pub unsafe fn start_ffi() {
135+
let mut sv_guard = SUPERVISOR.lock().unwrap();
136+
if let Some(sv) = sv_guard.take() {
137+
let exposed = discrete_alloc::MachineAlloc::pages();
138+
sv.t_message.send(TraceRequest::BeginFfi(exposed)).unwrap();
139+
*sv_guard = Some(sv);
140+
unsafe {
141+
if discrete_alloc::MachineAlloc::prepare_ffi().is_err() {
142+
// Don't mess up unwinding by maybe leaving the memory partly protected
143+
discrete_alloc::MachineAlloc::unprep_ffi();
144+
panic!("Cannot protect memory for FFI call!");
145+
}
135146
}
147+
signal::raise(signal::SIGSTOP).unwrap();
136148
}
137-
signal::raise(signal::SIGSTOP).unwrap();
138-
Some(())
139149
}
140150

141151
pub unsafe fn end_ffi() {
142152
let mut sv_guard = SUPERVISOR.lock().unwrap();
143-
let sv = sv_guard.take().unwrap();
144-
sv.t_message.send(TraceRequest::EndFfi).unwrap();
145-
*sv_guard = Some(sv);
146-
drop(sv_guard);
147-
discrete_alloc::MachineAlloc::unprep_ffi();
153+
if let Some(sv) = sv_guard.take() {
154+
sv.t_message.send(TraceRequest::EndFfi).unwrap();
155+
*sv_guard = Some(sv);
156+
drop(sv_guard);
157+
discrete_alloc::MachineAlloc::unprep_ffi();
158+
}
148159
}
149160

150161
pub fn get_events() -> Option<MemEvents> {
151-
let mut sv_guard = SUPERVISOR.lock().ok()?;
162+
let mut sv_guard = SUPERVISOR.lock().unwrap();
152163
let sv = sv_guard.take()?;
153164
let ret = sv.r_event.recv().ok();
154165
*sv_guard = Some(sv);
@@ -158,15 +169,15 @@ impl Supervisor {
158169

159170
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
160171
pub enum TraceRequest {
161-
BeginFfi(Vec<usize>),
172+
BeginFfi(Vec<u64>),
162173
EndFfi,
163174
Die,
164175
}
165176

166177
#[derive(serde::Serialize, serde::Deserialize, Debug)]
167178
pub struct MemEvents {
168-
pub accesses: Vec<(usize, usize, MemAccessType)>,
169-
pub mappings: Vec<(usize, usize)>,
179+
pub accesses: Vec<(u64, u64, MemAccessType)>,
180+
pub mappings: Vec<(u64, u64)>,
170181
}
171182

172183
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
@@ -192,6 +203,20 @@ impl MemAccessType {
192203
MemAccessType::ReadWrite => (),
193204
}
194205
}
206+
207+
pub fn did_read(&self) -> bool {
208+
match self {
209+
MemAccessType::Write => false,
210+
_ => true,
211+
}
212+
}
213+
214+
pub fn did_write(&self) -> bool {
215+
match self {
216+
MemAccessType::Read => false,
217+
_ => true,
218+
}
219+
}
195220
}
196221

197222
struct ChildListener {
@@ -249,8 +274,8 @@ impl Iterator for ChildListener {
249274
/// created before the fork are the same).
250275
fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
251276
// Things that we return to the child process
252-
let mut accesses: Vec<(usize, usize, MemAccessType)> = vec![];
253-
let mut mappings: Vec<(usize, usize)> = vec![];
277+
let mut accesses: Vec<(u64, u64, MemAccessType)> = vec![];
278+
let mut mappings: Vec<(u64, u64)> = vec![];
254279

255280
// Memory allocated on the MiriMachine
256281
let mut ch_pages = vec![];
@@ -329,7 +354,7 @@ fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
329354
#[expect(clippy::as_conversions)]
330355
if regs.retval() as isize > 0 {
331356
let addr = regs.retval();
332-
mappings.push((addr, len));
357+
mappings.push((addr.to_u64(), len.to_u64()));
333358
}
334359
}
335360
Err(ret) => {
@@ -484,12 +509,12 @@ fn wait_for_syscall(pid: unistd::Pid, syscall: i64) -> Result<libc::user_regs_st
484509
fn handle_munmap(
485510
pid: unistd::Pid,
486511
regs: libc::user_regs_struct,
487-
mappings: &mut Vec<(usize, usize)>,
512+
mappings: &mut Vec<(u64, u64)>,
488513
) -> Result<(), i32> {
489514
// The unmap call might hit multiple mappings we've saved,
490515
// or overlap with them partially (or both)
491-
let um_start = regs.arg1();
492-
let um_len = regs.arg2();
516+
let um_start = regs.arg1().to_u64();
517+
let um_len = regs.arg2().to_u64();
493518
let um_end = um_start.strict_add(um_len);
494519
let mut idxes = vec![];
495520
for (idx, &(mp_start, len)) in mappings.iter().enumerate() {
@@ -536,11 +561,11 @@ fn handle_munmap(
536561

537562
fn handle_segfault(
538563
pid: unistd::Pid,
539-
ch_pages: &[usize],
540-
accesses: &mut Vec<(usize, usize, MemAccessType)>,
564+
ch_pages: &[u64],
565+
accesses: &mut Vec<(u64, u64, MemAccessType)>,
541566
) -> Result<(), i32> {
542567
let siginfo = ptrace::getsiginfo(pid).unwrap();
543-
let addr = unsafe { siginfo.si_addr().addr() };
568+
let addr = unsafe { siginfo.si_addr().addr().to_u64() };
544569
let page_addr = addr.strict_sub(addr.strict_rem(unsafe { PAGE_SIZE }));
545570

546571
if ch_pages.contains(&page_addr) {
@@ -590,7 +615,7 @@ fn handle_segfault(
590615
let mut decoder = iced_x86::Decoder::new(BITS, instr.as_slice(), 0);
591616
let mut fac = iced_x86::InstructionInfoFactory::new();
592617
let instr = decoder.decode();
593-
let memsize = instr.op_code().memory_size().size();
618+
let memsize = instr.op_code().memory_size().size().to_u64();
594619
let mem = fac.info(&instr).used_memory();
595620
let acc = mem.iter().fold(None, |mut curr: Option<MemAccessType>, m| {
596621
if let Some(m) = match m.access() {
@@ -635,7 +660,7 @@ fn handle_segfault(
635660

636661
fn handle_sigtrap(
637662
pid: unistd::Pid,
638-
mappings: &mut Vec<(usize, usize)>,
663+
mappings: &mut Vec<(u64, u64)>,
639664
malloc_bytes: i64,
640665
realloc_bytes: i64,
641666
free_bytes: i64,
@@ -651,24 +676,28 @@ fn handle_sigtrap(
651676
let regs = ptrace::getregs(pid).unwrap();
652677
match regs.ip().strict_sub(1) {
653678
a if a == malloc_addr => {
654-
let size = regs.arg1(); // !
679+
let size = regs.arg1().to_u64(); // !
655680
let ptr = intercept_retptr(pid, regs, malloc_addr, malloc_bytes)?;
656-
mappings.push((ptr, size));
681+
if ptr > 0 {
682+
mappings.push((ptr as u64, size));
683+
}
657684
}
658685
a if a == realloc_addr => {
659-
let old_ptr = regs.arg1();
660-
let size = regs.arg2();
686+
let old_ptr = regs.arg1().to_u64();
687+
let size = regs.arg2().to_u64();
661688
let pos = mappings
662689
.iter()
663690
.position(|&(ptr, size)| ptr <= old_ptr && old_ptr < ptr.strict_add(size));
664691
if let Some(pos) = pos {
665692
let _ = mappings.remove(pos);
666693
}
667694
let ptr = intercept_retptr(pid, regs, realloc_addr, realloc_bytes)?;
668-
mappings.push((ptr, size));
695+
if ptr > 0 {
696+
mappings.push((ptr as u64, size));
697+
}
669698
}
670699
a if a == free_addr => {
671-
let old_ptr = regs.arg1();
700+
let old_ptr = regs.arg1().to_u64();
672701
//let size = regs.rdi;
673702
let pos = mappings
674703
.iter()
@@ -692,7 +721,7 @@ fn intercept_retptr(
692721
mut regs: libc::user_regs_struct,
693722
fn_addr: usize,
694723
fn_bytes: i64,
695-
) -> Result<usize, i32> {
724+
) -> Result<isize, i32> {
696725
// Outline:
697726
// - Move instr ptr back before the sigtrap happened
698727
// - Restore the function to what it's supposed to be
@@ -715,7 +744,8 @@ fn intercept_retptr(
715744

716745
// now we're getting the return hopefully
717746
let mut regs = ptrace::getregs(pid).unwrap();
718-
let ptr = regs.retval(); // !
747+
#[expect(clippy::as_conversions)]
748+
let ptr = regs.retval() as isize; // !
719749
regs.set_ip(regs.ip().strict_sub(1));
720750
ptrace::write(pid, std::ptr::without_provenance_mut(fn_addr), BREAKPT_INSTR).unwrap();
721751
ptrace::write(pid, std::ptr::without_provenance_mut(ret_addr), ret_bytes).unwrap();
@@ -729,7 +759,12 @@ fn intercept_retptr(
729759
// manually, so we *must not ever* unwind from it
730760
pub unsafe extern "C" fn mempr_off() {
731761
unsafe {
732-
if libc::mprotect(PAGE_ADDR, PAGE_SIZE, libc::PROT_READ | libc::PROT_WRITE) != 0 {
762+
if libc::mprotect(
763+
PAGE_ADDR,
764+
PAGE_SIZE.try_into().unwrap_unchecked(),
765+
libc::PROT_READ | libc::PROT_WRITE,
766+
) != 0
767+
{
733768
std::process::exit(-20);
734769
}
735770
// This might error e.g. if the next page is unallocated or not owned by us - that's fine.
@@ -748,7 +783,8 @@ pub unsafe extern "C" fn mempr_off() {
748783

749784
pub unsafe extern "C" fn mempr_on() {
750785
unsafe {
751-
if libc::mprotect(PAGE_ADDR, PAGE_SIZE, libc::PROT_NONE) != 0 {
786+
if libc::mprotect(PAGE_ADDR, PAGE_SIZE.try_into().unwrap_unchecked(), libc::PROT_NONE) != 0
787+
{
752788
std::process::exit(-22);
753789
}
754790
//let _ = libc::mprotect(PAGE_ADDR.wrapping_add(PAGE_SIZE), PAGE_SIZE, libc::PROT_NONE);

0 commit comments

Comments
 (0)