X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=contrib%2Ffsm_checker%2FFD_CHECK%2Ffd_checker.c;fp=contrib%2Ffsm_checker%2FFD_CHECK%2Ffd_checker.c;h=f026d62996972065f5174e62a4acf942a0b74020;hb=e09e518ebf18d490dbeb72c6358968af7d05d675;hp=0000000000000000000000000000000000000000;hpb=58f53b56557577b64911d0e7a2bba3fbb521d71d;p=lttv.git diff --git a/contrib/fsm_checker/FD_CHECK/fd_checker.c b/contrib/fsm_checker/FD_CHECK/fd_checker.c new file mode 100755 index 00000000..f026d629 --- /dev/null +++ b/contrib/fsm_checker/FD_CHECK/fd_checker.c @@ -0,0 +1,310 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fd.h" + +GArray *_fsm_list; +GArray * _fsms_to_remove; +struct timeval *tv1, *tv2; +int max_fsms = 0; +int total_forks = 0; +int count_events = 0; +int skip=0; + +static gboolean fs_close(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + struct marker_field *f = lttv_trace_get_hook_field(th, 0); + guint32 fd = ltt_event_get_long_unsigned(e, f); + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + //initialize a new finite state machine + struct fd *fdstruct = fd_Init(); + total_forks++; + //add new fsm to list + g_array_append_val(_fsm_list, fdstruct); + //call corresponding transition + fdContext_fs_close(&(fdstruct->_fsm), pid, fd); + + if(max_fsms<_fsm_list->len) + max_fsms=_fsm_list->len; + return FALSE; + +} + +static gboolean fs_open(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + struct marker_field *f = lttv_trace_get_hook_field(th, 0); + guint32 fd = ltt_event_get_long_unsigned(e, f); + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + //for every fsm in the list, call appropriate transition + //index i is sent as an argument in case fsm is to be freed + struct fd *fdstruct; + int i; + for(i=_fsm_list->len-1; i>=0; i--){ + if (skip) + break; + fdstruct = (struct fd *) g_array_index(_fsm_list, struct fdstruct *, i); + fdContext_fs_open(&(fdstruct->_fsm), pid, fd, i); + } + skip=0; + return FALSE; +} + +static gboolean fs_read(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + struct marker_field *f = lttv_trace_get_hook_field(th, 0); + guint32 fd = ltt_event_get_long_unsigned(e, f); + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + LttTime time = ltt_event_time(e); + long ts_nsec, ts_sec; + ts_sec = (long) time.tv_sec; + ts_nsec=(long) time.tv_nsec; + + //for every fsm in the list, call appropriate transition + struct fd *fdstruct; + int i; + for(i=0; i<_fsm_list->len; i++){ + if (skip) + break; + fdstruct = (struct fd *)g_array_index(_fsm_list, struct fd *, i); + fdContext_fs_read(&(fdstruct->_fsm), pid, fd, ts_sec, ts_nsec); + } + + skip=0; + return FALSE; +} +static gboolean fs_write(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + struct marker_field *f = lttv_trace_get_hook_field(th, 0); + guint32 fd = ltt_event_get_long_unsigned(e, f); + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + //for every fsm in the list, call appropriate transition + struct fd *fdstruct; + int i; + for(i=0; i<_fsm_list->len; i++){ + if (skip) + break; + fdstruct = g_array_index(_fsm_list, struct fd *, i); + fdContext_fs_write(&(fdstruct->_fsm), pid, fd); + } + skip=0; + return FALSE; +} +static gboolean process_exit(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + + //for every fsm in the list, call appropriate transition + struct fd *fdstruct; + int i; + for(i=_fsm_list->len-1; i>=0 ; i--){ + fdstruct =(struct fd *) g_array_index(_fsm_list, struct fd *, i); + fdContext_process_exit(&(fdstruct->_fsm), pid, i); + } + skip=0; + return FALSE; +} +static gboolean fs_dup3(void *hook_data, void *call_data){ + count_events++; + LttvTracefileState *s = (LttvTracefileState *) call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHook *th = (LttvTraceHook *)hook_data; + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context; + LttvProcessState *process = ts->running_process[tfs->cpu]; + int pid=process->pid; + + struct marker_field *f = lttv_trace_get_hook_field(th, 1); + guint32 newfd = ltt_event_get_long_unsigned(e, f); + + //for every fsm in the list, call appropriate transition + struct fd *fdstruct; + int i; + for(i=_fsm_list->len-1; i>=0; i--){ + if (skip) + break; + fdstruct =(struct fd *) g_array_index(_fsm_list, struct fd *, i); + fdContext_fs_dup3(&(fdstruct->_fsm), pid, newfd, i); + } + skip=0; + return FALSE; + +} + +void skip_FSM(){ + skip=1; +} + +int removefsm(int i){ + g_array_remove_index(_fsm_list, i); + } +static int add_events_by_id_hooks(void *hook_data, void *call_data){ + LttvTraceContext *tc = (LttvTraceContext *) call_data; + LttTrace *t = tc->t; + + //EVENT CHROOT + GQuark LTT_FACILITY_FS = g_quark_from_string("fs"); + GQuark LTT_FACILITY_KERNEL = g_quark_from_string("kernel"); + + GQuark LTT_EVENT_CLOSE = g_quark_from_string("close"); + //EVENT FIELDS + GQuark LTT_FIELD_FD = g_quark_from_string("fd"); + GQuark LTT_FIELD_OLD_FD = g_quark_from_string("oldfd"); + GQuark LTT_FIELD_NEW_FD = g_quark_from_string("newfd"); + + GQuark LTT_EVENT_OPEN = g_quark_from_string("open"); + + GQuark LTT_EVENT_READ = g_quark_from_string("read"); + + GQuark LTT_EVENT_WRITE = g_quark_from_string("write"); + + GQuark LTT_EVENT_DUP3 = g_quark_from_string("dup3"); + + GQuark LTT_EVENT_PROCESS_EXIT = g_quark_from_string("process_exit"); + + GArray *hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 6); + + lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_CLOSE, + FIELD_ARRAY(LTT_FIELD_FD), + fs_close, + NULL, + &hooks); + + lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_OPEN, + FIELD_ARRAY(LTT_FIELD_FD), + fs_open, + NULL, + &hooks); + + lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_READ, + FIELD_ARRAY(LTT_FIELD_FD), + fs_read, + NULL, + &hooks); + + + lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_WRITE, + FIELD_ARRAY(LTT_FIELD_FD), + fs_write, + NULL, + &hooks); + + lttv_trace_find_hook(t, LTT_FACILITY_KERNEL, LTT_EVENT_PROCESS_EXIT, + NULL, + process_exit, + NULL, + &hooks); + + lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_DUP3, + FIELD_ARRAY(LTT_FIELD_OLD_FD, LTT_FIELD_NEW_FD), + fs_dup3, + NULL, + &hooks); + + int nb_tracefiles = tc->tracefiles->len; + LttvTracefileContext **tfc; + LttvHooks *needed_hooks; + LttvTraceHook *th = (LttvTraceHook *)hook_data; + int i, j; + for(i=0; itracefiles, LttvTracefileContext*, i); + for(j=0; jlen; j++){ + th=&g_array_index(hooks, LttvTraceHook, j); + needed_hooks = lttv_hooks_by_id_find((*tfc)->event_by_id, th->id); + lttv_hooks_add(needed_hooks, th->h, th, LTTV_PRIO_DEFAULT); + } + } +} +static void init(){ + + gboolean result; + + LttvAttributeValue value; + + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); + + static LttvHooks *before_trace; + + result = lttv_iattribute_find_by_path(attributes, "hooks/trace/before", LTTV_POINTER, &value); + g_assert(result); + before_trace = *(value.v_pointer); + g_assert(before_trace); + + //Register add_events_by_id_hook to be called before starting to read the trace + //This function will be overwritten between checkers + lttv_hooks_add(before_trace, add_events_by_id_hooks, NULL, LTTV_PRIO_DEFAULT); + + //Initialize empty GArray for FSMs + _fsm_list = g_array_new(FALSE, FALSE, sizeof(struct fd *)); + + tv1 = (struct timeval *)malloc(sizeof(struct timeval)); + gettimeofday(tv1, NULL); +} +static void destroy(){ + tv2 = (struct timeval *)malloc(sizeof(struct timeval)); + gettimeofday(tv2, NULL); + int seconds = tv2->tv_sec - tv1->tv_sec; + printf("analysis took: %d seconds \n", seconds); + printf("total number of coexisting fsms is: %d\n",max_fsms); + printf("total number of forked fsms is: %d\n", total_forks); + printf("size of one fsm (in bytes) is: %d\n", sizeof(struct fd)); + printf("total number of pertinent events is %d\n", count_events); + +} + +LTTV_MODULE("fd_checker", "Detects improper fd usage", + "finds read/write access to a closed fd in a trace file", + init, destroy, "stats", "batchAnalysis", "option")