2 * Copyright (C) 2010 Dan Carpenter.
3 * Copyright (C) 2020 Oracle.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
20 * This is the "strict" version which is more daring and ambitious than
21 * the check_free.c file. The difference is that this looks at split
22 * returns and the other only looks at if every path frees a parameter.
23 * Also this has a bunch of kernel specific things to do with reference
29 #include "smatch_slist.h"
30 #include "smatch_extra.h"
38 static void match_kobject_put(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
);
39 static void match___skb_pad(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
);
46 const sval_t
*implies_start
, *implies_end
;
47 param_key_hook
*call_back
;
50 static struct func_info func_table
[] = {
51 { "free", PARAM_FREED
, 0, "$" },
52 { "kfree", PARAM_FREED
, 0, "$" },
53 { "vfree", PARAM_FREED
, 0, "$" },
54 { "kzfree", PARAM_FREED
, 0, "$" },
55 { "kvfree", PARAM_FREED
, 0, "$" },
57 { "kfree_skb", PARAM_FREED
, 0, "$" },
58 { "kfree_skbmem", PARAM_FREED
, 0, "$" },
60 { "mempool_free", PARAM_FREED
, 0, "$" },
61 { "kmem_cache_free", PARAM_FREED
, 1, "$" },
62 { "dma_pool_free", PARAM_FREED
, 1, "$" },
64 { "memstick_free_host", PARAM_FREED
, 0, "$" },
65 // { "spi_unregister_controller", PARAM_FREED, 0, "$" },
66 { "netif_rx_internal", PARAM_FREED
, 0, "$" },
67 { "netif_rx", PARAM_FREED
, 0, "$" },
69 { "enqueue_to_backlog", PARAM_FREED
, 0, "$" },
71 { "brelse", PARAM_FREED
, 0, "$" },
72 { "dma_free_coherent", PARAM_FREED
, 2, "$" },
73 { "free_netdev", PARAM_FREED
, 0, "$" },
74 { "sock_release", PARAM_FREED
, 0, "$" },
76 { "qdisc_enqueue", PARAM_FREED
, 0, "$" },
78 { "kobject_put", PARAM_FREED
, 0, "$", NULL
, NULL
, &match_kobject_put
},
79 { "put_device", PARAM_FREED
, 0, "$", NULL
, NULL
, &match_kobject_put
},
81 { "__skb_pad", PARAM_FREED
, 0, "$", &err_min
, &err_max
, &match___skb_pad
},
84 static struct name_sym_fn_list
*free_hooks
;
86 void add_free_hook(name_sym_hook
*hook
)
88 add_ptr_list(&free_hooks
, hook
);
91 static void call_free_call_backs_name_sym(const char *name
, struct symbol
*sym
)
93 struct expression
*expr
;
96 expr
= gen_expression_from_name_sym(name
, sym
);
98 FOR_EACH_PTR(free_hooks
, hook
) {
99 hook(expr
, name
, sym
);
100 } END_FOR_EACH_PTR(hook
);
103 static void ok_to_use(struct sm_state
*sm
, struct expression
*mod_expr
)
105 if (sm
->state
!= &ok
)
106 set_state(my_id
, sm
->name
, sm
->sym
, &ok
);
109 static void pre_merge_hook(struct sm_state
*cur
, struct sm_state
*other
)
111 if (is_impossible_path())
112 set_state(my_id
, cur
->name
, cur
->sym
, &ok
);
115 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
117 struct smatch_state
*state
;
120 if (sm
->state
!= &freed
&& sm
->state
!= &maybe_freed
)
123 if (get_param_num_from_sym(sm
->sym
) < 0)
127 * If the parent is non-there count it as freed. This is
128 * a hack for tracking return states.
130 if (parent_is_null_var_sym(sm
->name
, sm
->sym
))
133 state
= get_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
);
136 if (!estate_get_single_value(state
, &sval
) || sval
.value
!= 0)
138 /* It makes it easier to consider NULL pointers as freed. */
142 struct smatch_state
*merge_frees(struct smatch_state
*s1
, struct smatch_state
*s2
)
144 if (s1
== &freed
&& s2
== &maybe_freed
)
146 if (s1
== &maybe_freed
&& s2
== &freed
)
151 static int is_freed(struct expression
*expr
)
155 sm
= get_sm_state_expr(my_id
, expr
);
156 if (sm
&& slist_has_state(sm
->possible
, &freed
))
161 bool is_freed_var_sym(const char *name
, struct symbol
*sym
)
163 struct smatch_state
*state
;
165 state
= get_state(my_id
, name
, sym
);
166 if (state
== &freed
|| state
== &maybe_freed
)
172 static bool expr_is_condition(struct expression
*expr
)
174 struct statement
*stmt
;
176 stmt
= expr_get_parent_stmt(expr
);
179 if (stmt
->type
== STMT_IF
|| stmt
->type
== STMT_ITERATOR
)
184 bool is_part_of_condition(struct expression
*expr
)
186 struct expression
*parent
;
188 if (expr_is_condition(expr
))
191 parent
= expr_get_parent_expr(expr
);
194 if (parent
->type
== EXPR_LOGICAL
|| parent
->type
== EXPR_COMPARE
)
196 if (parent
->type
== EXPR_SELECT
|| parent
->type
== EXPR_CONDITIONAL
)
198 if (parent
->type
== EXPR_PREOP
&& parent
->op
== '!')
204 static bool is_percent_p(struct expression
*str_expr
, int idx
)
209 p
= str_expr
->string
->data
;
211 if (p
[0] == '%' && p
[1] == '%') {
215 /* If we have print("%.*s %p", prec, str, p); then it takes 2 params */
216 if ((p
[0] == '%' && p
[1] == '*') ||
217 (p
[0] == '%' && p
[1] == '.' && p
[2] == '*'))
221 if (idx
== cnt
&& p
[1] == 'p')
229 bool is_percent_p_print(struct expression
*expr
)
231 struct expression
*parent
, *arg
;
232 int expr_idx
, string_idx
;
234 parent
= expr_get_parent_expr(expr
);
235 if (!parent
|| parent
->type
!= EXPR_CALL
)
239 FOR_EACH_PTR(parent
->args
, arg
) {
243 } END_FOR_EACH_PTR(arg
);
249 FOR_EACH_PTR(parent
->args
, arg
) {
251 if (arg
->type
!= EXPR_STRING
)
253 if (is_percent_p(arg
, expr_idx
- string_idx
))
255 } END_FOR_EACH_PTR(arg
);
260 static void match_symbol(struct expression
*expr
)
262 struct expression
*parent
;
265 if (is_impossible_path())
267 if (__in_fake_parameter_assign
)
270 if (is_part_of_condition(expr
))
273 /* This ignores stuff like "get_new_ptr(&foo);" */
274 parent
= expr_get_parent_expr(expr
);
275 while (parent
&& parent
->type
== EXPR_PREOP
&& parent
->op
== '(')
276 parent
= expr_get_parent_expr(parent
);
277 if (parent
&& parent
->type
== EXPR_PREOP
&& parent
->op
== '&')
283 if (is_percent_p_print(expr
))
286 name
= expr_to_var(expr
);
287 sm_warning("'%s' was already freed.", name
);
291 static void match_dereferences(struct expression
*expr
)
295 if (expr
->type
!= EXPR_PREOP
)
298 if (is_impossible_path())
300 if (__in_fake_parameter_assign
)
303 expr
= strip_expr(expr
->unop
);
306 name
= expr_to_var(expr
);
307 sm_error("dereferencing freed memory '%s'", name
);
308 set_state_expr(my_id
, expr
, &ok
);
312 static int ignored_params
[16];
314 static void set_ignored_params(struct expression
*call
)
316 struct expression
*arg
;
320 memset(&ignored_params
, 0, sizeof(ignored_params
));
323 FOR_EACH_PTR(call
->args
, arg
) {
325 if (arg
->type
!= EXPR_STRING
)
328 } END_FOR_EACH_PTR(arg
);
334 p
= arg
->string
->data
;
335 while ((p
= strchr(p
, '%'))) {
336 if (i
>= ARRAY_SIZE(ignored_params
))
348 ignored_params
[i
] = 1;
353 static int is_free_func(struct expression
*fn
)
358 name
= expr_to_str(fn
);
361 if (strstr(name
, "free"))
368 static void match_call(struct expression
*expr
)
370 struct expression
*arg
;
374 if (is_impossible_path())
377 set_ignored_params(expr
);
380 FOR_EACH_PTR(expr
->args
, arg
) {
382 if (!is_pointer(arg
))
386 if (ignored_params
[i
])
388 if (is_percent_p_print(arg
))
391 name
= expr_to_var(arg
);
392 if (is_free_func(expr
->fn
))
393 sm_error("double free of '%s'", name
);
395 sm_warning("passing freed memory '%s'", name
);
396 set_state_expr(my_id
, arg
, &ok
);
398 } END_FOR_EACH_PTR(arg
);
401 static void match_return(struct expression
*expr
)
405 if (is_impossible_path())
413 name
= expr_to_var(expr
);
414 sm_warning("returning freed memory '%s'", name
);
415 set_state_expr(my_id
, expr
, &ok
);
419 static bool is_ptr_to(struct expression
*expr
, const char *type
)
423 sym
= get_type(expr
);
424 if (!is_ptr_type(sym
))
426 sym
= get_real_base_type(sym
);
427 if (sym
&& sym
->ident
&& strcmp(sym
->ident
->name
, type
) == 0)
432 static void match_free(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
434 struct expression
*arg
;
436 if (is_impossible_path())
439 arg
= gen_expression_from_name_sym(name
, sym
);
442 if (is_ptr_to(arg
, "sk_buff") &&
443 refcount_was_inced(arg
, "->users.refs.counter"))
445 if (is_ptr_to(arg
, "buffer_head") &&
446 refcount_was_inced(arg
, "->b_count.counter"))
449 sm_error("double free of '%s'", name
);
451 track_freed_param(arg
, &freed
);
452 call_free_call_backs_name_sym(name
, sym
);
453 set_state_expr(my_id
, arg
, &freed
);
457 static void match_kobject_put(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
459 struct expression
*arg
;
461 arg
= gen_expression_from_name_sym(name
, sym
);
464 /* kobject_put(&cdev->kobj); */
465 if (arg
->type
!= EXPR_PREOP
|| arg
->op
!= '&')
467 arg
= strip_expr(arg
->unop
);
468 if (arg
->type
!= EXPR_DEREF
)
470 arg
= strip_expr(arg
->deref
);
471 if (arg
->type
!= EXPR_PREOP
|| arg
->op
!= '*')
473 arg
= strip_expr(arg
->unop
);
474 track_freed_param(arg
, &maybe_freed
);
475 set_state_expr(my_id
, arg
, &maybe_freed
);
478 static void match___skb_pad(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *data
)
480 struct expression
*arg
, *skb
;
481 struct smatch_state
*state
;
484 while (expr
&& expr
->type
== EXPR_ASSIGNMENT
)
485 expr
= strip_expr(expr
->right
);
486 if (!expr
|| expr
->type
!= EXPR_CALL
)
489 arg
= get_argument_from_call_expr(expr
->args
, 2);
490 if (expr_is_zero(arg
))
492 state
= &maybe_freed
;
493 if (get_implied_value(arg
, &sval
) && sval
.value
!= 0)
496 skb
= get_argument_from_call_expr(expr
->args
, 0);
497 track_freed_param(skb
, state
);
498 set_state_expr(my_id
, skb
, state
);
501 struct string_list
*handled
;
502 static bool is_handled_func(struct expression
*fn
)
504 if (!fn
|| fn
->type
!= EXPR_SYMBOL
|| !fn
->symbol
->ident
)
507 return list_has_string(handled
, fn
->symbol
->ident
->name
);
510 static void set_param_helper(struct expression
*expr
, int param
,
511 char *key
, char *value
,
512 struct smatch_state
*state
)
514 struct expression
*arg
;
519 while (expr
->type
== EXPR_ASSIGNMENT
)
520 expr
= strip_expr(expr
->right
);
521 if (expr
->type
!= EXPR_CALL
)
524 if (is_handled_func(expr
->fn
))
527 arg
= get_argument_from_call_expr(expr
->args
, param
);
530 name
= get_variable_from_key(arg
, key
, &sym
);
534 /* skbs are not free if we called skb_get(). */
535 if (refcount_was_inced_name_sym(name
, sym
, "->users.refs.counter"))
537 if (refcount_was_inced_name_sym(name
, sym
, "->ref.refcount.refs.counter"))
540 if (state
== &freed
&& !is_impossible_path()) {
541 sm
= get_sm_state(my_id
, name
, sym
);
542 if (sm
&& slist_has_state(sm
->possible
, &freed
)) {
543 sm_warning("'%s' double freed", name
);
544 set_state(my_id
, name
, sym
, &ok
); /* fixme: doesn't silence anything. I know */
548 track_freed_param_var_sym(name
, sym
, state
);
550 call_free_call_backs_name_sym(name
, sym
);
551 set_state(my_id
, name
, sym
, state
);
556 static void set_param_freed(struct expression
*expr
, int param
, char *key
, char *value
)
558 set_param_helper(expr
, param
, key
, value
, &freed
);
561 static void set_param_maybe_freed(struct expression
*expr
, int param
, char *key
, char *value
)
563 set_param_helper(expr
, param
, key
, value
, &maybe_freed
);
566 int parent_is_free_var_sym_strict(const char *name
, struct symbol
*sym
)
572 struct smatch_state
*state
;
574 strncpy(buf
, name
, sizeof(buf
) - 1);
575 buf
[sizeof(buf
) - 1] = '\0';
578 while ((*start
== '&'))
582 while ((end
= strrchr(end
, '-'))) {
586 state
= __get_state(my_id
, start
, sym
);
595 int parent_is_free_strict(struct expression
*expr
)
601 expr
= strip_expr(expr
);
602 var
= expr_to_var_sym(expr
, &sym
);
605 ret
= parent_is_free_var_sym_strict(var
, sym
);
611 static void match_untracked(struct expression
*call
, int param
)
613 struct state_list
*slist
= NULL
;
614 struct expression
*arg
;
620 arg
= get_argument_from_call_expr(call
->args
, param
);
624 name
= expr_to_var(arg
);
627 snprintf(buf
, sizeof(buf
), "%s->", name
);
631 FOR_EACH_MY_SM(my_id
, __get_cur_stree(), sm
) {
632 if (strncmp(sm
->name
, buf
, len
) == 0)
633 add_ptr_list(&slist
, sm
);
634 } END_FOR_EACH_SM(sm
);
636 FOR_EACH_PTR(slist
, sm
) {
637 set_state(sm
->owner
, sm
->name
, sm
->sym
, &ok
);
638 } END_FOR_EACH_PTR(sm
);
643 void check_free_strict(int id
)
645 struct func_info
*info
;
651 if (option_project
!= PROJ_KERNEL
)
654 for (i
= 0; i
< ARRAY_SIZE(func_table
); i
++) {
655 info
= &func_table
[i
];
657 insert_string(&handled
, info
->name
);
660 cb
= info
->call_back
;
664 if (info
->implies_start
) {
665 return_implies_param_key(info
->name
,
666 *info
->implies_start
, *info
->implies_end
,
667 cb
, info
->param
, info
->key
, info
);
669 add_function_param_key_hook(info
->name
, cb
,
670 info
->param
, info
->key
, info
);
675 add_hook(&match_symbol
, SYM_HOOK
);
676 add_hook(&match_dereferences
, DEREF_HOOK
);
677 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
678 add_hook(&match_return
, RETURN_HOOK
);
680 add_modification_hook_late(my_id
, &ok_to_use
);
681 add_pre_merge_hook(my_id
, &pre_merge_hook
);
682 add_unmatched_state_hook(my_id
, &unmatched_state
);
683 add_merge_hook(my_id
, &merge_frees
);
685 select_return_states_hook(PARAM_FREED
, &set_param_freed
);
686 select_return_states_hook(MAYBE_FREED
, &set_param_maybe_freed
);
687 add_untracked_param_hook(&match_untracked
);