Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce usage of libc #114

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<u64> = {
// 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;
};
Expand Down
40 changes: 26 additions & 14 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
// Copyright 2016 6WIND S.A. <[email protected]>
// (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;

Expand Down Expand Up @@ -931,10 +933,8 @@ impl JitCompiler {
let offset_loc = jump.offset_loc as i32 + std::mem::size_of::<i32>() 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::<i32>());
let offset_ptr = mem.contents.as_ptr().add(jump.offset_loc) as *mut u8;
ptr::copy_nonoverlapping(rel.cast::<u8>(), offset_ptr, std::mem::size_of::<i32>());
}
}
Ok(())
Expand All @@ -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<u32, ebpf::Helper>, use_mbuff: bool,
update_data_ptr: bool) -> Result<JitMemory<'a>, 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,
};

Expand Down Expand Up @@ -994,7 +1006,7 @@ impl<'a> IndexMut<usize> 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);
}
}
}
Expand Down
Loading