Allowlist and denylist for QEMU edges and cmps (#311)
* fix edges hashtable query bug in hook * fmt
This commit is contained in:
parent
90928d3d97
commit
f2929b8253
@ -301,7 +301,11 @@ fn fuzz(
|
|||||||
|
|
||||||
let executor = QemuExecutor::new(
|
let executor = QemuExecutor::new(
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(QemuEdgeCoverageHelper::new(), QemuCmpLogHelper::new(), QemuSnapshotHelper::new()),
|
tuple_list!(
|
||||||
|
QemuEdgeCoverageHelper::new(),
|
||||||
|
QemuCmpLogHelper::new(),
|
||||||
|
QemuSnapshotHelper::new()
|
||||||
|
),
|
||||||
tuple_list!(edges_observer, time_observer),
|
tuple_list!(edges_observer, time_observer),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ops::Range};
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::tuples::MatchFirstType, executors::ExitKind, inputs::Input, observers::ObserversTuple,
|
bolts::tuples::MatchFirstType, executors::ExitKind, inputs::Input, observers::ObserversTuple,
|
||||||
@ -84,12 +84,56 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QemuEdgeCoverageHelper {}
|
pub enum QemuInstrumentationFilter {
|
||||||
|
AllowList(Vec<Range<u64>>),
|
||||||
|
DenyList(Vec<Range<u64>>),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QemuInstrumentationFilter {
|
||||||
|
pub fn allowed(&self, addr: u64) -> bool {
|
||||||
|
match self {
|
||||||
|
QemuInstrumentationFilter::AllowList(l) => {
|
||||||
|
for rng in l {
|
||||||
|
if rng.contains(&addr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
QemuInstrumentationFilter::DenyList(l) => {
|
||||||
|
for rng in l {
|
||||||
|
if rng.contains(&addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
QemuInstrumentationFilter::None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct QemuEdgeCoverageHelper {
|
||||||
|
filter: QemuInstrumentationFilter,
|
||||||
|
}
|
||||||
|
|
||||||
impl QemuEdgeCoverageHelper {
|
impl QemuEdgeCoverageHelper {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {}
|
Self {
|
||||||
|
filter: QemuInstrumentationFilter::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self {
|
||||||
|
Self { filter }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn must_instrument(&self, addr: u64) -> bool {
|
||||||
|
self.filter.allowed(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,12 +153,26 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QemuCmpLogHelper {}
|
pub struct QemuCmpLogHelper {
|
||||||
|
filter: QemuInstrumentationFilter,
|
||||||
|
}
|
||||||
|
|
||||||
impl QemuCmpLogHelper {
|
impl QemuCmpLogHelper {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {}
|
Self {
|
||||||
|
filter: QemuInstrumentationFilter::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self {
|
||||||
|
Self { filter }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn must_instrument(&self, addr: u64) -> bool {
|
||||||
|
self.filter.allowed(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ pub use libafl_targets::{
|
|||||||
EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM,
|
EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::helpers::{QemuHelperTuple, QemuSnapshotHelper};
|
use crate::helpers::*;
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize)]
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
pub struct QemuEdgesMapMetadata {
|
pub struct QemuEdgesMapMetadata {
|
||||||
@ -56,14 +56,21 @@ fn hash_me(mut x: u64) -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_unique_edge_ids<I, QT, S>(
|
pub fn gen_unique_edge_ids<I, QT, S>(
|
||||||
_helpers: &mut QT,
|
helpers: &mut QT,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
src: u64,
|
src: u64,
|
||||||
dest: u64,
|
dest: u64,
|
||||||
) -> Option<u64>
|
) -> Option<u64>
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
|
I: Input,
|
||||||
|
QT: QemuHelperTuple<I, S>,
|
||||||
{
|
{
|
||||||
|
if let Some(h) = helpers.match_first_type::<QemuEdgeCoverageHelper>() {
|
||||||
|
if !h.must_instrument(src) && !h.must_instrument(dest) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
if state.metadata().get::<QemuEdgesMapMetadata>().is_none() {
|
if state.metadata().get::<QemuEdgesMapMetadata>().is_none() {
|
||||||
state.add_metadata(QemuEdgesMapMetadata::new());
|
state.add_metadata(QemuEdgesMapMetadata::new());
|
||||||
}
|
}
|
||||||
@ -71,11 +78,17 @@ where
|
|||||||
.metadata_mut()
|
.metadata_mut()
|
||||||
.get_mut::<QemuEdgesMapMetadata>()
|
.get_mut::<QemuEdgesMapMetadata>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let id = max(meta.current_id as usize, unsafe { MAX_EDGES_NUM });
|
|
||||||
if meta.map.contains_key(&(src, dest)) {
|
if meta.map.contains_key(&(src, dest)) {
|
||||||
Some(*meta.map.get(&(src, dest)).unwrap())
|
let id = *meta.map.get(&(src, dest)).unwrap();
|
||||||
|
let nxt = (id as usize + 1) & (EDGES_MAP_SIZE - 1);
|
||||||
|
unsafe {
|
||||||
|
MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt);
|
||||||
|
}
|
||||||
|
Some(id)
|
||||||
} else {
|
} else {
|
||||||
meta.current_id = ((id + 1) & (EDGES_MAP_SIZE - 1)) as u64;
|
let id = meta.current_id;
|
||||||
|
meta.map.insert((src, dest), id);
|
||||||
|
meta.current_id = (id + 1) & (EDGES_MAP_SIZE as u64 - 1);
|
||||||
unsafe {
|
unsafe {
|
||||||
MAX_EDGES_NUM = meta.current_id as usize;
|
MAX_EDGES_NUM = meta.current_id as usize;
|
||||||
}
|
}
|
||||||
@ -84,11 +97,20 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_hashed_edge_ids<I, QT, S>(
|
pub fn gen_hashed_edge_ids<I, QT, S>(
|
||||||
_helpers: &mut QT,
|
helpers: &mut QT,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
src: u64,
|
src: u64,
|
||||||
dest: u64,
|
dest: u64,
|
||||||
) -> Option<u64> {
|
) -> Option<u64>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
QT: QemuHelperTuple<I, S>,
|
||||||
|
{
|
||||||
|
if let Some(h) = helpers.match_first_type::<QemuEdgeCoverageHelper>() {
|
||||||
|
if !h.must_instrument(src) && !h.must_instrument(dest) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(hash_me(src) ^ hash_me(dest))
|
Some(hash_me(src) ^ hash_me(dest))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,14 +155,21 @@ pub extern "C" fn trace_block_transition_single(id: u64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_unique_cmp_ids<I, QT, S>(
|
pub fn gen_unique_cmp_ids<I, QT, S>(
|
||||||
_helpers: &mut QT,
|
helpers: &mut QT,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
pc: u64,
|
pc: u64,
|
||||||
_size: usize,
|
_size: usize,
|
||||||
) -> Option<u64>
|
) -> Option<u64>
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
|
I: Input,
|
||||||
|
QT: QemuHelperTuple<I, S>,
|
||||||
{
|
{
|
||||||
|
if let Some(h) = helpers.match_first_type::<QemuCmpLogHelper>() {
|
||||||
|
if !h.must_instrument(pc) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
if state.metadata().get::<QemuCmpsMapMetadata>().is_none() {
|
if state.metadata().get::<QemuCmpsMapMetadata>().is_none() {
|
||||||
state.add_metadata(QemuCmpsMapMetadata::new());
|
state.add_metadata(QemuCmpsMapMetadata::new());
|
||||||
}
|
}
|
||||||
@ -153,6 +182,7 @@ where
|
|||||||
Some(*meta.map.get(&pc).unwrap())
|
Some(*meta.map.get(&pc).unwrap())
|
||||||
} else {
|
} else {
|
||||||
meta.current_id = ((id + 1) & (CMPLOG_MAP_W - 1)) as u64;
|
meta.current_id = ((id + 1) & (CMPLOG_MAP_W - 1)) as u64;
|
||||||
|
meta.map.insert(pc, id as u64);
|
||||||
Some(id as u64)
|
Some(id as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user