Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Refactor - JIT noop insertion (#584)
Browse files Browse the repository at this point in the history
* Uses the Uniform distribution type from rand for noop insertion instead of gen_range().

* Makes the ExhaustedTextSegment check more conservative.

* Makes cargo fmt happy.
  • Loading branch information
Lichtso authored Sep 5, 2024
1 parent 2d38c95 commit de52d05
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 18 deletions.
14 changes: 10 additions & 4 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ use rand::{thread_rng, Rng};
#[cfg(feature = "shuttle-test")]
use shuttle::rand::{thread_rng, Rng};

use rand::{rngs::SmallRng, SeedableRng};
use rand::{
distributions::{Distribution, Uniform},
rngs::SmallRng,
SeedableRng,
};
use std::{fmt::Debug, mem, ptr};

use crate::{
Expand Down Expand Up @@ -321,6 +325,7 @@ pub struct JitCompiler<'a, C: ContextObject> {
pc: usize,
last_instruction_meter_validation_pc: usize,
next_noop_insertion: u32,
noop_range: Uniform<u32>,
runtime_environment_key: i32,
diversification_rng: SmallRng,
stopwatch_is_active: bool,
Expand Down Expand Up @@ -372,6 +377,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
pc: 0,
last_instruction_meter_validation_pc: 0,
next_noop_insertion: if config.noop_instruction_rate == 0 { u32::MAX } else { diversification_rng.gen_range(0..config.noop_instruction_rate * 2) },
noop_range: Uniform::new_inclusive(0, config.noop_instruction_rate * 2),
runtime_environment_key,
diversification_rng,
stopwatch_is_active: false,
Expand All @@ -393,7 +399,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
self.emit_subroutines();

while self.pc * ebpf::INSN_SIZE < self.program.len() {
if self.offset_in_text_section + MAX_MACHINE_CODE_LENGTH_PER_INSTRUCTION > self.result.text_section.len() {
if self.offset_in_text_section + MAX_MACHINE_CODE_LENGTH_PER_INSTRUCTION * 2 >= self.result.text_section.len() {
return Err(EbpfError::ExhaustedTextSegment(self.pc));
}
let mut insn = ebpf::get_insn_unchecked(self.program, self.pc);
Expand Down Expand Up @@ -723,7 +729,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
}

// Bumper in case there was no final exit
if self.offset_in_text_section + MAX_MACHINE_CODE_LENGTH_PER_INSTRUCTION > self.result.text_section.len() {
if self.offset_in_text_section + MAX_MACHINE_CODE_LENGTH_PER_INSTRUCTION * 2 >= self.result.text_section.len() {
return Err(EbpfError::ExhaustedTextSegment(self.pc));
}
self.emit_validate_and_profile_instruction_count(true, Some(self.pc + 2));
Expand Down Expand Up @@ -786,7 +792,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
pub fn emit_ins(&mut self, instruction: X86Instruction) {
instruction.emit(self);
if self.next_noop_insertion == 0 {
self.next_noop_insertion = self.diversification_rng.gen_range(0..self.config.noop_instruction_rate * 2);
self.next_noop_insertion = self.noop_range.sample(&mut self.diversification_rng);
// X86Instruction::noop().emit(self)?;
self.emit::<u8>(0x90);
} else {
Expand Down
6 changes: 4 additions & 2 deletions src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ declare_builtin_function!(
);

declare_builtin_function!(
/// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C. See the GNU manual page (in
/// section 3) for `memfrob`. The memory is directly modified, and the syscall returns 0 in all
/// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C.
///
/// See the GNU manual page (in section 3) for `memfrob`.
/// The memory is directly modified, and the syscall returns 0 in all
/// cases. Arguments 3 to 5 are unused.
SyscallMemFrob,
fn rust(
Expand Down
13 changes: 1 addition & 12 deletions src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,7 @@
// the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This “verifier” performs simple checks when the eBPF program is loaded into the VM (before it is
//! interpreted or JIT-compiled). It has nothing to do with the much more elaborated verifier inside
//! Linux kernel. There is no verification regarding the program flow control (should be a Direct
//! Acyclic Graph) or the consistency for registers usage (the verifier of the kernel assigns types
//! to the registers and is much stricter).
//!
//! On the other hand, rbpf is not expected to run in kernel space.
//!
//! Improving the verifier would be nice, but this is not trivial (and Linux kernel is under GPL
//! license, so we cannot copy it).
//!
//! Contrary to the verifier of the Linux kernel, this one does not modify the bytecode at all.
//! Verifies that the bytecode is valid for the given config.
use crate::{
ebpf,
Expand Down

0 comments on commit de52d05

Please sign in to comment.