From 206d45b8231cb0568223458f6a86c5e048c082a3 Mon Sep 17 00:00:00 2001 From: Guillume DIDIER Date: Wed, 20 Oct 2021 13:57:57 +0200 Subject: [PATCH] Finish the function placement module (IP tool) --- basic_timing_cache_channel/src/lib.rs | 4 +- cache_utils/src/bin/l3.rs | 2 +- cache_utils/src/bin/two_thread_cal.rs | 8 +- cache_utils/src/main.rs | 2 +- cache_utils/src/mmap.rs | 18 ++++- covert_channels_evaluation/src/lib.rs | 2 +- prefetcher_reverse/src/ip_tool.rs | 105 +++++++++++++++++++++++--- prefetcher_reverse/src/lib.rs | 3 +- 8 files changed, 121 insertions(+), 23 deletions(-) diff --git a/basic_timing_cache_channel/src/lib.rs b/basic_timing_cache_channel/src/lib.rs index 3d7f2c1..3b8486c 100644 --- a/basic_timing_cache_channel/src/lib.rs +++ b/basic_timing_cache_channel/src/lib.rs @@ -303,7 +303,7 @@ impl TopologyAwareTimingChannel { core_pairs: impl Iterator + Clone, strat: CalibrationStrategy, ) -> Result<(Self, usize, usize), TopologyAwareError> { - let m = MMappedMemory::new(PAGE_LEN, false, |i| i as u8); + let m = MMappedMemory::new(PAGE_LEN, false, false, |i| i as u8); let array: &[u8] = m.slice(); let t = Default::default(); @@ -429,7 +429,7 @@ impl TopologyAwareTimingChannel { )? } ThresholdStrat::AV(_) | ThresholdStrat::AVSockets(_) => { - let m = MMappedMemory::new(PAGE_LEN, false, |i| i as u8); + let m = MMappedMemory::new(PAGE_LEN, false, false, |i| i as u8); let array: &[u8] = m.slice(); let mut hashset = HashSet::new(); hashset.insert(array); diff --git a/cache_utils/src/bin/l3.rs b/cache_utils/src/bin/l3.rs index b9311d3..7bcbdb8 100644 --- a/cache_utils/src/bin/l3.rs +++ b/cache_utils/src/bin/l3.rs @@ -4,7 +4,7 @@ use cache_utils::flush; use cache_utils::mmap::MMappedMemory; pub fn main() { - let m = MMappedMemory::new(2 << 20, true, |i| i as u8); + let m = MMappedMemory::new(2 << 20, true, false, |i| i as u8); let array = m.slice(); loop { unsafe { diff --git a/cache_utils/src/bin/two_thread_cal.rs b/cache_utils/src/bin/two_thread_cal.rs index 6790a01..8015811 100644 --- a/cache_utils/src/bin/two_thread_cal.rs +++ b/cache_utils/src/bin/two_thread_cal.rs @@ -111,7 +111,7 @@ fn main() { println!("Number of cores per socket: {}", core_per_socket); - let m = MMappedMemory::new(SIZE, true, |i: usize| i as u8); + let m = MMappedMemory::new(SIZE, true, false, |i: usize| i as u8); let array = m.slice(); let cache_line_size = 64; @@ -147,7 +147,7 @@ fn main() { display_name: "clflush remote hit", t: &(), }, -/* CalibrateOperation2T { + /* CalibrateOperation2T { prepare: maccess::, op: load_and_flush_wrap, name: "clflush_shared_hit", @@ -175,7 +175,7 @@ fn main() { display_name: "clflush miss - n", t: &(), }, -/* CalibrateOperation2T { + /* CalibrateOperation2T { prepare: noop::, op: load_and_flush_wrap, name: "clflush_local_hit_n", @@ -298,7 +298,7 @@ fn main() { Err(e) => panic!("Error: {}", e), }; -/* asvp_analysis[&ASVP { + /* asvp_analysis[&ASVP { attacker: 0, slice: 0, victim: 0, diff --git a/cache_utils/src/main.rs b/cache_utils/src/main.rs index e938589..977d31d 100644 --- a/cache_utils/src/main.rs +++ b/cache_utils/src/main.rs @@ -33,7 +33,7 @@ struct Page { } */ pub fn main() { - let m = MMappedMemory::new(SIZE, true, |i| i as u8); + let m = MMappedMemory::new(SIZE, true, false, |i| i as u8); let array = m.slice(); let old = sched_getaffinity(Pid::from_raw(0)).unwrap(); diff --git a/cache_utils/src/mmap.rs b/cache_utils/src/mmap.rs index fa307a5..da5e005 100644 --- a/cache_utils/src/mmap.rs +++ b/cache_utils/src/mmap.rs @@ -30,6 +30,7 @@ impl MMappedMemory { pub fn try_new( size: usize, huge: bool, + executable: bool, initializer: impl Fn(usize) -> T, ) -> Result, nix::Error> { assert_ne!(size_of::(), 0); @@ -37,7 +38,13 @@ impl MMappedMemory { let p = mman::mmap( null_mut(), size * size_of::(), - mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE, + mman::ProtFlags::PROT_READ + | mman::ProtFlags::PROT_WRITE + | if executable { + mman::ProtFlags::PROT_EXEC + } else { + mman::ProtFlags::PROT_READ + }, mman::MapFlags::MAP_PRIVATE | mman::MapFlags::MAP_ANONYMOUS | if huge { @@ -91,8 +98,13 @@ impl MMappedMemory { } } */ - pub fn new(size: usize, huge: bool, init: impl Fn(usize) -> T) -> MMappedMemory { - Self::try_new(size, huge, init).unwrap() + pub fn new( + size: usize, + huge: bool, + executable: bool, + init: impl Fn(usize) -> T, + ) -> MMappedMemory { + Self::try_new(size, huge, executable, init).unwrap() } pub fn slice(&self) -> &[T] { diff --git a/covert_channels_evaluation/src/lib.rs b/covert_channels_evaluation/src/lib.rs index 6240dac..c1881d7 100644 --- a/covert_channels_evaluation/src/lib.rs +++ b/covert_channels_evaluation/src/lib.rs @@ -165,7 +165,7 @@ pub fn benchmark_channel( let old_affinity = set_affinity(&channel.main_core()).unwrap(); let size = num_pages * PAGE_SIZE; - let mut m = MMappedMemory::new(size, false, |i| (i / PAGE_SIZE) as u8); + let mut m = MMappedMemory::new(size, false, false, |i| (i / PAGE_SIZE) as u8); let mut receiver_turn_handles = Vec::new(); let mut transmit_turn_handles = Vec::new(); diff --git a/prefetcher_reverse/src/ip_tool.rs b/prefetcher_reverse/src/ip_tool.rs index dcbf0f8..48a5b62 100644 --- a/prefetcher_reverse/src/ip_tool.rs +++ b/prefetcher_reverse/src/ip_tool.rs @@ -62,14 +62,19 @@ impl WXRange { mask: usize, round_mask: usize, ) -> Result<*mut u8, ()> { - // In each range, we want to find base = 2^a * k such that start <= base + align < start + 2^a + // In each range, we want to find base = 2^a * k such that start <= base + offset < start + 2^a // This can be done with k = ceil(start - align / 2^a). // 2^a * k can likely be computed with some clever bit tricks. // \o/ let start = self.start; - let mut candidate = (start - offset + mask) & round_mask + offset; + println!( + "offset: {:x}, align: {:x}, start: {:x}, mask {:x}, round_mask {:x}", + offset, align, start, mask, round_mask + ); + + let mut candidate = ((start - offset + mask) & round_mask) + offset; assert_eq!(candidate & mask, offset); - assert!(candidate > start); + assert!(candidate >= start); while candidate + length <= self.end { let bit_range = &mut self.bitmap[(candidate - start)..(candidate - start + length)]; if !bit_range.any() { @@ -80,6 +85,14 @@ impl WXRange { } Err(()) } + + unsafe fn deallocate(&mut self, p: *const u8, size: usize) { + let offset = p as usize - self.start; + if !self.bitmap[offset..(offset + size)].all() { + panic!("deallocating invalid data"); + } + self.bitmap[offset..(offset + size)].set_all(false); + } } impl WXAllocator { @@ -94,13 +107,73 @@ impl WXAllocator { } let mask = align - 1; let round_mask = !mask; - for range in self.ranges.iter_mut() { - if let Ok(p) = unsafe { range.allocate(align, offset, length, mask, round_mask) } { - return Ok(p); + loop { + for range in self.ranges.iter_mut() { + if let Ok(p) = unsafe { range.allocate(align, offset, length, mask, round_mask) } { + return Ok(p); + } + } + const PAGE_SIZE: usize = 1 << 12; + let size = (length + PAGE_SIZE - 1) & !(PAGE_SIZE - 1); + let new_page = MMappedMemory::try_new(size, false, true, |size| 0xcc as u8); + match new_page { + Err(_) => return Err(()), + Ok(new_page) => { + let start = &new_page.slice()[0] as *const u8 as usize; + let end = start + new_page.len() - 1; + let mut cursor = self.ranges.cursor_front_mut(); + loop { + if let Some(current) = cursor.current() { + if current.end == start { + current.end = end; + current.bitmap.append(&mut bitvec![0; end - start]); + current.pages.push(new_page); + break; + } + if current.start < start { + cursor.move_next() + } else { + if end == current.start { + current.start = start; + let mut bitmap = bitvec![0; end - start]; + bitmap.append(&mut current.bitmap); + current.bitmap = bitmap; + let mut pages = vec![new_page]; + pages.append(&mut current.pages); + current.pages = pages; + break; + } else { + cursor.insert_before(WXRange { + start, + end, + bitmap: bitvec![0;end-start], + pages: vec![new_page], + }); + break; + } + } + } else { + cursor.insert_before(WXRange { + start, + end, + bitmap: bitvec![0;end-start], + pages: vec![new_page], + }); + break; + } + } + } + } + } + } + + pub unsafe fn deallocate(&mut self, p: *const u8, size: usize) { + let start = p as usize; + for range in self.ranges.iter_mut() { + if range.start <= start && start + size - 1 <= range.end { + unsafe { range.deallocate(p, size) }; } } - // Now we need to allocate a new page ^^' - return Err(()); } } @@ -116,7 +189,10 @@ impl Function { return Err(()); // FIXME Error type. } let mask = align - 1; - let real_offset = (offset - (template.ip as usize) + (template.start as usize)) & mask; + let real_offset = (offset + .wrapping_add(template.start as usize) + .wrapping_sub(template.ip as usize)) + & mask; let length = (template.end as usize) - (template.start as usize); let p = unsafe { allocator.allocate(align, real_offset, length) }?; @@ -136,7 +212,10 @@ impl Function { impl Drop for Function { fn drop(&mut self) { // Find the correct range, and deallocate all the bits - todo!() + let p = self.fun as *mut u8; + unsafe { std::ptr::write_bytes(p, 0xcc, self.size) }; + let mut allocator = wx_allocator.lock().unwrap(); + unsafe { allocator.deallocate(self.fun as *const u8, self.size) }; } } @@ -213,4 +292,10 @@ pub fn tmp_test() { let p = &mem as *const u8; println!("maccess {:p} : {}", p, unsafe { timed_maccess_template(p) }); println!("clflush {:p} : {}", p, unsafe { timed_clflush_template(p) }); + + let f = Function::try_new(1, 0, TIMED_CLFLUSH).unwrap(); + + println!("{:p}", f.fun as *const u8); + let r = unsafe { (f.fun)(p) }; + println!("relocate clflush {:p}, {}", (f.fun) as *const u8, r); } diff --git a/prefetcher_reverse/src/lib.rs b/prefetcher_reverse/src/lib.rs index 4706ace..d28bb85 100644 --- a/prefetcher_reverse/src/lib.rs +++ b/prefetcher_reverse/src/lib.rs @@ -1,4 +1,5 @@ #![feature(global_asm)] +#![feature(linked_list_cursors)] #![deny(unsafe_op_in_unsafe_fn)] use crate::Probe::{Flush, FullFlush, Load}; @@ -171,7 +172,7 @@ impl Prober { }; for i in 0..num_pages { - let mut p = match MMappedMemory::::try_new(PAGE_LEN * GS, false, |j| { + let mut p = match MMappedMemory::::try_new(PAGE_LEN * GS, false, false, |j| { (j / CACHE_LINE_LEN + i * PAGE_CACHELINE_LEN) as u8 }) { Ok(p) => p,