From 5b76c22ea722b8cba191db61809635cbdf53c7a6 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Mon, 5 Jul 2021 09:54:44 +0200 Subject: [PATCH] Cmplog routines mutator (#204) * save * routines in meta * execute passes * fix cmplog rtn pass * clippy --- libafl/src/mutators/token_mutations.rs | 22 +++++- libafl_cc/src/clang.rs | 3 + libafl_cc/src/cmplog-routines-pass.cc | 2 +- libafl_targets/src/cmplog.c | 1 + libafl_targets/src/cmplog.h | 8 +- libafl_targets/src/cmplog.rs | 105 +++++++++++++++---------- 6 files changed, 90 insertions(+), 51 deletions(-) diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 5223155a8e..87546850ab 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -443,9 +443,25 @@ where } } } - CmpValues::Bytes(_v) => { - // TODO - // buffer_copy(input.bytes_mut(), token, 0, off, len); + CmpValues::Bytes(v) => { + 'outer: for i in off..len { + let mut size = core::cmp::min(v.0.len(), len - i); + while size != 0 { + if v.0[0..size] == input.bytes()[i..i + size] { + buffer_copy(input.bytes_mut(), &v.1, 0, i, size); + break 'outer; + } + size -= 1; + } + size = core::cmp::min(v.1.len(), len - i); + while size != 0 { + if v.1[0..size] == input.bytes()[i..i + size] { + buffer_copy(input.bytes_mut(), &v.0, 0, i, size); + break 'outer; + } + size -= 1; + } + } } } diff --git a/libafl_cc/src/clang.rs b/libafl_cc/src/clang.rs index eb65e73b7d..4260320350 100644 --- a/libafl_cc/src/clang.rs +++ b/libafl_cc/src/clang.rs @@ -188,6 +188,9 @@ impl CompilerWrapper for ClangWrapper { args.push(self.wrapped_cc.clone()); } args.extend_from_slice(self.base_args.as_slice()); + if !self.passes.is_empty() { + args.push("-fno-experimental-new-pass-manager".into()); + } for pass in &self.passes { args.push("-Xclang".into()); args.push("-load".into()); diff --git a/libafl_cc/src/cmplog-routines-pass.cc b/libafl_cc/src/cmplog-routines-pass.cc index 0a0fbd2655..0570b8aff5 100644 --- a/libafl_cc/src/cmplog-routines-pass.cc +++ b/libafl_cc/src/cmplog-routines-pass.cc @@ -247,7 +247,7 @@ bool CmpLogRoutines::hookRtns(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - if (!isIgnoreFunction(&F)) continue; + if (isIgnoreFunction(&F)) continue; for (auto &BB : F) { diff --git a/libafl_targets/src/cmplog.c b/libafl_targets/src/cmplog.c index bdc1bc3587..b6ea283724 100644 --- a/libafl_targets/src/cmplog.c +++ b/libafl_targets/src/cmplog.c @@ -205,3 +205,4 @@ void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstri get_llvm_stdstring(stdstring2)); } + diff --git a/libafl_targets/src/cmplog.h b/libafl_targets/src/cmplog.h index 7807221f82..41c43a12e5 100644 --- a/libafl_targets/src/cmplog.h +++ b/libafl_targets/src/cmplog.h @@ -12,7 +12,7 @@ #define CMPLOG_RTN_LEN 32 -#define CMPLOG_MAP_RTN_H ((CMPLOG_MAP_H * sizeof(CmpLogOperands)) / sizeof(CmpLogRoutine)) +#define CMPLOG_MAP_RTN_H ((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine)) #define CMPLOG_KIND_INS 0 #define CMPLOG_KIND_RTN 1 @@ -23,10 +23,10 @@ typedef struct CmpLogHeader { uint8_t kind; } CmpLogHeader; -typedef struct CmpLogOperands { +typedef struct CmpLogInstruction { uint64_t v0; uint64_t v1; -} CmpLogOperands; +} CmpLogInstruction; typedef struct CmpLogRoutine { uint8_t v0[CMPLOG_RTN_LEN]; @@ -36,7 +36,7 @@ typedef struct CmpLogRoutine { typedef struct CmpLogMap { CmpLogHeader headers[CMPLOG_MAP_W]; union { - CmpLogOperands operands[CMPLOG_MAP_W][CMPLOG_MAP_H]; + CmpLogInstruction operands[CMPLOG_MAP_W][CMPLOG_MAP_H]; CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H]; } vals; } CmpLogMap; diff --git a/libafl_targets/src/cmplog.rs b/libafl_targets/src/cmplog.rs index 2a65fcfd7e..569aea3dea 100644 --- a/libafl_targets/src/cmplog.rs +++ b/libafl_targets/src/cmplog.rs @@ -13,6 +13,12 @@ use crate::{CMPLOG_MAP_H, CMPLOG_MAP_W}; /// The `CmpLog` map size pub const CMPLOG_MAP_SIZE: usize = CMPLOG_MAP_W * CMPLOG_MAP_H; +/// The size of a logged routine argument in bytes +pub const CMPLOG_RTN_LEN: usize = 32; + +pub const CMPLOG_MAP_RTN_H: usize = (CMPLOG_MAP_H * core::mem::size_of::()) + / core::mem::size_of::(); + /// `CmpLog` instruction kind pub const CMPLOG_KIND_INS: u8 = 0; /// `CmpLog` return kind @@ -30,26 +36,31 @@ pub struct CmpLogHeader { /// The operands logged during `CmpLog`. #[repr(C)] #[derive(Default, Debug, Clone, Copy)] -pub struct CmpLogOperands(u64, u64); +pub struct CmpLogInstruction(u64, u64); + +/// The routine arguments logged during `CmpLog`. +#[repr(C)] +#[derive(Default, Debug, Clone, Copy)] +pub struct CmpLogRoutine([u8; CMPLOG_RTN_LEN], [u8; CMPLOG_RTN_LEN]); + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CmpLogVals { + operands: [[CmpLogInstruction; CMPLOG_MAP_H]; CMPLOG_MAP_W], + routines: [[CmpLogRoutine; CMPLOG_MAP_RTN_H]; CMPLOG_MAP_W], +} /// A struct containing the `CmpLog` metadata for a `LibAFL` run. #[repr(C)] -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct CmpLogMap { headers: [CmpLogHeader; CMPLOG_MAP_W], - operands: [[CmpLogOperands; CMPLOG_MAP_H]; CMPLOG_MAP_W], + vals: CmpLogVals, } impl Default for CmpLogMap { fn default() -> Self { - Self { - headers: [CmpLogHeader { - hits: 0, - shape: 0, - kind: 0, - }; CMPLOG_MAP_W], - operands: [[CmpLogOperands(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W], - } + unsafe { core::mem::zeroed() } } } @@ -63,50 +74,56 @@ impl CmpMap for CmpLogMap { } fn usable_executions_for(&self, idx: usize) -> usize { - if self.executions_for(idx) < CMPLOG_MAP_H { + if self.headers[idx].kind == CMPLOG_KIND_INS { + if self.executions_for(idx) < CMPLOG_MAP_H { + self.executions_for(idx) + } else { + CMPLOG_MAP_H + } + } else if self.executions_for(idx) < CMPLOG_MAP_RTN_H { self.executions_for(idx) } else { - CMPLOG_MAP_H + CMPLOG_MAP_RTN_H } } fn values_of(&self, idx: usize, execution: usize) -> CmpValues { if self.headers[idx].kind == CMPLOG_KIND_INS { - match self.headers[idx].shape { - 1 => { - return CmpValues::U8(( - self.operands[idx][execution].0 as u8, - self.operands[idx][execution].1 as u8, - )) + unsafe { + match self.headers[idx].shape { + 1 => CmpValues::U8(( + self.vals.operands[idx][execution].0 as u8, + self.vals.operands[idx][execution].1 as u8, + )), + 2 => CmpValues::U16(( + self.vals.operands[idx][execution].0 as u16, + self.vals.operands[idx][execution].1 as u16, + )), + 4 => CmpValues::U32(( + self.vals.operands[idx][execution].0 as u32, + self.vals.operands[idx][execution].1 as u32, + )), + 8 => CmpValues::U64(( + self.vals.operands[idx][execution].0 as u64, + self.vals.operands[idx][execution].1 as u64, + )), + other => panic!("Invalid CmpLog shape {}", other), } - 2 => { - return CmpValues::U16(( - self.operands[idx][execution].0 as u16, - self.operands[idx][execution].1 as u16, - )) - } - 4 => { - return CmpValues::U32(( - self.operands[idx][execution].0 as u32, - self.operands[idx][execution].1 as u32, - )) - } - 8 => { - return CmpValues::U64(( - self.operands[idx][execution].0 as u64, - self.operands[idx][execution].1 as u64, - )) - } - _ => {} - }; + } + } else { + unsafe { + CmpValues::Bytes(( + self.vals.routines[idx][execution].0.to_vec(), + self.vals.routines[idx][execution].1.to_vec(), + )) + } } - // TODO bytes - CmpValues::Bytes((vec![], vec![])) } fn reset(&mut self) -> Result<(), Error> { + // For performance, we reset just the headers self.headers = unsafe { core::mem::zeroed() }; - // self.operands = unsafe { core::mem::zeroed() }; + // self.vals.operands = unsafe { core::mem::zeroed() }; Ok(()) } } @@ -119,7 +136,9 @@ pub static mut libafl_cmplog_map: CmpLogMap = CmpLogMap { shape: 0, kind: 0, }; CMPLOG_MAP_W], - operands: [[CmpLogOperands(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W], + vals: CmpLogVals { + operands: [[CmpLogInstruction(0, 0); CMPLOG_MAP_H]; CMPLOG_MAP_W], + }, }; pub use libafl_cmplog_map as CMPLOG_MAP;