locking: _atomic_dec_and_lock() is a spinlock()
[smatch.git] / check_uncapped_alloc.c
blobd3f8f3a9f5d2282b36e0c8f1a4b0b62bb795df13
1 /*
2 * smatch/check_uncapped_alloc.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include <errno.h>
12 #include "parse.h"
13 #include "smatch.h"
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
17 static int my_id;
19 STATE(capped);
20 STATE(untrusted);
22 static struct symbol_list *untrusted_syms;
24 static int db_callback(void *unused, int argc, char **argv, char **azColName)
26 struct symbol *arg;
27 unsigned int param;
28 int i;
29 int dummy = 0;
31 errno = 0;
32 param = strtoul(argv[0], NULL, 10);
33 if (errno)
34 return dummy;
36 i = 0;
37 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
38 if (i == param)
39 add_ptr_list(&untrusted_syms, arg);
40 i++;
41 } END_FOR_EACH_PTR(arg);
43 return dummy;
46 static void match_function_def(struct symbol *sym)
48 if (!sym || !sym->ident || !sym->ident->name)
49 return;
51 run_sql(db_callback,
52 "select distinct parameter from untrusted where function = '%s';",
53 sym->ident->name);
56 static int is_untrusted_sym(struct symbol *sym)
58 struct symbol *tmp;
60 FOR_EACH_PTR(untrusted_syms, tmp) {
61 if (tmp == sym)
62 return 1;
63 } END_FOR_EACH_PTR(tmp);
65 return 0;
68 static int is_untrusted_data(struct expression *expr)
70 char *name;
71 struct symbol *sym;
72 int is_untrusted = 0;
73 struct sm_state *sm;
75 sm = get_sm_state_expr(my_id, expr);
76 if (sm && slist_has_state(sm->possible, &untrusted))
77 return 1;
79 name = get_variable_from_expr(expr, &sym);
80 if (!name || !sym)
81 goto free;
82 is_untrusted = is_untrusted_sym(sym);
83 free:
84 free_string(name);
85 return is_untrusted;
88 static void match_condition(struct expression *expr)
90 struct smatch_state *left_true = NULL;
91 struct smatch_state *left_false = NULL;
92 struct smatch_state *right_true = NULL;
93 struct smatch_state *right_false = NULL;
96 switch (expr->op) {
97 case '<':
98 case SPECIAL_LTE:
99 case SPECIAL_UNSIGNED_LT:
100 case SPECIAL_UNSIGNED_LTE:
101 left_true = &capped;
102 right_false = &capped;
103 break;
104 case '>':
105 case SPECIAL_GTE:
106 case SPECIAL_UNSIGNED_GT:
107 case SPECIAL_UNSIGNED_GTE:
108 left_false = &capped;
109 right_true = &capped;
110 break;
111 default:
112 return;
114 if (is_untrusted_data(expr->left))
115 set_true_false_states_expr(my_id, expr->left, left_true, left_false);
116 if (is_untrusted_data(expr->right))
117 set_true_false_states_expr(my_id, expr->right, right_true, right_false);
120 static int is_uncapped(struct expression *expr)
122 long long max;
124 if (expr->type == EXPR_BINOP) {
125 if (is_uncapped(expr->left))
126 return 1;
127 if (is_uncapped(expr->right))
128 return 1;
129 return 0;
131 if (!is_untrusted_data(expr))
132 return 0;
133 if (get_implied_max(expr, &max))
134 return 0;
135 if (get_absolute_max(expr, &max) && max <= 4096)
136 return 0;
137 if (get_state_expr(my_id, expr) == &capped)
138 return 0;
139 return 1;
142 static void match_assign(struct expression *expr)
144 struct expression *left;
146 left = strip_expr(expr->left);
147 if (is_untrusted_data(left))
148 set_state_expr(my_id, left, &capped);
149 if (is_uncapped(expr->right))
150 set_state_expr(my_id, left, &untrusted);
153 static void match_uncapped_max(const char *fn, struct expression *expr, void *_arg_nr)
155 int arg_nr = (int)_arg_nr;
156 struct expression *arg;
157 char *name;
159 arg = get_argument_from_call_expr(expr->args, arg_nr);
160 if (!is_uncapped(arg))
161 return;
162 name = get_variable_from_expr(arg, NULL);
163 sm_msg("warn: untrusted data is not capped '%s'", name);
164 free_string(name);
167 static void match_func_end(struct symbol *sym)
169 __free_ptr_list((struct ptr_list **)&untrusted_syms);
172 void check_uncapped_alloc(int id)
174 if (option_project != PROJ_KERNEL)
175 return;
176 if (option_no_db)
177 return;
178 my_id = id;
180 add_hook(&match_condition, CONDITION_HOOK);
181 add_hook(&match_function_def, FUNC_DEF_HOOK);
182 add_function_hook("kmalloc", &match_uncapped_max, INT_PTR(0));
183 add_function_hook("kzalloc", &match_uncapped_max, INT_PTR(0));
185 add_function_hook("copy_to_user", &match_uncapped_max, INT_PTR(2));
186 add_function_hook("_copy_to_user", &match_uncapped_max, INT_PTR(2));
187 add_function_hook("__copy_to_user", &match_uncapped_max, INT_PTR(2));
188 add_function_hook("copy_from_user", &match_uncapped_max, INT_PTR(2));
189 add_function_hook("_copy_from_user", &match_uncapped_max, INT_PTR(2));
190 add_function_hook("__copy_from_user", &match_uncapped_max, INT_PTR(2));
192 add_hook(&match_assign, ASSIGNMENT_HOOK);
194 add_hook(&match_func_end, END_FUNC_HOOK);