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 {"comedi_alloc_spriv", "$1", .zeroed
=true},
51 {"devm_kmalloc", "$1"},
52 {"devm_kzalloc", "$1", .zeroed
=true},
53 {"devm_kmalloc_array", "$1 * $2"},
54 {"devm_kcalloc", "$1 * $2", .zeroed
=true},
56 {"dma_alloc_attrs", "$1", .zeroed
=true},
57 {"dma_alloc_coherent", "$1", .zeroed
=true},
58 {"dma_alloc_contiguous", "$1"},
63 {"kmalloc_node", "$0"},
64 {"kmalloc_noprof", "$0"},
65 {"kzalloc", "$0", .zeroed
=true},
66 {"kzalloc_node", "$0", .zeroed
=true},
67 {"kzalloc_noprof", "$0", .zeroed
=true},
69 {"kmalloc_array", "$0 * $1"},
70 {"kcalloc", "$0 * $1", .zeroed
=true},
74 {"vzalloc", "$0", .zeroed
=true},
77 {"kvmalloc_array", "$0 * $1"},
78 {"kvmalloc_node", "$0"},
79 {"kvzalloc", "$0", .zeroed
=true},
80 {"kvcalloc", "$0 * $1", .zeroed
=true},
81 {"kvzalloc_node", "$0", .zeroed
=true},
85 {"devm_kmemdup", "$2"},
86 {"memdup_user", "$1"},
89 {"sk_prot_alloc", ""},
90 {"sock_kmalloc", "$1"},
93 {"get_zeroed_page", {"PAGE_SIZE", zeroed
=true}},
94 {"alloc_page", {"PAGE_SIZE"}},
95 {"alloc_pages", {"(1 < $0) * PAGE_SIZE"}},
96 {"alloc_pages_current", {"(1 < $0) * PAGE_SIZE"}},
97 {"__get_free_pages", {"(1 < $0) * PAGE_SIZE"}},
102 void add_allocation_hook(alloc_hook
*hook
)
104 add_ptr_list(&hook_funcs
, hook
);
107 void add_allocation_hook_early(alloc_hook
*hook
)
109 add_ptr_list(&hook_funcs_early
, hook
);
112 static void load_size_data(struct allocation_info
*data
, struct expression
*expr
, const char *size_str
)
114 struct expression
*call
, *arg1
, *arg2
;
130 call
= get_assigned_call(expr
);
133 arg1
= get_argument_from_call_expr(call
->args
, param
);
139 data
->total_size
= arg1
;
145 if (op
!= '*' && op
!= '+')
150 if (p
[0] != '$' || !isdigit(p
[1]))
154 arg2
= get_argument_from_call_expr(call
->args
, param
);
159 data
->nr_elems
= arg1
;
160 data
->elem_size
= arg2
;
164 static void match_alloc_helper(struct alloc_hook_list
*hooks
, struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
166 struct alloc_fn_info
*info
= _info
;
167 struct allocation_info data
= { };
170 data
.fn_name
= info
->name
;
171 data
.size_str
= info
->size
;
172 data
.zeroed
= info
->zeroed
;
173 load_size_data(&data
, expr
, info
->size
);
175 FOR_EACH_PTR(hooks
, fn
) {
176 fn(expr
, name
, sym
, &data
);
177 } END_FOR_EACH_PTR(fn
);
180 static void match_alloc_early(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
182 match_alloc_helper(hook_funcs_early
, expr
, name
, sym
, _info
);
185 static void match_alloc(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
187 match_alloc_helper(hook_funcs
, expr
, name
, sym
, _info
);
190 void register_allocations(int id
)
192 struct alloc_fn_info
*info
;
196 if (option_project
== PROJ_KERNEL
)
197 info
= kernel_alloc_funcs
;
202 add_function_param_key_hook_early(info
->name
, &match_alloc_early
, -1, "$", info
);
203 add_function_param_key_hook(info
->name
, &match_alloc
, -1, "$", info
);