15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 */
17
18 /*
19 * This is kernel specific stuff for smatch_extra.
20 */
21
22 #include "scope.h"
23 #include "smatch.h"
24 #include "smatch_extra.h"
25
26 static sval_t err_ptr_min;
27 static sval_t err_ptr_max;
28 static sval_t null_ptr;
29
30 static int implied_err_cast_return(struct expression *call, void *unused, struct range_list **rl)
31 {
32 struct expression *arg;
33
34 arg = get_argument_from_call_expr(call->args, 0);
35 if (!get_implied_rl(arg, rl)) {
36 *rl = alloc_rl(err_ptr_min, err_ptr_max);
37 *rl = cast_rl(get_type(arg), *rl);
38 }
39 return 1;
40 }
41
42 static void hack_ERR_PTR(struct symbol *sym)
43 {
44 struct symbol *arg;
45 struct smatch_state *estate;
46 struct range_list *after;
47 sval_t low_error;
48 sval_t minus_one;
49 sval_t zero;
50
51 low_error.type = &long_ctype;
52 low_error.value = -4095;
53
54 minus_one.type = &long_ctype;
55 minus_one.value = -1;
56
57 zero.type = &long_ctype;
58 zero.value = 0;
113 if (pre_state)
114 pre = estate_rl(pre_state);
115 else
116 pre = alloc_whole_rl(&ptr_ctype);
117 call_results_to_rl(call_expr, &ptr_ctype, "0,(-4095)-(-1)", &rl);
118 rl = rl_intersection(pre, rl);
119 rl = cast_rl(get_type(arg), rl);
120 end_state = alloc_estate_rl(rl);
121 set_extra_expr_nomod(arg, end_state);
122 }
123
124 static void match_not_err(const char *fn, struct expression *call_expr,
125 struct expression *assign_expr, void *unused)
126 {
127 struct expression *arg;
128 struct smatch_state *pre_state;
129 struct range_list *rl;
130
131 arg = get_argument_from_call_expr(call_expr->args, 0);
132 pre_state = get_state_expr(SMATCH_EXTRA, arg);
133 if (estate_rl(pre_state)) {
134 rl = estate_rl(pre_state);
135 rl = remove_range(rl, err_ptr_min, err_ptr_max);
136 } else {
137 rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
138 }
139 rl = cast_rl(get_type(arg), rl);
140 set_extra_expr_nomod(arg, alloc_estate_rl(rl));
141 }
142
143 static void match_err(const char *fn, struct expression *call_expr,
144 struct expression *assign_expr, void *unused)
145 {
146 struct expression *arg;
147 struct smatch_state *pre_state;
148 struct range_list *rl;
149
150 arg = get_argument_from_call_expr(call_expr->args, 0);
151 pre_state = get_state_expr(SMATCH_EXTRA, arg);
152 rl = estate_rl(pre_state);
153 if (!rl)
154 rl = alloc_rl(err_ptr_min, err_ptr_max);
155 rl = rl_intersection(rl, alloc_rl(err_ptr_min, err_ptr_max));
156 rl = cast_rl(get_type(arg), rl);
157 set_extra_expr_nomod(arg, alloc_estate_rl(rl));
158 }
159
160 static void match_container_of_macro(const char *fn, struct expression *expr, void *unused)
161 {
162 set_extra_expr_mod(expr->left, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
163 }
164
165 static void match_container_of(struct expression *expr)
166 {
167 struct expression *right = expr->right;
168 char *macro;
169
170 /*
171 * The problem here is that sometimes the container_of() macro is itself
172 * inside a macro and get_macro() only returns the name of the outside
173 * macro.
174 */
175
176 /*
240 if (!get_implied_rl(arg, &arg_rl))
241 return 0;
242 if (rl_to_sval(arg_rl, &sval)) {
243 int i;
244
245 for (i = 63; i >= 0; i--) {
246 if (sval.uvalue & 1ULL << i)
247 break;
248 }
249 sval.value = i + 1;
250 *rl = alloc_rl(sval, sval);
251 return 1;
252 }
253 zero.type = rl_type(arg_rl);
254 if (!rl_has_sval(arg_rl, zero))
255 start.value = 1;
256 *rl = alloc_rl(start, end);
257 return 1;
258 }
259
260
261
262 static void find_module_init_exit(struct symbol_list *sym_list)
263 {
264 struct symbol *sym;
265 struct symbol *fn;
266 struct statement *stmt;
267 char *name;
268 int init;
269 int count;
270
271 /*
272 * This is more complicated because Sparse ignores the "alias"
273 * attribute. I search backwards because module_init() is normally at
274 * the end of the file.
275 */
276 count = 0;
277 FOR_EACH_PTR_REVERSE(sym_list, sym) {
278 if (sym->type != SYM_NODE)
279 continue;
280 if (!(sym->ctype.modifiers & MOD_STATIC))
281 continue;
389 data = strip_parens(data->unop);
390
391 dest = get_argument_from_call_expr(call->args, 1);
392 if (dest->type != EXPR_DEREF || dest->op != '.')
393 return;
394 if (!dest->member || strcmp(dest->member->name, "__c") != 0)
395 return;
396 dest = dest->deref;
397 type = get_type(dest);
398 if (!type)
399 return;
400 val_sym = first_ptr_list((struct ptr_list *)type->symbol_list);
401 dest = member_expression(dest, '.', val_sym->ident);
402
403 assign = assign_expression(dest, '=', data);
404 __in_fake_assign++;
405 __split_expr(assign);
406 __in_fake_assign--;
407 }
408
409 bool is_ignored_kernel_data(const char *name)
410 {
411 if (option_project != PROJ_KERNEL)
412 return false;
413
414 /*
415 * On the file I was looking at lockdep was 25% of the DB.
416 */
417 if (strstr(name, ".dep_map."))
418 return true;
419 if (strstr(name, ".lockdep_map."))
420 return true;
421 return false;
422 }
423
424 void check_kernel(int id)
425 {
426 if (option_project != PROJ_KERNEL)
427 return;
428
446 return_implies_state("IS_ERR", 1, 1, &match_err, NULL);
447 return_implies_state("tomoyo_memory_ok", 1, 1, &match_param_valid_ptr, (void *)0);
448
449 add_macro_assign_hook_extra("container_of", &match_container_of_macro, NULL);
450 add_hook(match_container_of, ASSIGNMENT_HOOK);
451
452 add_implied_return_hook("find_next_bit", &match_next_bit, NULL);
453 add_implied_return_hook("find_next_zero_bit", &match_next_bit, NULL);
454 add_implied_return_hook("find_first_bit", &match_next_bit, NULL);
455 add_implied_return_hook("find_first_zero_bit", &match_next_bit, NULL);
456
457 add_implied_return_hook("fls", &match_fls, NULL);
458 add_implied_return_hook("fls64", &match_fls, NULL);
459
460 add_function_hook("__ftrace_bad_type", &__match_nullify_path_hook, NULL);
461 add_function_hook("__write_once_size", &match__write_once_size, NULL);
462
463 add_function_hook("__read_once_size", &match__read_once_size, NULL);
464 add_function_hook("__read_once_size_nocheck", &match__read_once_size, NULL);
465
466 if (option_info)
467 add_hook(match_end_file, END_FILE_HOOK);
468 }
|
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 */
17
18 /*
19 * This is kernel specific stuff for smatch_extra.
20 */
21
22 #include "scope.h"
23 #include "smatch.h"
24 #include "smatch_extra.h"
25
26 static sval_t err_ptr_min;
27 static sval_t err_ptr_max;
28 static sval_t null_ptr;
29
30 static int implied_err_cast_return(struct expression *call, void *unused, struct range_list **rl)
31 {
32 struct expression *arg;
33
34 arg = get_argument_from_call_expr(call->args, 0);
35 if (!get_implied_rl(arg, rl))
36 *rl = alloc_rl(err_ptr_min, err_ptr_max);
37
38 *rl = cast_rl(get_type(call), *rl);
39 return 1;
40 }
41
42 static void hack_ERR_PTR(struct symbol *sym)
43 {
44 struct symbol *arg;
45 struct smatch_state *estate;
46 struct range_list *after;
47 sval_t low_error;
48 sval_t minus_one;
49 sval_t zero;
50
51 low_error.type = &long_ctype;
52 low_error.value = -4095;
53
54 minus_one.type = &long_ctype;
55 minus_one.value = -1;
56
57 zero.type = &long_ctype;
58 zero.value = 0;
113 if (pre_state)
114 pre = estate_rl(pre_state);
115 else
116 pre = alloc_whole_rl(&ptr_ctype);
117 call_results_to_rl(call_expr, &ptr_ctype, "0,(-4095)-(-1)", &rl);
118 rl = rl_intersection(pre, rl);
119 rl = cast_rl(get_type(arg), rl);
120 end_state = alloc_estate_rl(rl);
121 set_extra_expr_nomod(arg, end_state);
122 }
123
124 static void match_not_err(const char *fn, struct expression *call_expr,
125 struct expression *assign_expr, void *unused)
126 {
127 struct expression *arg;
128 struct smatch_state *pre_state;
129 struct range_list *rl;
130
131 arg = get_argument_from_call_expr(call_expr->args, 0);
132 pre_state = get_state_expr(SMATCH_EXTRA, arg);
133 if (pre_state)
134 return;
135 rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
136 rl = cast_rl(get_type(arg), rl);
137 set_extra_expr_nomod(arg, alloc_estate_rl(rl));
138 }
139
140 static void match_err(const char *fn, struct expression *call_expr,
141 struct expression *assign_expr, void *unused)
142 {
143 struct expression *arg;
144 struct smatch_state *pre_state;
145 struct range_list *rl;
146
147 arg = get_argument_from_call_expr(call_expr->args, 0);
148 pre_state = get_state_expr(SMATCH_EXTRA, arg);
149 rl = estate_rl(pre_state);
150 if (!rl)
151 rl = alloc_rl(err_ptr_min, err_ptr_max);
152 rl = rl_intersection(rl, alloc_rl(err_ptr_min, err_ptr_max));
153 rl = cast_rl(get_type(arg), rl);
154 if (pre_state && rl) {
155 /*
156 * Ideally this would all be handled by smatch_implied.c
157 * but it doesn't work very well for impossible paths.
158 *
159 */
160 return;
161 }
162 set_extra_expr_nomod(arg, alloc_estate_rl(rl));
163 }
164
165 static void match_container_of_macro(const char *fn, struct expression *expr, void *unused)
166 {
167 set_extra_expr_mod(expr->left, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
168 }
169
170 static void match_container_of(struct expression *expr)
171 {
172 struct expression *right = expr->right;
173 char *macro;
174
175 /*
176 * The problem here is that sometimes the container_of() macro is itself
177 * inside a macro and get_macro() only returns the name of the outside
178 * macro.
179 */
180
181 /*
245 if (!get_implied_rl(arg, &arg_rl))
246 return 0;
247 if (rl_to_sval(arg_rl, &sval)) {
248 int i;
249
250 for (i = 63; i >= 0; i--) {
251 if (sval.uvalue & 1ULL << i)
252 break;
253 }
254 sval.value = i + 1;
255 *rl = alloc_rl(sval, sval);
256 return 1;
257 }
258 zero.type = rl_type(arg_rl);
259 if (!rl_has_sval(arg_rl, zero))
260 start.value = 1;
261 *rl = alloc_rl(start, end);
262 return 1;
263 }
264
265 static void find_module_init_exit(struct symbol_list *sym_list)
266 {
267 struct symbol *sym;
268 struct symbol *fn;
269 struct statement *stmt;
270 char *name;
271 int init;
272 int count;
273
274 /*
275 * This is more complicated because Sparse ignores the "alias"
276 * attribute. I search backwards because module_init() is normally at
277 * the end of the file.
278 */
279 count = 0;
280 FOR_EACH_PTR_REVERSE(sym_list, sym) {
281 if (sym->type != SYM_NODE)
282 continue;
283 if (!(sym->ctype.modifiers & MOD_STATIC))
284 continue;
392 data = strip_parens(data->unop);
393
394 dest = get_argument_from_call_expr(call->args, 1);
395 if (dest->type != EXPR_DEREF || dest->op != '.')
396 return;
397 if (!dest->member || strcmp(dest->member->name, "__c") != 0)
398 return;
399 dest = dest->deref;
400 type = get_type(dest);
401 if (!type)
402 return;
403 val_sym = first_ptr_list((struct ptr_list *)type->symbol_list);
404 dest = member_expression(dest, '.', val_sym->ident);
405
406 assign = assign_expression(dest, '=', data);
407 __in_fake_assign++;
408 __split_expr(assign);
409 __in_fake_assign--;
410 }
411
412 static void match_closure_call(const char *name, struct expression *call,
413 void *unused)
414 {
415 struct expression *cl, *fn, *fake_call;
416 struct expression_list *args = NULL;
417
418 cl = get_argument_from_call_expr(call->args, 0);
419 fn = get_argument_from_call_expr(call->args, 1);
420 if (!fn || !cl)
421 return;
422
423 add_ptr_list(&args, cl);
424 fake_call = call_expression(fn, args);
425 __split_expr(fake_call);
426 }
427
428 bool is_ignored_kernel_data(const char *name)
429 {
430 if (option_project != PROJ_KERNEL)
431 return false;
432
433 /*
434 * On the file I was looking at lockdep was 25% of the DB.
435 */
436 if (strstr(name, ".dep_map."))
437 return true;
438 if (strstr(name, ".lockdep_map."))
439 return true;
440 return false;
441 }
442
443 void check_kernel(int id)
444 {
445 if (option_project != PROJ_KERNEL)
446 return;
447
465 return_implies_state("IS_ERR", 1, 1, &match_err, NULL);
466 return_implies_state("tomoyo_memory_ok", 1, 1, &match_param_valid_ptr, (void *)0);
467
468 add_macro_assign_hook_extra("container_of", &match_container_of_macro, NULL);
469 add_hook(match_container_of, ASSIGNMENT_HOOK);
470
471 add_implied_return_hook("find_next_bit", &match_next_bit, NULL);
472 add_implied_return_hook("find_next_zero_bit", &match_next_bit, NULL);
473 add_implied_return_hook("find_first_bit", &match_next_bit, NULL);
474 add_implied_return_hook("find_first_zero_bit", &match_next_bit, NULL);
475
476 add_implied_return_hook("fls", &match_fls, NULL);
477 add_implied_return_hook("fls64", &match_fls, NULL);
478
479 add_function_hook("__ftrace_bad_type", &__match_nullify_path_hook, NULL);
480 add_function_hook("__write_once_size", &match__write_once_size, NULL);
481
482 add_function_hook("__read_once_size", &match__read_once_size, NULL);
483 add_function_hook("__read_once_size_nocheck", &match__read_once_size, NULL);
484
485 add_function_hook("closure_call", &match_closure_call, NULL);
486
487 if (option_info)
488 add_hook(match_end_file, END_FILE_HOOK);
489 }
|