2 * smatch/check_uncapped_alloc.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
22 static struct symbol_list
*untrusted_syms
;
24 static int db_callback(void *unused
, int argc
, char **argv
, char **azColName
)
32 param
= strtoul(argv
[0], NULL
, 10);
37 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
39 add_ptr_list(&untrusted_syms
, arg
);
41 } END_FOR_EACH_PTR(arg
);
46 static void match_function_def(struct symbol
*sym
)
48 if (!sym
|| !sym
->ident
|| !sym
->ident
->name
)
52 "select distinct parameter from untrusted where function = '%s';",
56 static int is_untrusted_sym(struct symbol
*sym
)
60 FOR_EACH_PTR(untrusted_syms
, tmp
) {
63 } END_FOR_EACH_PTR(tmp
);
68 static int is_untrusted_data(struct expression
*expr
)
75 sm
= get_sm_state_expr(my_id
, expr
);
76 if (sm
&& slist_has_state(sm
->possible
, &untrusted
))
79 name
= get_variable_from_expr(expr
, &sym
);
82 is_untrusted
= is_untrusted_sym(sym
);
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
;
99 case SPECIAL_UNSIGNED_LT
:
100 case SPECIAL_UNSIGNED_LTE
:
102 right_false
= &capped
;
106 case SPECIAL_UNSIGNED_GT
:
107 case SPECIAL_UNSIGNED_GTE
:
108 left_false
= &capped
;
109 right_true
= &capped
;
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
)
124 if (expr
->type
== EXPR_BINOP
) {
125 if (is_uncapped(expr
->left
))
127 if (is_uncapped(expr
->right
))
131 if (!is_untrusted_data(expr
))
133 if (get_implied_max(expr
, &max
))
135 if (get_absolute_max(expr
, &max
) && max
<= 4096)
137 if (get_state_expr(my_id
, expr
) == &capped
)
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
= PTR_INT(_arg_nr
);
156 struct expression
*arg
;
159 arg
= get_argument_from_call_expr(expr
->args
, arg_nr
);
160 if (!is_uncapped(arg
))
162 name
= get_variable_from_expr(arg
, NULL
);
163 sm_msg("warn: untrusted data is not capped '%s'", 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
)
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
);