2 * sparse/check_kernel.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * This is kernel specific stuff for smatch_extra.
16 #include "smatch_extra.h"
18 static int implied_err_cast_return(struct expression
*call
, void *unused
, struct range_list
**rl
)
20 struct expression
*arg
;
22 arg
= get_argument_from_call_expr(call
->args
, 0);
23 if (!get_implied_rl(arg
, rl
))
24 *rl
= alloc_rl(ll_to_sval(-4095), ll_to_sval(-1));
28 static int implied_copy_return(struct expression
*call
, void *unused
, struct range_list
**rl
)
30 struct expression
*arg
;
33 arg
= get_argument_from_call_expr(call
->args
, 2);
34 get_absolute_max(arg
, &max
);
35 *rl
= alloc_rl(ll_to_sval(0), max
);
39 static void match_param_valid_ptr(const char *fn
, struct expression
*call_expr
,
40 struct expression
*assign_expr
, void *_param
)
42 int param
= PTR_INT(_param
);
43 struct expression
*arg
;
44 struct smatch_state
*pre_state
;
45 struct smatch_state
*end_state
;
47 arg
= get_argument_from_call_expr(call_expr
->args
, param
);
48 pre_state
= get_state_expr(SMATCH_EXTRA
, arg
);
49 end_state
= estate_filter_range(pre_state
, ll_to_sval(-4095), ll_to_sval(0));
50 set_extra_expr_nomod(arg
, end_state
);
53 static void match_param_err_or_null(const char *fn
, struct expression
*call_expr
,
54 struct expression
*assign_expr
, void *_param
)
56 int param
= PTR_INT(_param
);
57 struct expression
*arg
;
58 struct range_list
*rl
;
59 struct smatch_state
*pre_state
;
60 struct smatch_state
*end_state
;
62 arg
= get_argument_from_call_expr(call_expr
->args
, param
);
63 pre_state
= get_state_expr(SMATCH_EXTRA
, arg
);
64 rl
= alloc_rl(ll_to_sval(-4095), ll_to_sval(0));
65 rl
= rl_intersection(estate_rl(pre_state
), rl
);
66 rl
= cast_rl(estate_type(pre_state
), rl
);
67 end_state
= alloc_estate_rl(rl
);
68 set_extra_expr_nomod(arg
, end_state
);
71 static void match_not_err(const char *fn
, struct expression
*call_expr
,
72 struct expression
*assign_expr
, void *unused
)
74 struct expression
*arg
;
75 struct smatch_state
*pre_state
;
76 struct smatch_state
*new_state
;
78 arg
= get_argument_from_call_expr(call_expr
->args
, 0);
79 pre_state
= get_state_expr(SMATCH_EXTRA
, arg
);
80 new_state
= estate_filter_range(pre_state
, sval_type_min(&long_ctype
), ll_to_sval(-1));
81 set_extra_expr_nomod(arg
, new_state
);
84 static void match_err(const char *fn
, struct expression
*call_expr
,
85 struct expression
*assign_expr
, void *unused
)
87 struct expression
*arg
;
88 struct smatch_state
*pre_state
;
89 struct smatch_state
*new_state
;
91 arg
= get_argument_from_call_expr(call_expr
->args
, 0);
92 pre_state
= get_state_expr(SMATCH_EXTRA
, arg
);
93 new_state
= estate_filter_range(pre_state
, sval_type_min(&long_ctype
), ll_to_sval(-4096));
94 new_state
= estate_filter_range(new_state
, ll_to_sval(0), sval_type_max(&long_ctype
));
95 set_extra_expr_nomod(arg
, new_state
);
98 static void match_container_of(const char *fn
, struct expression
*expr
, void *unused
)
100 set_extra_expr_mod(expr
->left
, alloc_estate_range(valid_ptr_min_sval
, valid_ptr_max_sval
));
103 static int match_next_bit(struct expression
*call
, void *unused
, struct range_list
**rl
)
105 struct expression
*start_arg
;
106 struct expression
*size_arg
;
108 sval_t min
, max
, tmp
;
110 size_arg
= get_argument_from_call_expr(call
->args
, 1);
111 /* btw. there isn't a start_arg for find_first_bit() */
112 start_arg
= get_argument_from_call_expr(call
->args
, 2);
114 type
= get_type(call
);
115 min
= sval_type_val(type
, 0);
116 max
= sval_type_val(type
, sizeof(long long) * 8);
118 if (get_implied_max(size_arg
, &tmp
) && tmp
.uvalue
< max
.value
)
120 if (start_arg
&& get_implied_min(start_arg
, &tmp
) && !sval_is_negative(tmp
))
122 if (sval_cmp(min
, max
) > 0)
124 min
= sval_cast(type
, min
);
125 max
= sval_cast(type
, max
);
126 *rl
= alloc_rl(min
, max
);
130 static void find_module_init_exit(struct symbol_list
*sym_list
)
134 struct statement
*stmt
;
140 * This is more complicated because Sparse ignores the "alias"
141 * attribute. I search backwards because module_init() is normally at
142 * the end of the file.
145 FOR_EACH_PTR_REVERSE(sym_list
, sym
) {
146 if (sym
->type
!= SYM_NODE
)
148 if (!(sym
->ctype
.modifiers
& MOD_STATIC
))
150 fn
= get_base_type(sym
);
153 if (fn
->type
!= SYM_FN
)
155 if (!sym
->ident
|| !sym
->ident
->name
)
157 if (!fn
->inline_stmt
)
159 if (strcmp(sym
->ident
->name
, "__inittest") == 0)
161 else if (strcmp(sym
->ident
->name
, "__exittest") == 0)
168 stmt
= first_ptr_list((struct ptr_list
*)fn
->inline_stmt
->stmts
);
169 if (!stmt
|| stmt
->type
!= STMT_RETURN
)
171 name
= expr_to_var(stmt
->ret_value
);
175 sql_insert_function_ptr(name
, "(struct module)->init");
177 sql_insert_function_ptr(name
, "(struct module)->exit");
181 } END_FOR_EACH_PTR_REVERSE(sym
);
184 static void match_end_file(struct symbol_list
*sym_list
)
188 /* find the last static symbol in the file */
189 FOR_EACH_PTR_REVERSE(sym_list
, sym
) {
190 if (!(sym
->ctype
.modifiers
& MOD_STATIC
))
194 find_module_init_exit(sym
->scope
->symbols
);
196 } END_FOR_EACH_PTR_REVERSE(sym
);
199 void check_kernel(int id
)
201 if (option_project
!= PROJ_KERNEL
)
204 add_implied_return_hook("ERR_PTR", &implied_err_cast_return
, NULL
);
205 add_implied_return_hook("ERR_CAST", &implied_err_cast_return
, NULL
);
206 add_implied_return_hook("PTR_ERR", &implied_err_cast_return
, NULL
);
207 return_implies_state("IS_ERR_OR_NULL", 0, 0, &match_param_valid_ptr
, (void *)0);
208 return_implies_state("IS_ERR_OR_NULL", 1, 1, &match_param_err_or_null
, (void *)0);
209 return_implies_state("IS_ERR", 0, 0, &match_not_err
, NULL
);
210 return_implies_state("IS_ERR", 1, 1, &match_err
, NULL
);
211 return_implies_state("tomoyo_memory_ok", 1, 1, &match_param_valid_ptr
, (void *)0);
212 add_macro_assign_hook_extra("container_of", &match_container_of
, NULL
);
214 add_implied_return_hook("copy_to_user", &implied_copy_return
, NULL
);
215 add_implied_return_hook("__copy_to_user", &implied_copy_return
, NULL
);
216 add_implied_return_hook("copy_from_user", &implied_copy_return
, NULL
);
217 add_implied_return_hook("__copy_fom_user", &implied_copy_return
, NULL
);
218 add_implied_return_hook("clear_user", &implied_copy_return
, NULL
);
220 add_implied_return_hook("find_next_bit", &match_next_bit
, NULL
);
221 add_implied_return_hook("find_next_zero_bit", &match_next_bit
, NULL
);
222 add_implied_return_hook("find_first_bit", &match_next_bit
, NULL
);
223 add_implied_return_hook("find_first_zero_bit", &match_next_bit
, NULL
);
225 add_function_hook("__ftrace_bad_type", &__match_nullify_path_hook
, NULL
);
228 add_hook(match_end_file
, END_FILE_HOOK
);