detect job releases during race-conditions

This commit is contained in:
Alwin Berger 2024-08-29 11:24:32 +02:00
parent 2c00f82d39
commit a613a803ca
3 changed files with 56 additions and 7 deletions

View File

@ -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() };

View File

@ -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 {

View File

@ -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");