Print this page
new smatch


  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 /* Does a search for Dan Rosenberg style info leaks */
  19 
  20 /* fixme: struct includes a struct with a hole in it */
  21 /* function is called that clears the struct */
  22 
  23 #include "scope.h"
  24 #include "smatch.h"
  25 #include "smatch_function_hashtable.h"
  26 #include "smatch_slist.h"
  27 #include "smatch_extra.h"
  28 
  29 static int my_whole_id;
  30 static int my_member_id;

  31 
  32 STATE(cleared);
  33 
  34 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  35 {
  36         struct symbol *type;
  37 
  38         type = get_real_base_type(sym);
  39         if (!type || type->type != SYM_STRUCT)
  40                 return;
  41 
  42         set_state(my_member_id, name, sym, state);
  43 }
  44 
  45 static void print_holey_warning(struct expression *data, const char *member)
  46 {
  47         char *name;
  48 
  49         name = expr_to_str(data);
  50         if (member) {


 107         struct symbol *type;
 108         type = get_type(expr);
 109         if (!type || type->type != SYM_STRUCT)
 110                 return 0;
 111 
 112         return check_struct(expr, type);
 113 }
 114 
 115 static int has_global_scope(struct expression *expr)
 116 {
 117         struct symbol *sym;
 118 
 119         if (expr->type != EXPR_SYMBOL)
 120                 return FALSE;
 121         sym = expr->symbol;
 122         if (!sym)
 123                 return FALSE;
 124         return toplevel(sym->scope);
 125 }
 126 
 127 static int was_initialized(struct expression *expr)
 128 {
 129         struct symbol *sym;
 130         char *name;
 131 
 132         name = expr_to_var_sym(expr, &sym);
 133         if (!name)
 134                 return 0;
 135         if (sym->initializer)
 136                 return 1;
 137         return 0;
 138 }
 139 
 140 static void match_clear(const char *fn, struct expression *expr, void *_arg_no)
 141 {
 142         struct expression *ptr;
 143         int arg_no = PTR_INT(_arg_no);
 144 
 145         ptr = get_argument_from_call_expr(expr->args, arg_no);
 146         if (!ptr)
 147                 return;
 148         ptr = strip_expr(ptr);
 149         if (ptr->type != EXPR_PREOP || ptr->op != '&')
 150                 return;
 151         ptr = strip_expr(ptr->unop);
 152         set_state_expr(my_whole_id, ptr, &cleared);
 153 }
 154 
 155 static int was_memset(struct expression *expr)
 156 {
 157         if (get_state_expr(my_whole_id, expr) == &cleared)
 158                 return 1;
 159         return 0;


 241                         goto out;
 242                 }
 243         } END_FOR_EACH_PTR(tmp);
 244 out:
 245         free_string(name);
 246         return printed;
 247 }
 248 
 249 static void check_was_initialized(struct expression *data)
 250 {
 251         data = strip_expr(data);
 252         if (!data)
 253                 return;
 254         if (data->type == EXPR_PREOP && data->op == '&')
 255                 data = strip_expr(data->unop);
 256         if (data->type != EXPR_SYMBOL)
 257                 return;
 258 
 259         if (has_global_scope(data))
 260                 return;
 261         if (was_initialized(data))
 262                 return;













 263         if (was_memset(data))
 264                 return;
 265         if (warn_on_holey_struct(data))
 266                 return;
 267         check_members_initialized(data);
 268 }
 269 
 270 static void match_copy_to_user(const char *fn, struct expression *expr, void *_arg)
 271 {
 272         int arg = PTR_INT(_arg);
 273         struct expression *data;
 274 
 275         data = get_argument_from_call_expr(expr->args, arg);
 276         data = strip_expr(data);
 277         if (!data)
 278                 return;
 279         if (data->type != EXPR_PREOP || data->op != '&')
 280                 return;
 281         check_was_initialized(data);
 282 }
 283 
 284 static void db_param_cleared(struct expression *expr, int param, char *key, char *value)
 285 {
 286         while (expr->type == EXPR_ASSIGNMENT)
 287                 expr = strip_expr(expr->right);
 288         if (expr->type != EXPR_CALL)
 289                 return;
 290 
 291         match_clear(NULL, expr, INT_PTR(param));
 292 }
 293 
 294 static void match_assign(struct expression *expr)
 295 {

















 296         struct symbol *type;

 297 
 298         type = get_type(expr->left);

 299         if (!type || type->type != SYM_STRUCT)
 300                 return;
 301         set_state_expr(my_whole_id, expr->left, &cleared);

 302 }
 303 















 304 static void register_clears_argument(void)
 305 {
 306         struct token *token;
 307         const char *func;
 308         int arg;
 309 
 310         token = get_tokens_file("kernel.clears_argument");
 311         if (!token)
 312                 return;
 313         if (token_type(token) != TOKEN_STREAMBEGIN)
 314                 return;
 315         token = token->next;
 316         while (token_type(token) != TOKEN_STREAMEND) {
 317                 if (token_type(token) != TOKEN_IDENT)
 318                         return;
 319                 func = show_ident(token->ident);
 320                 token = token->next;
 321                 if (token_type(token) != TOKEN_NUMBER)
 322                         return;
 323                 arg = atoi(token->number);


 352                 token = token->next;
 353         }
 354         clear_token_alloc();
 355 }
 356 
 357 void check_rosenberg(int id)
 358 {
 359         if (option_project != PROJ_KERNEL)
 360                 return;
 361         my_whole_id = id;
 362 
 363         add_function_hook("memset", &match_clear, INT_PTR(0));
 364         add_function_hook("memcpy", &match_clear, INT_PTR(0));
 365         add_function_hook("memzero", &match_clear, INT_PTR(0));
 366         add_function_hook("__memset", &match_clear, INT_PTR(0));
 367         add_function_hook("__memcpy", &match_clear, INT_PTR(0));
 368         add_function_hook("__memzero", &match_clear, INT_PTR(0));
 369         add_function_hook("__builtin_memset", &match_clear, INT_PTR(0));
 370         add_function_hook("__builtin_memcpy", &match_clear, INT_PTR(0));
 371 
 372         add_hook(&match_assign, ASSIGNMENT_HOOK);
 373         register_clears_argument();
 374         select_return_states_hook(PARAM_CLEARED, &db_param_cleared);
 375 
 376         register_copy_funcs_from_file();
 377 }
 378 
 379 void check_rosenberg2(int id)
 380 {
 381         if (option_project != PROJ_KERNEL)
 382                 return;
 383 
 384         my_member_id = id;
 385         set_dynamic_states(my_member_id);
 386         add_extra_mod_hook(&extra_mod_hook);
 387 }
 388 













  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 /* Does a search for Dan Rosenberg style info leaks */
  19 
  20 /* fixme: struct includes a struct with a hole in it */
  21 /* function is called that clears the struct */
  22 
  23 #include "scope.h"
  24 #include "smatch.h"
  25 #include "smatch_function_hashtable.h"
  26 #include "smatch_slist.h"
  27 #include "smatch_extra.h"
  28 
  29 static int my_whole_id;
  30 static int my_member_id;
  31 static int skb_put_id;
  32 
  33 STATE(cleared);
  34 
  35 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
  36 {
  37         struct symbol *type;
  38 
  39         type = get_real_base_type(sym);
  40         if (!type || type->type != SYM_STRUCT)
  41                 return;
  42 
  43         set_state(my_member_id, name, sym, state);
  44 }
  45 
  46 static void print_holey_warning(struct expression *data, const char *member)
  47 {
  48         char *name;
  49 
  50         name = expr_to_str(data);
  51         if (member) {


 108         struct symbol *type;
 109         type = get_type(expr);
 110         if (!type || type->type != SYM_STRUCT)
 111                 return 0;
 112 
 113         return check_struct(expr, type);
 114 }
 115 
 116 static int has_global_scope(struct expression *expr)
 117 {
 118         struct symbol *sym;
 119 
 120         if (expr->type != EXPR_SYMBOL)
 121                 return FALSE;
 122         sym = expr->symbol;
 123         if (!sym)
 124                 return FALSE;
 125         return toplevel(sym->scope);
 126 }
 127 













 128 static void match_clear(const char *fn, struct expression *expr, void *_arg_no)
 129 {
 130         struct expression *ptr;
 131         int arg_no = PTR_INT(_arg_no);
 132 
 133         ptr = get_argument_from_call_expr(expr->args, arg_no);
 134         if (!ptr)
 135                 return;
 136         ptr = strip_expr(ptr);
 137         if (ptr->type != EXPR_PREOP || ptr->op != '&')
 138                 return;
 139         ptr = strip_expr(ptr->unop);
 140         set_state_expr(my_whole_id, ptr, &cleared);
 141 }
 142 
 143 static int was_memset(struct expression *expr)
 144 {
 145         if (get_state_expr(my_whole_id, expr) == &cleared)
 146                 return 1;
 147         return 0;


 229                         goto out;
 230                 }
 231         } END_FOR_EACH_PTR(tmp);
 232 out:
 233         free_string(name);
 234         return printed;
 235 }
 236 
 237 static void check_was_initialized(struct expression *data)
 238 {
 239         data = strip_expr(data);
 240         if (!data)
 241                 return;
 242         if (data->type == EXPR_PREOP && data->op == '&')
 243                 data = strip_expr(data->unop);
 244         if (data->type != EXPR_SYMBOL)
 245                 return;
 246 
 247         if (has_global_scope(data))
 248                 return;
 249         if (was_memset(data))
 250                 return;
 251         if (warn_on_holey_struct(data))
 252                 return;
 253         check_members_initialized(data);
 254 }
 255 
 256 static void check_skb_put(struct expression *data)
 257 {
 258         data = strip_expr(data);
 259         if (!data)
 260                 return;
 261         if (data->type == EXPR_PREOP && data->op == '&')
 262                 data = strip_expr(data->unop);
 263 
 264         if (was_memset(data))
 265                 return;
 266         if (warn_on_holey_struct(data))
 267                 return;
 268         check_members_initialized(data);
 269 }
 270 
 271 static void match_copy_to_user(const char *fn, struct expression *expr, void *_arg)
 272 {
 273         int arg = PTR_INT(_arg);
 274         struct expression *data;
 275 
 276         data = get_argument_from_call_expr(expr->args, arg);
 277         data = strip_expr(data);
 278         if (!data)
 279                 return;
 280         if (data->type != EXPR_PREOP || data->op != '&')
 281                 return;
 282         check_was_initialized(data);
 283 }
 284 
 285 static void db_param_cleared(struct expression *expr, int param, char *key, char *value)
 286 {
 287         while (expr->type == EXPR_ASSIGNMENT)
 288                 expr = strip_expr(expr->right);
 289         if (expr->type != EXPR_CALL)
 290                 return;
 291 
 292         match_clear(NULL, expr, INT_PTR(param));
 293 }
 294 
 295 static struct smatch_state *alloc_expr_state(struct expression *expr)
 296 {
 297         struct smatch_state *state;
 298         char *name;
 299 
 300         name = expr_to_str(expr);
 301         if (!name)
 302                 return NULL;
 303 
 304         state = __alloc_smatch_state(0);
 305         expr = strip_expr(expr);
 306         state->name = alloc_sname(name);
 307         free_string(name);
 308         state->data = expr;
 309         return state;
 310 }
 311 
 312 static void match_skb_put(const char *fn, struct expression *expr, void *unused)
 313 {
 314         struct symbol *type;
 315         struct smatch_state *state;
 316 
 317         type = get_type(expr->left);
 318         type = get_real_base_type(type);
 319         if (!type || type->type != SYM_STRUCT)
 320                 return;
 321         state = alloc_expr_state(expr->left);
 322         set_state_expr(skb_put_id, expr->left, state);
 323 }
 324 
 325 static void match_return_skb_put(struct expression *expr)
 326 {
 327         struct sm_state *sm;
 328         struct stree *stree;
 329 
 330         if (is_error_return(expr))
 331                 return;
 332 
 333         stree = __get_cur_stree();
 334 
 335         FOR_EACH_MY_SM(skb_put_id, stree, sm) {
 336                 check_skb_put(sm->state->data);
 337         } END_FOR_EACH_SM(sm);
 338 }
 339 
 340 static void register_clears_argument(void)
 341 {
 342         struct token *token;
 343         const char *func;
 344         int arg;
 345 
 346         token = get_tokens_file("kernel.clears_argument");
 347         if (!token)
 348                 return;
 349         if (token_type(token) != TOKEN_STREAMBEGIN)
 350                 return;
 351         token = token->next;
 352         while (token_type(token) != TOKEN_STREAMEND) {
 353                 if (token_type(token) != TOKEN_IDENT)
 354                         return;
 355                 func = show_ident(token->ident);
 356                 token = token->next;
 357                 if (token_type(token) != TOKEN_NUMBER)
 358                         return;
 359                 arg = atoi(token->number);


 388                 token = token->next;
 389         }
 390         clear_token_alloc();
 391 }
 392 
 393 void check_rosenberg(int id)
 394 {
 395         if (option_project != PROJ_KERNEL)
 396                 return;
 397         my_whole_id = id;
 398 
 399         add_function_hook("memset", &match_clear, INT_PTR(0));
 400         add_function_hook("memcpy", &match_clear, INT_PTR(0));
 401         add_function_hook("memzero", &match_clear, INT_PTR(0));
 402         add_function_hook("__memset", &match_clear, INT_PTR(0));
 403         add_function_hook("__memcpy", &match_clear, INT_PTR(0));
 404         add_function_hook("__memzero", &match_clear, INT_PTR(0));
 405         add_function_hook("__builtin_memset", &match_clear, INT_PTR(0));
 406         add_function_hook("__builtin_memcpy", &match_clear, INT_PTR(0));
 407 

 408         register_clears_argument();
 409         select_return_states_hook(PARAM_CLEARED, &db_param_cleared);
 410 
 411         register_copy_funcs_from_file();
 412 }
 413 
 414 void check_rosenberg2(int id)
 415 {
 416         if (option_project != PROJ_KERNEL)
 417                 return;
 418 
 419         my_member_id = id;
 420         set_dynamic_states(my_member_id);
 421         add_extra_mod_hook(&extra_mod_hook);
 422 }
 423 
 424 void check_rosenberg3(int id)
 425 {
 426         if (option_project != PROJ_KERNEL)
 427                 return;
 428 
 429         skb_put_id = id;
 430         set_dynamic_states(skb_put_id);
 431         add_function_assign_hook("skb_put", &match_skb_put, NULL);
 432         add_hook(&match_return_skb_put, RETURN_HOOK);
 433 }
 434