1 /* 2 * Copyright (C) 2017 Oracle. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 16 */ 17 18 /* 19 * This is to help create Trinity fuzzer templates. 20 * 21 */ 22 23 #include "smatch.h" 24 #include "smatch_slist.h" 25 26 static int my_id; 27 28 STATE(ARG_FD); 29 #if 0 30 STATE(arg_range); 31 STATE(arg_op); 32 STATE(arg_list); 33 STATE(arg_cpu); 34 STATE(arg_pathname); 35 #endif 36 // nr_segs * sizeof(struct iovec) 37 // if (nr_segs > UIO_MAXIOV) 38 #if 0 39 STATE(arg_ioveclen); 40 STATE(arg_sockaddrlen); 41 STATE(arg_socketinfo); 42 #endif 43 44 struct smatch_state *merge_states(struct smatch_state *s1, struct smatch_state *s2) 45 { 46 if (s1 == &undefined) 47 return s2; 48 return s1; 49 } 50 51 struct typedef_lookup { 52 const char *name; 53 struct symbol *sym; 54 int failed; 55 }; 56 57 static struct symbol *_typedef_lookup(const char *name) 58 { 59 struct ident *id; 60 struct symbol *node; 61 62 id = built_in_ident(name); 63 if (!id) 64 return NULL; 65 node = lookup_symbol(id, NS_TYPEDEF); 66 if (!node || node->type != SYM_NODE) 67 return NULL; 68 return get_real_base_type(node); 69 } 70 71 static void typedef_lookup(struct typedef_lookup *tl) 72 { 73 if (tl->sym || tl->failed) 74 return; 75 tl->sym = _typedef_lookup(tl->name); 76 if (!tl->sym) 77 tl->failed = 1; 78 } 79 80 static int is_mode_t(struct symbol *sym) 81 { 82 static struct typedef_lookup umode_t = { .name = "umode_t" }; 83 struct symbol *type; 84 85 typedef_lookup(&umode_t); 86 if (!umode_t.sym) 87 return 0; 88 type = get_base_type(sym); 89 if (type == umode_t.sym) 90 return 1; 91 return 0; 92 } 93 94 static int is_pid_t(struct symbol *sym) 95 { 96 static struct typedef_lookup pid_t = { .name = "pid_t" }; 97 struct symbol *type; 98 99 typedef_lookup(&pid_t); 100 if (!pid_t.sym) 101 return 0; 102 type = get_base_type(sym); 103 if (type == pid_t.sym) 104 return 1; 105 return 0; 106 } 107 108 static const char *get_arg_type_from_type(struct symbol *sym) 109 { 110 struct symbol *type; 111 112 if (is_mode_t(sym)) 113 return "ARG_MODE_T"; 114 if (is_pid_t(sym)) 115 return "ARG_PID"; 116 117 type = get_real_base_type(sym); 118 if (!type || type->type != SYM_PTR) 119 return NULL; 120 type = get_real_base_type(type); 121 if (!type) 122 return NULL; 123 if (type == &char_ctype) 124 return "ARG_MMAP"; 125 if (!type->ident) 126 return NULL; 127 if (strcmp(type->ident->name, "iovec") == 0) 128 return "ARG_IOVEC"; 129 if (strcmp(type->ident->name, "sockaddr") == 0) 130 return "ARG_SOCKADDR"; 131 return "ARG_ADDRESS"; 132 } 133 134 static void match_fdget(const char *fn, struct expression *expr, void *unused) 135 { 136 struct expression *arg; 137 138 arg = get_argument_from_call_expr(expr->args, 0); 139 set_state_expr(my_id, arg, &ARG_FD); 140 } 141 142 const char *get_syscall_arg_type(struct symbol *sym) 143 { 144 struct smatch_state *state; 145 const char *type; 146 147 if (!sym || !sym->ident) 148 return "ARG_UNDEFINED"; 149 type = get_arg_type_from_type(sym); 150 if (type) 151 return type; 152 state = get_state(my_id, sym->ident->name, sym); 153 if (!state) 154 return "ARG_UNDEFINED"; 155 return state->name; 156 } 157 158 void check_syscall_arg_type(int id) 159 { 160 my_id = id; 161 if (option_project != PROJ_KERNEL) 162 return; 163 164 add_merge_hook(my_id, &merge_states); 165 add_function_hook("fdget", &match_fdget, NULL); 166 } 167 168 169