detect job releases during race-conditions
This commit is contained in:
parent
2c00f82d39
commit
a613a803ca
@ -206,7 +206,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> freertos::List_t {
|
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> (freertos::List_t, bool) {
|
||||||
let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target);
|
let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target);
|
||||||
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
|
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &liba
|
|||||||
eprintln!("Warning: attempted to read a list that is being modified");
|
eprintln!("Warning: attempted to read a list that is being modified");
|
||||||
let mut read=read;
|
let mut read=read;
|
||||||
read.uxNumberOfItems = 0;
|
read.uxNumberOfItems = 0;
|
||||||
return read;
|
return (read, false);
|
||||||
}
|
}
|
||||||
// assert_eq!(next_item.pvContainer,target);
|
// assert_eq!(next_item.pvContainer,target);
|
||||||
let new_next_index=next_item.pxNext;
|
let new_next_index=next_item.pxNext;
|
||||||
@ -241,7 +241,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &liba
|
|||||||
let next_item : freertos::MiniListItem_t = freertos::emu_lookup::lookup(emulator, next_index);
|
let next_item : freertos::MiniListItem_t = freertos::emu_lookup::lookup(emulator, next_index);
|
||||||
systemstate.dumping_ground.insert(next_index,List_MiniItem_struct(next_item));
|
systemstate.dumping_ground.insert(next_index,List_MiniItem_struct(next_item));
|
||||||
}
|
}
|
||||||
return read;
|
return (read, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -300,18 +300,31 @@ fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr)
|
|||||||
// Extract delay list
|
// Extract delay list
|
||||||
let mut target : GuestAddr = h.delay_queue;
|
let mut target : GuestAddr = h.delay_queue;
|
||||||
target = freertos::emu_lookup::lookup(emulator, target);
|
target = freertos::emu_lookup::lookup(emulator, target);
|
||||||
systemstate.delay_list = read_freertos_list(&mut systemstate, emulator, target);
|
let _temp = read_freertos_list(&mut systemstate, emulator, target);
|
||||||
|
systemstate.delay_list = _temp.0;
|
||||||
|
systemstate.read_invalid |= !_temp.1;
|
||||||
|
|
||||||
// Extract delay list overflow
|
// Extract delay list overflow
|
||||||
let mut target : GuestAddr = h.delay_queue_overflow;
|
let mut target : GuestAddr = h.delay_queue_overflow;
|
||||||
target = freertos::emu_lookup::lookup(emulator, target);
|
target = freertos::emu_lookup::lookup(emulator, target);
|
||||||
systemstate.delay_list_overflow = read_freertos_list(&mut systemstate, emulator, target);
|
let _temp = read_freertos_list(&mut systemstate, emulator, target);
|
||||||
|
systemstate.delay_list_overflow = _temp.0;
|
||||||
|
systemstate.read_invalid |= !_temp.1;
|
||||||
|
|
||||||
|
// Extract suspended tasks (infinite wait), seems broken, always appreas to be modified
|
||||||
|
// let mut target : GuestAddr = h.suspended_queue;
|
||||||
|
// target = freertos::emu_lookup::lookup(emulator, target);
|
||||||
|
// systemstate.suspended_list = read_freertos_list(&mut systemstate, emulator, target);
|
||||||
|
|
||||||
// Extract priority lists
|
// Extract priority lists
|
||||||
for i in 0..NUM_PRIOS {
|
for i in 0..NUM_PRIOS {
|
||||||
let target : GuestAddr = listbytes*GuestAddr::try_from(i).unwrap()+h.ready_queues;
|
let target : GuestAddr = listbytes*GuestAddr::try_from(i).unwrap()+h.ready_queues;
|
||||||
systemstate.prio_ready_lists[i] = read_freertos_list(&mut systemstate, emulator, target);
|
let _temp = read_freertos_list(&mut systemstate, emulator, target);
|
||||||
|
systemstate.prio_ready_lists[i] = _temp.0;
|
||||||
|
systemstate.read_invalid |= !_temp.1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
systemstate.read_invalid = true;
|
||||||
}
|
}
|
||||||
systemstate.mem_reads = unsafe { MEM_READ.take().unwrap_or_default() };
|
systemstate.mem_reads = unsafe { MEM_READ.take().unwrap_or_default() };
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ pub struct RawFreeRTOSSystemState {
|
|||||||
delay_list: freertos::List_t,
|
delay_list: freertos::List_t,
|
||||||
delay_list_overflow: freertos::List_t,
|
delay_list_overflow: freertos::List_t,
|
||||||
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
||||||
|
read_invalid: bool,
|
||||||
input_counter: u32,
|
input_counter: u32,
|
||||||
edge: (GuestAddr,GuestAddr),
|
edge: (GuestAddr,GuestAddr),
|
||||||
capture_point: (CaptureEvent,String),
|
capture_point: (CaptureEvent,String),
|
||||||
@ -125,6 +126,7 @@ pub struct ReducedFreeRTOSSystemState {
|
|||||||
pub current_task: RefinedTCB,
|
pub current_task: RefinedTCB,
|
||||||
ready_list_after: Vec<RefinedTCB>,
|
ready_list_after: Vec<RefinedTCB>,
|
||||||
delay_list_after: Vec<RefinedTCB>,
|
delay_list_after: Vec<RefinedTCB>,
|
||||||
|
read_invalid: bool,
|
||||||
// edge: (Option<GuestAddr>,Option<GuestAddr>),
|
// edge: (Option<GuestAddr>,Option<GuestAddr>),
|
||||||
// pub capture_point: (CaptureEvent,String),
|
// pub capture_point: (CaptureEvent,String),
|
||||||
// input_counter: u32
|
// input_counter: u32
|
||||||
@ -132,7 +134,7 @@ pub struct ReducedFreeRTOSSystemState {
|
|||||||
impl PartialEq for ReducedFreeRTOSSystemState {
|
impl PartialEq for ReducedFreeRTOSSystemState {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.current_task == other.current_task && self.ready_list_after == other.ready_list_after &&
|
self.current_task == other.current_task && self.ready_list_after == other.ready_list_after &&
|
||||||
self.delay_list_after == other.delay_list_after
|
self.delay_list_after == other.delay_list_after && self.read_invalid == other.read_invalid
|
||||||
// && self.edge == other.edge
|
// && self.edge == other.edge
|
||||||
// && self.capture_point == other.capture_point
|
// && self.capture_point == other.capture_point
|
||||||
}
|
}
|
||||||
@ -143,6 +145,7 @@ impl Hash for ReducedFreeRTOSSystemState {
|
|||||||
self.current_task.hash(state);
|
self.current_task.hash(state);
|
||||||
self.ready_list_after.hash(state);
|
self.ready_list_after.hash(state);
|
||||||
self.delay_list_after.hash(state);
|
self.delay_list_after.hash(state);
|
||||||
|
self.read_invalid.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ReducedFreeRTOSSystemState {
|
impl ReducedFreeRTOSSystemState {
|
||||||
|
@ -211,6 +211,7 @@ fn refine_system_states(mut input: Vec<RawFreeRTOSSystemState>) -> (Vec<ReducedF
|
|||||||
current_task: cur,
|
current_task: cur,
|
||||||
ready_list_after: collector,
|
ready_list_after: collector,
|
||||||
delay_list_after: delay_list,
|
delay_list_after: delay_list,
|
||||||
|
read_invalid: i.read_invalid,
|
||||||
// input_counter: i.input_counter,//+IRQ_INPUT_BYTES_NUMBER,
|
// input_counter: i.input_counter,//+IRQ_INPUT_BYTES_NUMBER,
|
||||||
});
|
});
|
||||||
ret.1.push((i.qemu_tick, i.capture_point.0, i.capture_point.1.to_string(), i.edge, i.mem_reads));
|
ret.1.push((i.qemu_tick, i.capture_point.0, i.capture_point.1.to_string(), i.edge, i.mem_reads));
|
||||||
@ -233,6 +234,38 @@ fn get_releases(trace: &Vec<ExecInterval>, states: &HashMap<u64, ReducedFreeRTOS
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if i.start_capture.0 == CaptureEvent::ISRStart && ( i.start_capture.1 == "xPortSysTickHandler" || i.start_capture.1 == "isr_starter" ) {
|
if i.start_capture.0 == CaptureEvent::ISRStart && ( i.start_capture.1 == "xPortSysTickHandler" || i.start_capture.1 == "isr_starter" ) {
|
||||||
|
// detect race-conditions, get start adn end state from the nearest valid intervals
|
||||||
|
if states.get(&i.start_state).map(|x| x.read_invalid).unwrap_or(true) {
|
||||||
|
let mut start_index=None;
|
||||||
|
for n in 1.._n {
|
||||||
|
if let Some(interval_start) = trace.get(_n-n) {
|
||||||
|
let start_state = states.get(&interval_start.start_state).unwrap();
|
||||||
|
if !start_state.read_invalid {
|
||||||
|
start_index = Some(_n-n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {break;}
|
||||||
|
};
|
||||||
|
let mut end_index=None;
|
||||||
|
for n in (_n+1)..trace.len() {
|
||||||
|
if let Some(interval_end) = trace.get(n) {
|
||||||
|
let end_state = states.get(&interval_end.end_state).unwrap();
|
||||||
|
if !end_state.read_invalid {
|
||||||
|
end_index = Some(n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {break;}
|
||||||
|
};
|
||||||
|
if let Some(Some(start_state)) = start_index.map(|x| states.get(&trace[x].start_state)) {
|
||||||
|
if let Some(Some(end_state)) = end_index.map(|x| states.get(&trace[x].end_state)) {
|
||||||
|
end_state.ready_list_after.iter().for_each(|x| {
|
||||||
|
if x.task_name != end_state.current_task.task_name && x.task_name != start_state.current_task.task_name && !start_state.ready_list_after.iter().any(|y| x.task_name == y.task_name) {
|
||||||
|
ret.push((i.end_tick, x.task_name.clone()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
if i.end_capture.0 == CaptureEvent::ISREnd {
|
if i.end_capture.0 == CaptureEvent::ISREnd {
|
||||||
let start_state = states.get(&i.start_state).expect("State not found");
|
let start_state = states.get(&i.start_state).expect("State not found");
|
||||||
let end_state = states.get(&i.end_state).expect("State not found");
|
let end_state = states.get(&i.end_state).expect("State not found");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user