cleanup timeout_detection

This commit is contained in:
Steffen Schulz 2022-05-01 18:37:44 -07:00 committed by Sergej Schumilo
parent a2ee5ef587
commit 35809c5207
3 changed files with 78 additions and 133 deletions

View File

@ -2451,9 +2451,7 @@ int kvm_cpu_exec(CPUState *cpu)
smp_rmb();
#ifdef QEMU_NYX
if(arm_sigprof_timer(&GET_GLOBAL_STATE()->timeout_detector)){
assert(false);
}
arm_sigprof_timer(&GET_GLOBAL_STATE()->timeout_detector);
#endif
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);

View File

@ -26,138 +26,103 @@ volatile bool synchronization_reload_pending = false;
volatile bool synchronization_kvm_loop_waiting = false;
/* new SIGALRM based timeout detection */
/* SIGALRM based timeout detection */
//#define DEBUG_TIMEOUT_DETECTOR
void init_timeout_detector(timeout_detector_t* timer){
timer->kvm_tid = 0;
timer->detection_enabled = false;
void init_timeout_detector(timeout_detector_t* timeout_detector){
timeout_detector->kvm_tid = 0;
timeout_detector->reload_pending = false;
timeout_detector->detection_enabled = false;
timer->config.tv_sec = 0;
timer->config.tv_usec = 0;
timeout_detector->timeout_sec = 0;
timeout_detector->timeout_usec = 0; /* default: disabled */
timeout_detector->arm_timeout.it_interval.tv_sec = 0;
timeout_detector->arm_timeout.it_interval.tv_usec = 0;
timeout_detector->arm_timeout.it_value.tv_sec = 0;
timeout_detector->arm_timeout.it_value.tv_usec = 0;
timeout_detector->disarm_timeout.it_interval.tv_sec = 0;
timeout_detector->disarm_timeout.it_interval.tv_usec = 0;
timeout_detector->arm_timeout.it_value.tv_sec = timeout_detector->timeout_sec;
timeout_detector->arm_timeout.it_value.tv_usec = timeout_detector->timeout_usec;
timer->alarm.it_interval.tv_sec = 0;
timer->alarm.it_interval.tv_usec = 0;
timer->alarm.it_value.tv_sec = 0;
timer->alarm.it_value.tv_usec = 0;
}
static void sigalarm_handler(int signum) {
/* ensure that SIGALARM is ALWAYS handled by kvm thread */
assert(GET_GLOBAL_STATE()->timeout_detector.kvm_tid == syscall(SYS_gettid));
//GET_GLOBAL_STATE()->timeout_detector.reload_pending = true;
/* ensure that SIGALARM is ALWAYS handled by kvm thread */
assert(GET_GLOBAL_STATE()->timeout_detector.kvm_tid == syscall(SYS_gettid));
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "Handled! %d %ld\n", signum, syscall(SYS_gettid));
#endif
//fprintf(stderr, "Handled! %d %ld\n", signum, syscall(SYS_gettid));
}
void install_timeout_detector(timeout_detector_t* timeout_detector){
timeout_detector->kvm_tid = syscall(SYS_gettid);
if(signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
fprintf(stderr, "%s failed!\n", __func__);
assert(false);
}
//fprintf(stderr, "SIGALRM HANDLER INSTALLED! %ld\n", syscall(SYS_gettid));
}
void reset_timeout_detector(timeout_detector_t* timeout_detector){
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "%s!\n", __func__);
#endif
timeout_detector->reload_pending = false;
if(timeout_detector->timeout_sec || timeout_detector->timeout_usec){
timeout_detector->arm_timeout.it_value.tv_sec = timeout_detector->timeout_sec;
timeout_detector->arm_timeout.it_value.tv_usec = timeout_detector->timeout_usec;
timeout_detector->detection_enabled = true;
void install_timeout_detector(timeout_detector_t* timer){
timer->kvm_tid = syscall(SYS_gettid);
if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
fprintf(stderr, "%s failed!\n", __func__);
assert(false);
}
else{
timeout_detector->detection_enabled = false;
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "SIGALRM HANDLER INSTALLED! tid=%ld\n", syscall(SYS_gettid));
#endif
}
void reset_timeout_detector(timeout_detector_t* timer){
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "%s!\n", __func__);
#endif
if (timer->config.tv_sec || timer->config.tv_usec) {
timer->alarm.it_value.tv_sec = timer->config.tv_sec;
timer->alarm.it_value.tv_usec = timer->config.tv_usec;
timer->detection_enabled = true;
} else {
timer->detection_enabled = false;
}
}
void enable_timeout_detector(timeout_detector_t* timeout_detector){
timeout_detector->detection_enabled = true;
}
/*
static void disable_timeout_detector(timeout_detector_t* timeout_detector){
timeout_detector->detection_enabled = false;
struct itimerval tmp;
timeout_detector->disarm_timeout.it_interval.tv_sec = 0;
timeout_detector->disarm_timeout.it_interval.tv_usec = 0;
assert(setitimer(ITIMER_REAL, &timeout_detector->disarm_timeout, &tmp) == 0);
}
*/
void update_itimer(timeout_detector_t* timeout_detector, uint8_t sec, uint32_t usec){
void update_itimer(timeout_detector_t* timer, uint8_t sec, uint32_t usec)
{
#ifdef DEBUG_TIMEOUT_DETECTOR
//fprintf(stderr, "%s: %x %x\n", __func__, sec, usec);
if(sec || usec){
timeout_detector->timeout_sec = (time_t) sec;
timeout_detector->timeout_usec = (suseconds_t) usec;
timeout_detector->detection_enabled = true;
}
else{
timeout_detector->detection_enabled = false;
#endif
if (sec || usec) {
timer->config.tv_sec = (time_t)sec;
timer->config.tv_usec = (suseconds_t)usec;
timer->detection_enabled = true;
} else {
timer->detection_enabled = false;
}
}
bool arm_sigprof_timer(timeout_detector_t* timeout_detector){
//return false;
if(timeout_detector->detection_enabled){
if(timeout_detector->reload_pending || (!timeout_detector->arm_timeout.it_value.tv_sec && !timeout_detector->arm_timeout.it_value.tv_usec)){
//assert(false);
fprintf(stderr, "TIMER EXPIRED 1! %d %ld %ld\n", timeout_detector->reload_pending, timeout_detector->arm_timeout.it_value.tv_sec, timeout_detector->arm_timeout.it_value.tv_usec);
reset_timeout_detector(timeout_detector);
/* TODO: check if this function still works as expected even if we don't return at this point */
//return true;
}
void arm_sigprof_timer(timeout_detector_t* timer){
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "%s (%ld %ld)\n", __func__, timeout_detector->arm_timeout.it_value.tv_sec, timeout_detector->arm_timeout.it_value.tv_usec);
fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec, timer->alarm.it_value.tv_usec);
#endif
timeout_detector->arm_timeout.it_interval.tv_sec = 0;
timeout_detector->arm_timeout.it_interval.tv_usec = 0;
assert(setitimer(ITIMER_REAL, &timeout_detector->arm_timeout, 0) == 0);
}
return false;
if (timer->detection_enabled) {
if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
fprintf(stderr, "Attempting to re-arm an expired timer! => reset(%ld.%ld)\n",
timer->config.tv_sec, timer->config.tv_usec);
reset_timeout_detector(timer);
//return true;
}
assert(setitimer(ITIMER_REAL, &timer->alarm, NULL) == 0);
}
}
bool disarm_sigprof_timer(timeout_detector_t* timeout_detector){
//return false;
struct itimerval tmp;
if(timeout_detector->detection_enabled){
timeout_detector->disarm_timeout.it_interval.tv_sec = 0;
timeout_detector->disarm_timeout.it_interval.tv_usec = 0;
assert(setitimer(ITIMER_REAL, &timeout_detector->disarm_timeout, &tmp) == 0);
timeout_detector->arm_timeout.it_value.tv_sec = tmp.it_value.tv_sec;
timeout_detector->arm_timeout.it_value.tv_usec = tmp.it_value.tv_usec;
bool disarm_sigprof_timer(timeout_detector_t* timer){
#ifdef DEBUG_TIMEOUT_DETECTOR
fprintf(stderr, "%s (%ld %ld)\n", __func__, timeout_detector->arm_timeout.it_value.tv_sec, timeout_detector->arm_timeout.it_value.tv_usec);
fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec, timer->alarm.it_value.tv_usec);
#endif
if(timeout_detector->reload_pending || (!timeout_detector->arm_timeout.it_value.tv_sec && !timeout_detector->arm_timeout.it_value.tv_usec)){
//fprintf(stderr, "TIMER EXPIRED 2! %d %d %d\n", timeout_detector->reload_pending, timeout_detector->arm_timeout.it_value.tv_sec, timeout_detector->arm_timeout.it_value.tv_usec);
reset_timeout_detector(timeout_detector);
//timeout_detector->detection_enabled = false;
return true;
}
}
return false;
if (timer->detection_enabled) {
struct itimerval disable = {0};
assert(setitimer(ITIMER_REAL, &disable, &timer->alarm) == 0);
assert(timer->alarm.it_interval.tv_usec == 0);
if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
reset_timeout_detector(timer);
return true;
}
}
return false;
}
void block_signals(void){
@ -264,16 +229,10 @@ void synchronization_lock(void){
runtime_usec = timer.config.tv_usec - timer.alarm.it_value.tv_usec + 1000000;
}
set_exec_done_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
runtime_sec, runtime_usec,
GET_GLOBAL_STATE()->num_dirty_pages);
/*
if(last_timeout){
reset_timeout_detector_timeout(&(GET_GLOBAL_STATE()->timeout_detector));
}
else{
*/
runtime_sec, runtime_usec,
GET_GLOBAL_STATE()->num_dirty_pages);
reset_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
//}
if(synchronization_check_page_not_found()){
set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 0);
@ -480,6 +439,5 @@ void synchronization_enter_fuzzing_loop(CPUState *cpu){
in_fuzzing_loop = true;
reset_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
//enable_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
}

