Skip to content

Commit

Permalink
Make Verifier Restriction on MUL64_IMM Configurable (#201)
Browse files Browse the repository at this point in the history
* Passes the config to the executable verifier.

* Adds the "verify_mul64_imm_nonzero" config flag.
  • Loading branch information
Lichtso authored Jul 19, 2021
1 parent 38ba6a5 commit 99d5591
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 9 deletions.
10 changes: 7 additions & 3 deletions src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//!
//! Contrary to the verifier of the Linux kernel, this one does not modify the bytecode at all.
use crate::ebpf;
use crate::{ebpf, vm::Config};
use thiserror::Error;

/// Error definitions
Expand Down Expand Up @@ -173,7 +173,7 @@ fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Verifier

/// Check the program against the verifier's rules
#[rustfmt::skip]
pub fn check(prog: &[u8]) -> Result<(), VerifierError> {
pub fn check(prog: &[u8], config: &Config) -> Result<(), VerifierError> {
check_prog_len(prog)?;

let mut insn_ptr: usize = 0;
Expand Down Expand Up @@ -250,7 +250,11 @@ pub fn check(prog: &[u8]) -> Result<(), VerifierError> {
ebpf::ADD64_REG => {},
ebpf::SUB64_IMM => {},
ebpf::SUB64_REG => {},
ebpf::MUL64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MUL64_IMM => {
if config.verify_mul64_imm_nonzero {
check_imm_nonzero(&insn, insn_ptr)?;
}
},
ebpf::MUL64_REG => {},
ebpf::DIV64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::DIV64_REG => {},
Expand Down
11 changes: 7 additions & 4 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use std::{
/// - Unknown instructions.
/// - Bad formed instruction.
/// - Unknown eBPF syscall index.
pub type Verifier = fn(prog: &[u8]) -> Result<(), VerifierError>;
pub type Verifier = fn(prog: &[u8], config: &Config) -> Result<(), VerifierError>;

/// Return value of programs and syscalls
pub type ProgramResult<E> = Result<u64, EbpfError<E>>;
Expand Down Expand Up @@ -193,6 +193,8 @@ pub struct Config {
pub sanitize_user_provided_values: bool,
/// Encrypt the environment registers in JIT
pub encrypt_environment_registers: bool,
/// Feature flag for the MUL64_IMM != 0 verification check
pub verify_mul64_imm_nonzero: bool,
}
impl Default for Config {
fn default() -> Self {
Expand All @@ -206,6 +208,7 @@ impl Default for Config {
noop_instruction_ratio: 1.0 / 256.0,
sanitize_user_provided_values: true,
encrypt_environment_registers: true,
verify_mul64_imm_nonzero: false,
}
}
}
Expand Down Expand Up @@ -252,9 +255,9 @@ impl<E: UserDefinedError, I: 'static + InstructionMeter> dyn Executable<E, I> {
syscall_registry: SyscallRegistry,
) -> Result<Box<Self>, EbpfError<E>> {
let ebpf_elf = EBpfElf::load(config, elf_bytes, syscall_registry)?;
let (_, bytes) = ebpf_elf.get_text_bytes()?;
let text_bytes = ebpf_elf.get_text_bytes()?.1;
if let Some(verifier) = verifier {
verifier(bytes)?;
verifier(text_bytes, &config)?;
}
Ok(Box::new(ebpf_elf))
}
Expand All @@ -267,7 +270,7 @@ impl<E: UserDefinedError, I: 'static + InstructionMeter> dyn Executable<E, I> {
bpf_functions: BTreeMap<u32, (usize, String)>,
) -> Result<Box<Self>, EbpfError<E>> {
if let Some(verifier) = verifier {
verifier(text_bytes).map_err(EbpfError::VerifierError)?;
verifier(text_bytes, &config).map_err(EbpfError::VerifierError)?;
}
Ok(Box::new(EBpfElf::new_from_text_bytes(
config,
Expand Down
4 changes: 2 additions & 2 deletions tests/ubpf_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn test_verifier_success() {
"
mov32 r0, 0xBEE
exit",
Some(|_prog: &[u8]| Ok(())),
Some(|_prog: &[u8], _config: &Config| Ok(())),
Config::default(),
SyscallRegistry::default(),
)
Expand All @@ -58,7 +58,7 @@ fn test_verifier_success() {
#[test]
#[should_panic(expected = "NoProgram")]
fn test_verifier_fail() {
fn verifier_fail(_prog: &[u8]) -> Result<(), VerifierError> {
fn verifier_fail(_prog: &[u8], _config: &Config) -> Result<(), VerifierError> {
Err(VerifierError::NoProgram)
}
let _executable = assemble::<UserError, DefaultInstructionMeter>(
Expand Down

0 comments on commit 99d5591

Please sign in to comment.