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
;
31 struct alloc_fn_info
{
37 static struct alloc_fn_info alloc_fns
[] = {
39 {"calloc", "$0 * $1", .zeroed
=true},
45 static struct alloc_fn_info kernel_alloc_funcs
[] = {
46 {"__alloc_skb", "$0"},
48 {"devm_kmalloc", "$1"},
49 {"devm_kzalloc", "$1", .zeroed
=true},
50 {"devm_kmalloc_array", "$1 * $2"},
51 {"devm_kcalloc", "$1 * $2", .zeroed
=true},
53 {"dma_alloc_attrs", "$1", .zeroed
=true},
54 {"dma_alloc_coherent", "$1", .zeroed
=true},
55 {"dma_alloc_contiguous", "$1"},
60 {"kmalloc_node", "$0"},
61 {"kzalloc", "$0", .zeroed
=true},
62 {"kzalloc_node", "$0", .zeroed
=true},
64 {"kmalloc_array", "$0 * $1"},
65 {"kcalloc", "$0 * $1", .zeroed
=true},
69 {"vzalloc", "$0", .zeroed
=true},
72 {"kvmalloc_array", "$0 * $1"},
73 {"kvmalloc_node", "$0"},
74 {"kvzalloc", "$0", .zeroed
=true},
75 {"kvcalloc", "$0 * $1", .zeroed
=true},
76 {"kvzalloc_node", "$0", .zeroed
=true},
80 {"devm_kmemdup", "$2"},
81 {"memdup_user", "$1"},
83 {"sock_kmalloc", "$1"},
86 {"get_zeroed_page", {"PAGE_SIZE", zeroed
=true}},
87 {"alloc_page", {"PAGE_SIZE"}},
88 {"alloc_pages", {"(1 < $0) * PAGE_SIZE"}},
89 {"alloc_pages_current", {"(1 < $0) * PAGE_SIZE"}},
90 {"__get_free_pages", {"(1 < $0) * PAGE_SIZE"}},
95 void add_allocation_hook(alloc_hook
*hook
)
97 add_ptr_list(&hook_funcs
, hook
);
100 static void load_size_data(struct allocation_info
*data
, struct expression
*expr
, const char *size_str
)
102 struct expression
*call
, *arg1
, *arg2
;
118 call
= get_assigned_call(expr
);
121 arg1
= get_argument_from_call_expr(call
->args
, param
);
127 data
->total_size
= arg1
;
133 if (op
!= '*' && op
!= '+')
138 if (p
[0] != '$' || !isdigit(p
[1]))
142 arg2
= get_argument_from_call_expr(call
->args
, param
);
147 data
->nr_elems
= arg1
;
148 data
->elem_size
= arg2
;
152 static void match_alloc(struct expression
*expr
, const char *name
, struct symbol
*sym
, void *_info
)
154 struct alloc_fn_info
*info
= _info
;
155 struct allocation_info data
= { };
158 data
.fn_name
= info
->name
;
159 data
.size_str
= info
->size
;
160 data
.zeroed
= info
->zeroed
;
161 load_size_data(&data
, expr
, info
->size
);
163 FOR_EACH_PTR(hook_funcs
, fn
) {
164 fn(expr
, name
, sym
, &data
);
165 } END_FOR_EACH_PTR(fn
);
168 void register_allocations(int id
)
170 struct alloc_fn_info
*info
;
174 if (option_project
== PROJ_KERNEL
)
175 info
= kernel_alloc_funcs
;
180 add_function_param_key_hook(info
->name
, &match_alloc
, -1, "$", info
);