View File

@ -3,27 +3,19 @@
#include "qemu/osdep.h"
#include <linux/kvm.h>
typedef struct timeout_detector_s{
typedef struct timeout_detector_s {
int kvm_tid;
volatile bool reload_pending;
volatile bool detection_enabled;
time_t timeout_sec;
suseconds_t timeout_usec;
struct itimerval arm_timeout;
struct itimerval disarm_timeout;
struct timespec start_time;
struct timespec end_time;
struct timeval config;
struct itimerval alarm;
} timeout_detector_t;
void init_timeout_detector(timeout_detector_t* timeout_detector);
void install_timeout_detector(timeout_detector_t* timeout_detector);
void reset_timeout_detector(timeout_detector_t* timeout_detector);
bool arm_sigprof_timer(timeout_detector_t* timeout_detector);
void arm_sigprof_timer(timeout_detector_t* timeout_detector);
bool disarm_sigprof_timer(timeout_detector_t* timeout_detector);
void update_itimer(timeout_detector_t* timeout_detector, uint8_t sec, uint32_t usec);
void block_signals(void);
@ -44,6 +36,3 @@ void synchronization_cow_full_detected(void);
void synchronization_disable_pt(CPUState *cpu);
void synchronization_enter_fuzzing_loop(CPUState *cpu);
void synchronization_payload_buffer_write_detected(void);
void enable_timeout_detector(timeout_detector_t* timeout_detector);
void reset_timeout_detector_timeout(timeout_detector_t* timeout_detector);