1 #include "smatch.h"
   2 #include "linearize.h"
   3 
   4 static int my_id;
   5 static struct symbol *cur_syscall;
   6 
   7 static const char *expression_type_name(enum expression_type type)
   8 {
   9         static const char *expression_type_name[] = {
  10                 [EXPR_VALUE] = "EXPR_VALUE",
  11                 [EXPR_STRING] = "EXPR_STRING",
  12                 [EXPR_SYMBOL] = "EXPR_SYMBOL",
  13                 [EXPR_TYPE] = "EXPR_TYPE",
  14                 [EXPR_BINOP] = "EXPR_BINOP",
  15                 [EXPR_ASSIGNMENT] = "EXPR_ASSIGNMENT",
  16                 [EXPR_LOGICAL] = "EXPR_LOGICAL",
  17                 [EXPR_DEREF] = "EXPR_DEREF",
  18                 [EXPR_PREOP] = "EXPR_PREOP",
  19                 [EXPR_POSTOP] = "EXPR_POSTOP",
  20                 [EXPR_CAST] = "EXPR_CAST",
  21                 [EXPR_FORCE_CAST] = "EXPR_FORCE_CAST",
  22                 [EXPR_IMPLIED_CAST] = "EXPR_IMPLIED_CAST",
  23                 [EXPR_SIZEOF] = "EXPR_SIZEOF",
  24                 [EXPR_ALIGNOF] = "EXPR_ALIGNOF",
  25                 [EXPR_PTRSIZEOF] = "EXPR_PTRSIZEOF",
  26                 [EXPR_CONDITIONAL] = "EXPR_CONDITIONAL",
  27                 [EXPR_SELECT] = "EXPR_SELECT",
  28                 [EXPR_STATEMENT] = "EXPR_STATEMENT",
  29                 [EXPR_CALL] = "EXPR_CALL",
  30                 [EXPR_COMMA] = "EXPR_COMMA",
  31                 [EXPR_COMPARE] = "EXPR_COMPARE",
  32                 [EXPR_LABEL] = "EXPR_LABEL",
  33                 [EXPR_INITIALIZER] = "EXPR_INITIALIZER",
  34                 [EXPR_IDENTIFIER] = "EXPR_IDENTIFIER",
  35                 [EXPR_INDEX] = "EXPR_INDEX",
  36                 [EXPR_POS] = "EXPR_POS",
  37                 [EXPR_FVALUE] = "EXPR_FVALUE",
  38                 [EXPR_SLICE] = "EXPR_SLICE",
  39                 [EXPR_OFFSETOF] = "EXPR_OFFSETOF",
  40         };
  41         return expression_type_name[type] ?: "UNKNOWN_EXPRESSION_TYPE";
  42 }
  43 
  44 static inline void prefix() {
  45         printf("%s:%d %s() ", get_filename(), get_lineno(), get_function());
  46 }
  47 
  48 static void match_syscall_definition(struct symbol *sym)
  49 {
  50         // struct symbol *arg;
  51         char *macro;
  52         char *name;
  53         int is_syscall = 0;
  54 
  55         macro = get_macro_name(sym->pos);
  56         if (macro &&
  57             (strncmp("SYSCALL_DEFINE", macro, strlen("SYSCALL_DEFINE")) == 0 ||
  58              strncmp("COMPAT_SYSCALL_DEFINE", macro, strlen("COMPAT_SYSCALL_DEFINE")) == 0))
  59                 is_syscall = 1;
  60 
  61         name = get_function();
  62         
  63         /* 
  64         if (!option_no_db && get_state(my_id, "this_function", NULL) != &called) {
  65                 if (name && strncmp(name, "sys_", 4) == 0)
  66                         is_syscall = 1;
  67         }
  68         */
  69 
  70         /* Ignore compat_sys b/c syzkaller doesn't fuzz these?
  71         if (name && strncmp(name, "compat_sys_", 11) == 0)
  72                 is_syscall = 1;
  73         */
  74 
  75         if (!is_syscall)
  76                 return;
  77         printf("-------------------------\n");  
  78         printf("\nsyscall found: %s at: ", name);
  79         prefix(); printf("\n");
  80         cur_syscall = sym;
  81 
  82         /*
  83         FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
  84                 set_state(my_id, arg->ident->name, arg, &user_data_set);
  85         } END_FOR_EACH_PTR(arg);
  86         */
  87 }
  88 
  89 static void match_after_syscall(struct symbol *sym) {
  90     if (cur_syscall && sym == cur_syscall) {
  91         printf("\n"); prefix();
  92         printf("exiting scope of syscall %s\n", get_function());
  93         printf("-------------------------\n");  
  94         cur_syscall = NULL;
  95     }
  96 }
  97 
  98 static void print_member_type(struct expression *expr)
  99 {
 100         char *member;
 101 
 102         member = get_member_name(expr);
 103         if (!member)
 104                 return;
 105         // sm_msg("info: uses %s", member);
 106         prefix();
 107         printf("info: uses %s\n", member);
 108         free_string(member);
 109 }
 110 
 111 static void match_condition(struct expression *expr) {
 112     if (!cur_syscall)
 113         return;
 114     
 115     /*
 116     prefix();
 117     printf("found conditional %s on line %d\n", expression_type_name(expr->type), get_lineno());
 118     printf("expr_str: %s\n", expr_to_str(expr));
 119     */
 120 
 121     /* 
 122     switch (expr->type) {
 123         case EXPR_COMPARE:
 124             match_condition(expr->left);
 125             match_condition(expr->right);
 126             break;
 127         case EXPR_SYMBOL:
 128             printf("symbol: %s\n", expr->symbol_name->name);
 129             break;
 130         case EXPR_CALL:
 131             break;
 132     }
 133     */
 134 
 135     prefix(); printf("-- condition found\n");
 136 
 137     if (expr->type == EXPR_COMPARE || expr->type == EXPR_BINOP
 138             || expr->type == EXPR_LOGICAL
 139             || expr->type == EXPR_ASSIGNMENT
 140             || expr->type == EXPR_COMMA) {
 141             match_condition(expr->left);
 142             match_condition(expr->right);
 143             return;
 144     }
 145     print_member_type(expr);
 146 
 147 }
 148 
 149 static void match_function_call(struct expression *expr) {
 150     if (!cur_syscall)
 151         return;
 152     prefix();
 153     printf("function call %s\n", expression_type_name(expr->type)); 
 154 }
 155 
 156 void check_implicit_dependencies_tester(int id)
 157 {
 158     my_id = id;
 159 
 160     if (option_project != PROJ_KERNEL)
 161         return;
 162 
 163     add_hook(&match_syscall_definition, AFTER_DEF_HOOK);
 164     add_hook(&match_after_syscall, AFTER_FUNC_HOOK);
 165     add_hook(&match_condition, CONDITION_HOOK);
 166     add_hook(&match_function_call, FUNCTION_CALL_HOOK);
 167 }
 168