1 /* 2 * Copyright (C) 2013 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 #include "smatch.h" 19 20 STATE(devm); 21 22 static int my_id; 23 24 static void match_assign(const char *fn, struct expression *expr, void *unused) 25 { 26 set_state_expr(my_id, expr->left, &devm); 27 } 28 29 static void match_free_func(const char *fn, struct expression *expr, void *_arg) 30 { 31 struct expression *arg_expr; 32 int arg = PTR_INT(_arg); 33 char *name; 34 35 arg_expr = get_argument_from_call_expr(expr->args, arg); 36 if (!get_state_expr(my_id, arg_expr)) 37 return; 38 name = expr_to_str(arg_expr); 39 sm_warning("passing devm_ allocated variable to kfree. '%s'", name); 40 free_string(name); 41 } 42 43 static void register_funcs_from_file(void) 44 { 45 struct token *token; 46 const char *func; 47 int arg; 48 49 token = get_tokens_file("kernel.frees_argument"); 50 if (!token) 51 return; 52 if (token_type(token) != TOKEN_STREAMBEGIN) 53 return; 54 token = token->next; 55 while (token_type(token) != TOKEN_STREAMEND) { 56 if (token_type(token) != TOKEN_IDENT) 57 return; 58 func = show_ident(token->ident); 59 token = token->next; 60 if (token_type(token) != TOKEN_NUMBER) 61 return; 62 arg = atoi(token->number); 63 add_function_hook(func, &match_free_func, INT_PTR(arg)); 64 token = token->next; 65 } 66 clear_token_alloc(); 67 } 68 69 void check_freeing_devm(int id) 70 { 71 if (option_project != PROJ_KERNEL) 72 return; 73 74 my_id = id; 75 76 add_function_assign_hook("devm_kmalloc", &match_assign, NULL); 77 add_function_assign_hook("devm_kzalloc", &match_assign, NULL); 78 add_function_assign_hook("devm_kcalloc", &match_assign, NULL); 79 add_function_assign_hook("devm_kmalloc_array", &match_assign, NULL); 80 81 82 add_function_hook("kfree", &match_free_func, INT_PTR(0)); 83 add_function_hook("krealloc", &match_free_func, INT_PTR(0)); 84 register_funcs_from_file(); 85 }