2 * Copyright (C) 2021 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
23 #include "smatch_extra.h"
24 #include "smatch_slist.h"
28 DECLARE_PTR_LIST(alloc_hook_list
, alloc_hook
);
29 static struct alloc_hook_list
*hook_funcs_early
;
30 static struct alloc_hook_list
*hook_funcs
;
32 struct alloc_fn_info
{
38 static struct alloc_fn_info alloc_fns
[] = {
40 {"calloc", "$0 * $1", .zeroed
=true},
46 static struct alloc_fn_info kernel_alloc_funcs
[] = {
47 {"__alloc_skb", "$0"},
49 {"devm_kmalloc", "$1"},
50 {"devm_kzalloc", "$1", .zeroed
=true},
51 {"devm_kmalloc_array", "$1 * $2"},
52 {"devm_kcalloc", "$1 * $2", .zeroed
=true},
54 {"dma_alloc_attrs", "$1", .zeroed
=true},
55 {"dma_alloc_coherent", "$1", .zeroed
=true},
56 {"dma_alloc_contiguous", "$1"},
61 {"kmalloc_node", "$0"},
62 {"kzalloc", "$0", .zeroed
=true},
63 {"kzalloc_node", "$0", .zeroed
=true},
65 {"kmalloc_array", "$0 * $1"},
66 {"kcalloc", "$0 * $1", .zeroed
=true},
70 {"vzalloc", "$0", .zeroed
=true},
73 {"kvmalloc_array", "$0 * $1"},
74 {"kvmalloc_node", "$0"},
75 {"kvzalloc", "$0", .zeroed
=true},
76 {"kvcalloc", "$0 * $1", .zeroed
=true},
77 {"kvzalloc_node", "$0", .zeroed
=true},
81 {"devm_kmemdup", "$2"},
82 {"memdup_user", "$1"},
84 {"sock_kmalloc", "$1"},
87 {"get_zeroed_page", {"PAGE_SIZE", zeroed
=true}},
88 {"alloc_page", {"PAGE_SIZE"}},
89 {"alloc_pages", {"(1 < $0) * PAGE_SIZE"}},
90 {"alloc_pages_current", {"(1 < $0) * PAGE_SIZE"}},
91 {"__get_free_pages", {"(1 < $0) * PAGE_SIZE"}},
96 void add_allocation_hook(alloc_hook
*hook
)
98 add_ptr_list(&hook_funcs
, hook
);
101 void add_allocation_hook_early(alloc_hook
*hook
)
103 add_ptr_list(&hook_funcs_early
, hook
);
106 static void load_size_data(struct allocation_info
*data
, struct expression
*expr
, const char *size_str
)
108 struct expression
*call
, *arg1
, *arg2
;
124 call
= get_assigned_call(expr
);
127 arg1
= get_argument_from_call_expr(call
->args
, param
);
133 data
->total_size
= arg1
;
139 if (op
!= '*' && op
!= '+')
144 if (p
[0] != '$' || !isdigit(p
[1]))
148 arg2
= get_argument_from_call_expr(call
->args
, param
);
153 data
->nr_elems
= arg1
;
154 data
->elem_size
= arg2
;
158 static void match_alloc_helper(struct alloc_hook_list
*hooks
, struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
160 struct alloc_fn_info
*info
= _info
;
161 struct allocation_info data
= { };
164 data
.fn_name
= info
->name
;
165 data
.size_str
= info
->size
;
166 data
.zeroed
= info
->zeroed
;
167 load_size_data(&data
, expr
, info
->size
);
169 FOR_EACH_PTR(hooks
, fn
) {
170 fn(expr
, name
, sym
, &data
);
171 } END_FOR_EACH_PTR(fn
);
174 static void match_alloc_early(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
176 match_alloc_helper(hook_funcs_early
, expr
, name
, sym
, _info
);
179 static void match_alloc(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
181 match_alloc_helper(hook_funcs
, expr
, name
, sym
, _info
);
184 void register_allocations(int id
)
186 struct alloc_fn_info
*info
;
190 if (option_project
== PROJ_KERNEL
)
191 info
= kernel_alloc_funcs
;
196 add_function_param_key_hook_early(info
->name
, &match_alloc_early
, -1, "$", info
);
197 add_function_param_key_hook(info
->name
, &match_alloc
, -1, "$", info
);