diff --git a/src/helpers.rs b/src/helpers.rs index c93497f4..ad4f00c4 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -16,9 +16,6 @@ //! value. Hence some helpers have unused arguments, or return a 0 value in all cases, in order to //! respect this convention. -#[cfg(feature = "std")] -extern crate libc; - use crate::lib::*; // Helpers associated to kernel helpers @@ -243,30 +240,39 @@ pub fn strcmp (arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u /// Returns a random u64 value comprised between `min` and `max` values (inclusive). Arguments 3 to /// 5 are unused. /// -/// Relies on `rand()` function from libc, so `libc::srand()` should be called once before this -/// helper is used. -/// -/// # Examples -/// -/// ``` -/// extern crate libc; -/// extern crate rbpf; -/// extern crate time; -/// -/// unsafe { -/// libc::srand(time::precise_time_ns() as u32) -/// } -/// -/// let n = rbpf::helpers::rand(3, 6, 0, 0, 0); -/// assert!(3 <= n && n <= 6); -/// ``` +/// This does not rely on `libc::rand()` and therefore can be called without `libc::srand()`. #[allow(dead_code)] #[allow(unused_variables)] #[cfg(feature = "std")] pub fn rand (min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 { - let mut n = unsafe { - (libc::rand() as u64).wrapping_shl(32) + libc::rand() as u64 - }; + use std::cell::Cell; + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + use std::thread; + use std::time::Instant; + + // Constants for WyRand taken from: https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h#L151 + const WY_CONST_0: u64 = 0x2d35_8dcc_aa6c_78a5; + const WY_CONST_1: u64 = 0x8bb8_4b93_962e_acc9; + + std::thread_local! { + static RNG: Cell = { + // Seed the RNG with the thread ID and the current time. + let mut hasher = DefaultHasher::new(); + Instant::now().hash(&mut hasher); + thread::current().id().hash(&mut hasher); + Cell::new(hasher.finish()) + }; + } + + // Run one round of WyRand. + let mut n = RNG.with(|rng| { + let s = rng.get().wrapping_add(WY_CONST_0); + rng.set(s); + let t = u128::from(s) * u128::from(s ^ WY_CONST_1); + (t as u64) ^ (t >> 64) as u64 + }); + if min < max { n = n % (max + 1 - min) + min; }; diff --git a/src/jit.rs b/src/jit.rs index a472b77f..21aa0d69 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -5,12 +5,14 @@ // Copyright 2016 6WIND S.A. // (Translation to Rust, MetaBuff addition) +use std::alloc; use std::mem; use std::collections::HashMap; use std::fmt::Formatter; use std::fmt::Error as FormatterError; use std::io::{Error, ErrorKind}; use std::ops::{Index, IndexMut}; +use std::ptr; use ebpf; @@ -931,10 +933,8 @@ impl JitCompiler { let offset_loc = jump.offset_loc as i32 + std::mem::size_of::() as i32; let rel = &(target_loc as i32 - offset_loc) as *const i32; - let offset_ptr = mem.contents.as_ptr().add(jump.offset_loc); - - libc::memcpy(offset_ptr as *mut libc::c_void, rel as *const libc::c_void, - std::mem::size_of::()); + let offset_ptr = mem.contents.as_ptr().add(jump.offset_loc) as *mut u8; + ptr::copy_nonoverlapping(rel.cast::(), offset_ptr, std::mem::size_of::()); } } Ok(()) @@ -943,25 +943,37 @@ impl JitCompiler { pub struct JitMemory<'a> { contents: &'a mut [u8], + layout: alloc::Layout, offset: usize, } impl<'a> JitMemory<'a> { pub fn new(prog: &[u8], helpers: &HashMap, use_mbuff: bool, update_data_ptr: bool) -> Result, Error> { - let contents: &mut[u8]; - let mut raw: mem::MaybeUninit<*mut libc::c_void> = mem::MaybeUninit::uninit(); - unsafe { + let layout; + + // Allocate the appropriately sized memory. + let contents = unsafe { + // Create a layout with the proper size and alignment. let size = NUM_PAGES * PAGE_SIZE; - libc::posix_memalign(raw.as_mut_ptr(), PAGE_SIZE, size); - libc::mprotect(*raw.as_mut_ptr(), size, libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE); - std::ptr::write_bytes(*raw.as_mut_ptr(), 0xc3, size); // for now, prepopulate with 'RET' calls - contents = std::slice::from_raw_parts_mut(*raw.as_mut_ptr() as *mut u8, NUM_PAGES * PAGE_SIZE); - raw.assume_init(); - } + layout = alloc::Layout::from_size_align_unchecked(size, PAGE_SIZE); + + // Allocate the region of memory. + let ptr = alloc::alloc(layout); + if ptr.is_null() { + return Err(Error::from(std::io::ErrorKind::OutOfMemory)); + } + + // Protect it. + libc::mprotect(ptr.cast(), size, libc::PROT_EXEC | libc::PROT_WRITE); + + // Convert to a slice. + std::slice::from_raw_parts_mut(ptr, size) + }; let mut mem = JitMemory { contents, + layout, offset: 0, }; @@ -994,7 +1006,7 @@ impl<'a> IndexMut for JitMemory<'a> { impl<'a> Drop for JitMemory<'a> { fn drop(&mut self) { unsafe { - libc::free(self.contents.as_mut_ptr() as *mut libc::c_void); + alloc::dealloc(self.contents.as_mut_ptr(), self.layout); } } }