Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_kernel_user_data.c
+++ new/usr/src/tools/smatch/src/smatch_kernel_user_data.c
1 1 /*
2 2 * Copyright (C) 2011 Dan Carpenter.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 /*
19 19 * There are a couple checks that try to see if a variable
20 20 * comes from the user. It would be better to unify them
21 21 * into one place. Also it we should follow the data down
22 22 * the call paths. Hence this file.
23 23 */
24 24
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
25 25 #include "smatch.h"
26 26 #include "smatch_slist.h"
27 27 #include "smatch_extra.h"
28 28
29 29 static int my_id;
30 30 static int my_call_id;
31 31
32 32 STATE(called);
33 33 static bool func_gets_user_data;
34 34
35 -static const char * kstr_funcs[] = {
35 +static const char *kstr_funcs[] = {
36 36 "kstrtoull", "kstrtoll", "kstrtoul", "kstrtol", "kstrtouint",
37 37 "kstrtoint", "kstrtou64", "kstrtos64", "kstrtou32", "kstrtos32",
38 38 "kstrtou16", "kstrtos16", "kstrtou8", "kstrtos8", "kstrtoull_from_user"
39 39 "kstrtoll_from_user", "kstrtoul_from_user", "kstrtol_from_user",
40 40 "kstrtouint_from_user", "kstrtoint_from_user", "kstrtou16_from_user",
41 41 "kstrtos16_from_user", "kstrtou8_from_user", "kstrtos8_from_user",
42 42 "kstrtou64_from_user", "kstrtos64_from_user", "kstrtou32_from_user",
43 43 "kstrtos32_from_user",
44 44 };
45 45
46 46 static const char *returns_user_data[] = {
47 47 "simple_strtol", "simple_strtoll", "simple_strtoul", "simple_strtoull",
48 - "kvm_register_read", "nlmsg_data", "nla_data", "memdup_user",
49 - "kmap_atomic", "skb_network_header",
48 + "kvm_register_read",
50 49 };
51 50
51 +static const char *returns_pointer_to_user_data[] = {
52 + "nlmsg_data", "nla_data", "memdup_user", "kmap_atomic", "skb_network_header",
53 +};
54 +
52 55 static void set_points_to_user_data(struct expression *expr);
53 56
54 57 static struct stree *start_states;
55 58 static struct stree_stack *saved_stack;
56 59 static void save_start_states(struct statement *stmt)
57 60 {
58 61 start_states = clone_stree(__get_cur_stree());
59 62 }
60 63
61 64 static void free_start_states(void)
62 65 {
63 66 free_stree(&start_states);
64 67 }
65 68
66 69 static void match_save_states(struct expression *expr)
67 70 {
68 71 push_stree(&saved_stack, start_states);
69 72 start_states = NULL;
70 73 }
71 74
72 75 static void match_restore_states(struct expression *expr)
73 76 {
74 77 free_stree(&start_states);
75 78 start_states = pop_stree(&saved_stack);
76 79 }
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
77 80
78 81 static struct smatch_state *empty_state(struct sm_state *sm)
79 82 {
80 83 return alloc_estate_empty();
81 84 }
82 85
83 86 static void pre_merge_hook(struct sm_state *sm)
84 87 {
85 88 struct smatch_state *user;
86 89 struct smatch_state *extra;
90 + struct smatch_state *state;
87 91 struct range_list *rl;
88 92 sval_t dummy;
89 93 sval_t sval_100;
90 94
91 95 sval_100.value = 100;
92 96 sval_100.type = &int_ctype;
93 97
94 - user = get_state(my_id, sm->name, sm->sym);
95 - if (!user)
98 + user = __get_state(my_id, sm->name, sm->sym);
99 + if (!user || !estate_rl(user))
96 100 return;
97 - if (!__in_function_def && !estate_rl(sm->state)) {
98 - /*
99 - * If the one side is capped and the other side is empty then
100 - * let's just mark it as not-user data because the information
101 - * isn't going to be useful. How this looks is:
102 - *
103 - * if (user_var > trusted)
104 - * user_var = trusted; <-- empty state
105 - * else
106 - * <-- capped
107 - *
108 - * The problem is that sometimes things are capped to a literal
109 - * and we'd like to keep the state in that case... Ugh. I've
110 - * added a check which assumes that everything less than 100 is
111 - * probably capped against a literal.
112 - *
113 - */
114 - if (is_capped_var_sym(sm->name, sm->sym) &&
115 - sval_cmp(estate_max(user), sval_100) > 0)
116 - set_state(my_id, sm->name, sm->sym, alloc_estate_empty());
101 + extra = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
102 + if (!extra)
117 103 return;
118 - }
119 - extra = get_state(SMATCH_EXTRA, sm->name, sm->sym);
120 - if (!extra || !estate_rl(extra))
121 - return;
122 104 rl = rl_intersection(estate_rl(user), estate_rl(extra));
123 105 if (rl_to_sval(rl, &dummy))
124 106 rl = NULL;
125 - set_state(my_id, sm->name, sm->sym, alloc_estate_rl(clone_rl(rl)));
107 + state = alloc_estate_rl(clone_rl(rl));
108 + if (estate_capped(user) || is_capped_var_sym(sm->name, sm->sym))
109 + estate_set_capped(state);
110 + set_state(my_id, sm->name, sm->sym, state);
126 111 }
127 112
128 113 static void extra_nomod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
129 114 {
130 - struct smatch_state *user;
115 + struct smatch_state *user, *new;
131 116 struct range_list *rl;
132 117
133 - user = get_state(my_id, name, sym);
118 + user = __get_state(my_id, name, sym);
134 119 if (!user)
135 120 return;
136 121 rl = rl_intersection(estate_rl(user), estate_rl(state));
137 122 if (rl_equiv(rl, estate_rl(user)))
138 123 return;
139 - set_state(my_id, name, sym, alloc_estate_rl(rl));
124 + new = alloc_estate_rl(rl);
125 + if (estate_capped(user))
126 + estate_set_capped(new);
127 + set_state(my_id, name, sym, new);
140 128 }
141 129
130 +static bool binop_capped(struct expression *expr)
131 +{
132 + struct range_list *left_rl;
133 + int comparison;
134 +
135 + if (expr->op == '-' && get_user_rl(expr->left, &left_rl)) {
136 + if (user_rl_capped(expr->left))
137 + return true;
138 + comparison = get_comparison(expr->left, expr->right);
139 + if (comparison && show_special(comparison)[0] == '>')
140 + return true;
141 + return false;
142 + }
143 +
144 + if (expr->op == '&' || expr->op == '%') {
145 + if (is_capped(expr->left) || is_capped(expr->right))
146 + return true;
147 + if (user_rl_capped(expr->left) || user_rl_capped(expr->right))
148 + return true;
149 + return false;
150 + }
151 +
152 + if (user_rl_capped(expr->left) &&
153 + user_rl_capped(expr->right))
154 + return true;
155 + return false;
156 +}
157 +
158 +bool user_rl_capped(struct expression *expr)
159 +{
160 + struct smatch_state *state;
161 + struct range_list *rl;
162 + sval_t sval;
163 +
164 + expr = strip_expr(expr);
165 + if (!expr)
166 + return false;
167 + if (get_value(expr, &sval))
168 + return true;
169 + if (expr->type == EXPR_BINOP)
170 + return binop_capped(expr);
171 + if ((expr->type == EXPR_PREOP || expr->type == EXPR_POSTOP) &&
172 + (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT))
173 + return user_rl_capped(expr->unop);
174 + state = get_state_expr(my_id, expr);
175 + if (state)
176 + return estate_capped(state);
177 +
178 + if (get_user_rl(expr, &rl))
179 + return false; /* uncapped user data */
180 +
181 + return true; /* not actually user data */
182 +}
183 +
142 184 static void tag_inner_struct_members(struct expression *expr, struct symbol *member)
143 185 {
144 186 struct expression *edge_member;
145 187 struct symbol *base = get_real_base_type(member);
146 188 struct symbol *tmp;
147 189
148 190 if (member->ident)
149 191 expr = member_expression(expr, '.', member->ident);
150 192
151 193 FOR_EACH_PTR(base->symbol_list, tmp) {
152 194 struct symbol *type;
153 195
154 196 type = get_real_base_type(tmp);
155 197 if (!type)
156 198 continue;
157 199
158 200 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
159 201 tag_inner_struct_members(expr, tmp);
160 202 continue;
161 203 }
162 204
163 205 if (!tmp->ident)
164 206 continue;
165 207
166 208 edge_member = member_expression(expr, '.', tmp->ident);
167 209 set_state_expr(my_id, edge_member, alloc_estate_whole(type));
168 210 } END_FOR_EACH_PTR(tmp);
169 211 }
170 212
171 213 static void tag_struct_members(struct symbol *type, struct expression *expr)
172 214 {
173 215 struct symbol *tmp;
174 216 struct expression *member;
175 217 int op = '*';
176 218
177 219 if (expr->type == EXPR_PREOP && expr->op == '&') {
178 220 expr = strip_expr(expr->unop);
179 221 op = '.';
180 222 }
181 223
182 224 FOR_EACH_PTR(type->symbol_list, tmp) {
183 225 type = get_real_base_type(tmp);
184 226 if (!type)
185 227 continue;
186 228
187 229 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
188 230 tag_inner_struct_members(expr, tmp);
189 231 continue;
190 232 }
191 233
192 234 if (!tmp->ident)
193 235 continue;
194 236
195 237 member = member_expression(expr, op, tmp->ident);
196 238 set_state_expr(my_id, member, alloc_estate_whole(get_type(member)));
197 239
198 240 if (type->type == SYM_ARRAY)
199 241 set_points_to_user_data(member);
200 242 } END_FOR_EACH_PTR(tmp);
201 243 }
202 244
203 245 static void tag_base_type(struct expression *expr)
204 246 {
205 247 if (expr->type == EXPR_PREOP && expr->op == '&')
206 248 expr = strip_expr(expr->unop);
207 249 else
208 250 expr = deref_expression(expr);
209 251 set_state_expr(my_id, expr, alloc_estate_whole(get_type(expr)));
210 252 }
211 253
212 254 static void tag_as_user_data(struct expression *expr)
213 255 {
214 256 struct symbol *type;
215 257
216 258 expr = strip_expr(expr);
217 259
218 260 type = get_type(expr);
219 261 if (!type || type->type != SYM_PTR)
220 262 return;
221 263 type = get_real_base_type(type);
222 264 if (!type)
223 265 return;
224 266 if (type == &void_ctype) {
225 267 set_state_expr(my_id, deref_expression(expr), alloc_estate_whole(&ulong_ctype));
226 268 return;
227 269 }
228 270 if (type->type == SYM_BASETYPE)
229 271 tag_base_type(expr);
230 272 if (type->type == SYM_STRUCT || type->type == SYM_UNION) {
231 273 if (expr->type != EXPR_PREOP || expr->op != '&')
232 274 expr = deref_expression(expr);
233 275 else
234 276 set_state_expr(my_id, deref_expression(expr), alloc_estate_whole(&ulong_ctype));
235 277 tag_struct_members(type, expr);
236 278 }
237 279 }
238 280
239 281 static void match_user_copy(const char *fn, struct expression *expr, void *_param)
240 282 {
241 283 int param = PTR_INT(_param);
242 284 struct expression *dest;
243 285
244 286 func_gets_user_data = true;
245 287
246 288 dest = get_argument_from_call_expr(expr->args, param);
247 289 dest = strip_expr(dest);
248 290 if (!dest)
249 291 return;
250 292 tag_as_user_data(dest);
251 293 }
252 294
253 295 static int is_dev_attr_name(struct expression *expr)
254 296 {
255 297 char *name;
256 298 int ret = 0;
257 299
258 300 name = expr_to_str(expr);
259 301 if (!name)
260 302 return 0;
261 303 if (strstr(name, "->attr.name"))
262 304 ret = 1;
263 305 free_string(name);
264 306 return ret;
265 307 }
266 308
267 309 static int ends_in_n(struct expression *expr)
268 310 {
269 311 struct string *str;
270 312
271 313 if (!expr)
272 314 return 0;
273 315 if (expr->type != EXPR_STRING || !expr->string)
274 316 return 0;
275 317
276 318 str = expr->string;
277 319 if (str->length < 3)
278 320 return 0;
279 321
280 322 if (str->data[str->length - 3] == '%' &&
281 323 str->data[str->length - 2] == 'n')
282 324 return 1;
283 325 return 0;
284 326 }
285 327
286 328 static void match_sscanf(const char *fn, struct expression *expr, void *unused)
287 329 {
288 330 struct expression *str, *format, *arg;
289 331 int i, last;
290 332
291 333 func_gets_user_data = true;
292 334
293 335 str = get_argument_from_call_expr(expr->args, 0);
294 336 if (is_dev_attr_name(str))
295 337 return;
296 338
297 339 format = get_argument_from_call_expr(expr->args, 1);
298 340 if (is_dev_attr_name(format))
299 341 return;
300 342
301 343 last = ptr_list_size((struct ptr_list *)expr->args) - 1;
302 344
303 345 i = -1;
304 346 FOR_EACH_PTR(expr->args, arg) {
305 347 i++;
306 348 if (i < 2)
307 349 continue;
308 350 if (i == last && ends_in_n(format))
309 351 continue;
310 352 tag_as_user_data(arg);
311 353 } END_FOR_EACH_PTR(arg);
312 354 }
313 355
314 356 static int is_skb_data(struct expression *expr)
315 357 {
316 358 struct symbol *sym;
317 359
318 360 if (!expr)
319 361 return 0;
320 362
321 363 if (expr->type == EXPR_BINOP && expr->op == '+')
322 364 return is_skb_data(expr->left);
323 365
324 366 expr = strip_expr(expr);
325 367 if (!expr)
326 368 return 0;
327 369 if (expr->type != EXPR_DEREF || expr->op != '.')
328 370 return 0;
329 371
330 372 if (!expr->member)
331 373 return 0;
332 374 if (strcmp(expr->member->name, "data") != 0)
333 375 return 0;
334 376
335 377 sym = expr_to_sym(expr->deref);
336 378 if (!sym)
337 379 return 0;
338 380 sym = get_real_base_type(sym);
339 381 if (!sym || sym->type != SYM_PTR)
↓ open down ↓ |
188 lines elided |
↑ open up ↑ |
340 382 return 0;
341 383 sym = get_real_base_type(sym);
342 384 if (!sym || sym->type != SYM_STRUCT || !sym->ident)
343 385 return 0;
344 386 if (strcmp(sym->ident->name, "sk_buff") != 0)
345 387 return 0;
346 388
347 389 return 1;
348 390 }
349 391
392 +static bool is_points_to_user_data_fn(struct expression *expr)
393 +{
394 + int i;
395 +
396 + expr = strip_expr(expr);
397 + if (expr->type != EXPR_CALL || expr->fn->type != EXPR_SYMBOL ||
398 + !expr->fn->symbol)
399 + return false;
400 + expr = expr->fn;
401 + for (i = 0; i < ARRAY_SIZE(returns_pointer_to_user_data); i++) {
402 + if (sym_name_is(returns_pointer_to_user_data[i], expr))
403 + return true;
404 + }
405 + return false;
406 +}
407 +
350 408 static int get_rl_from_function(struct expression *expr, struct range_list **rl)
351 409 {
352 410 int i;
353 411
354 412 if (expr->type != EXPR_CALL || expr->fn->type != EXPR_SYMBOL ||
355 413 !expr->fn->symbol_name || !expr->fn->symbol_name->name)
356 414 return 0;
357 415
358 416 for (i = 0; i < ARRAY_SIZE(returns_user_data); i++) {
359 417 if (strcmp(expr->fn->symbol_name->name, returns_user_data[i]) == 0) {
360 418 *rl = alloc_whole_rl(get_type(expr));
361 419 return 1;
362 420 }
363 421 }
364 422 return 0;
365 423 }
366 424
367 425 int points_to_user_data(struct expression *expr)
368 426 {
369 427 struct smatch_state *state;
370 428 struct range_list *rl;
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
371 429 char buf[256];
372 430 struct symbol *sym;
373 431 char *name;
374 432 int ret = 0;
375 433
376 434 expr = strip_expr(expr);
377 435 if (!expr)
378 436 return 0;
379 437 if (is_skb_data(expr))
380 438 return 1;
439 + if (is_points_to_user_data_fn(expr))
440 + return 1;
381 441 if (get_rl_from_function(expr, &rl))
382 442 return 1;
383 443
384 444 if (expr->type == EXPR_BINOP && expr->op == '+') {
385 445 if (points_to_user_data(expr->left))
386 446 return 1;
387 447 if (points_to_user_data(expr->right))
388 448 return 1;
389 449 return 0;
390 450 }
391 451
392 452 name = expr_to_var_sym(expr, &sym);
393 453 if (!name || !sym)
394 454 goto free;
395 455 snprintf(buf, sizeof(buf), "*%s", name);
396 - state = get_state(my_id, buf, sym);
456 + state = __get_state(my_id, buf, sym);
397 457 if (state && estate_rl(state))
398 458 ret = 1;
399 459 free:
400 460 free_string(name);
401 461 return ret;
402 462 }
403 463
404 464 static void set_points_to_user_data(struct expression *expr)
405 465 {
406 466 char *name;
407 467 struct symbol *sym;
408 468 char buf[256];
469 + struct symbol *type;
409 470
410 471 name = expr_to_var_sym(expr, &sym);
411 472 if (!name || !sym)
412 473 goto free;
413 474 snprintf(buf, sizeof(buf), "*%s", name);
414 - set_state(my_id, buf, sym, alloc_estate_whole(&llong_ctype));
475 + type = get_type(expr);
476 + if (type && type->type == SYM_PTR)
477 + type = get_real_base_type(type);
478 + if (!type || type->type != SYM_BASETYPE)
479 + type = &llong_ctype;
480 + set_state(my_id, buf, sym, alloc_estate_whole(type));
415 481 free:
416 482 free_string(name);
417 483 }
418 484
419 485 static int comes_from_skb_data(struct expression *expr)
420 486 {
421 487 expr = strip_expr(expr);
422 488 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
423 489 return 0;
424 490
425 491 expr = strip_expr(expr->unop);
426 492 if (!expr)
427 493 return 0;
428 494 if (expr->type == EXPR_BINOP && expr->op == '+')
429 495 expr = strip_expr(expr->left);
430 496
431 497 return is_skb_data(expr);
432 498 }
433 499
434 500 static int handle_struct_assignment(struct expression *expr)
435 501 {
436 502 struct expression *right;
437 503 struct symbol *left_type, *right_type;
438 504
439 505 left_type = get_type(expr->left);
440 506 if (!left_type || left_type->type != SYM_PTR)
441 507 return 0;
442 508 left_type = get_real_base_type(left_type);
443 509 if (!left_type)
444 510 return 0;
445 511 if (left_type->type != SYM_STRUCT &&
446 512 left_type->type != SYM_UNION)
447 513 return 0;
448 514
449 515 /*
450 516 * Ignore struct to struct assignments because for those we look at the
451 517 * individual members.
452 518 */
453 519 right = strip_expr(expr->right);
454 520 right_type = get_type(right);
455 521 if (!right_type || right_type->type != SYM_PTR)
456 522 return 0;
457 523
458 524 /* If we are assigning struct members then normally that is handled
459 525 * by fake assignments, however if we cast one struct to a different
460 526 * of struct then we handle that here.
461 527 */
462 528 right_type = get_real_base_type(right_type);
463 529 if (right_type == left_type)
464 530 return 0;
465 531
466 532 if (!points_to_user_data(right))
467 533 return 0;
468 534
469 535 tag_as_user_data(expr->left);
470 536 return 1;
471 537 }
472 538
473 539 static int handle_get_user(struct expression *expr)
474 540 {
475 541 char *name;
476 542 int ret = 0;
477 543
478 544 name = get_macro_name(expr->pos);
479 545 if (!name || strcmp(name, "get_user") != 0)
480 546 return 0;
481 547
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
482 548 name = expr_to_var(expr->right);
483 549 if (!name || strcmp(name, "__val_gu") != 0)
484 550 goto free;
485 551 set_state_expr(my_id, expr->left, alloc_estate_whole(get_type(expr->left)));
486 552 ret = 1;
487 553 free:
488 554 free_string(name);
489 555 return ret;
490 556 }
491 557
558 +static bool handle_op_assign(struct expression *expr)
559 +{
560 + struct expression *binop_expr;
561 + struct smatch_state *state;
562 + struct range_list *rl;
563 +
564 + switch (expr->op) {
565 + case SPECIAL_ADD_ASSIGN:
566 + case SPECIAL_SUB_ASSIGN:
567 + case SPECIAL_AND_ASSIGN:
568 + case SPECIAL_MOD_ASSIGN:
569 + case SPECIAL_SHL_ASSIGN:
570 + case SPECIAL_SHR_ASSIGN:
571 + case SPECIAL_OR_ASSIGN:
572 + case SPECIAL_XOR_ASSIGN:
573 + case SPECIAL_MUL_ASSIGN:
574 + case SPECIAL_DIV_ASSIGN:
575 + binop_expr = binop_expression(expr->left,
576 + op_remove_assign(expr->op),
577 + expr->right);
578 + if (!get_user_rl(binop_expr, &rl))
579 + return true;
580 +
581 + rl = cast_rl(get_type(expr->left), rl);
582 + state = alloc_estate_rl(rl);
583 + if (user_rl_capped(binop_expr))
584 + estate_set_capped(state);
585 + set_state_expr(my_id, expr->left, state);
586 + return true;
587 + }
588 + return false;
589 +}
590 +
492 591 static void match_assign(struct expression *expr)
493 592 {
494 593 struct range_list *rl;
594 + static struct expression *handled;
595 + struct smatch_state *state;
596 + struct expression *faked;
495 597
598 + faked = get_faked_expression();
599 + if (faked && faked == handled)
600 + return;
496 601 if (is_fake_call(expr->right))
497 602 goto clear_old_state;
498 603 if (handle_get_user(expr))
499 604 return;
500 - if (points_to_user_data(expr->right))
605 + if (points_to_user_data(expr->right)) {
606 + handled = expr;
501 607 set_points_to_user_data(expr->left);
608 + }
502 609 if (handle_struct_assignment(expr))
503 610 return;
504 611
612 + if (handle_op_assign(expr))
613 + return;
614 + if (expr->op != '=')
615 + goto clear_old_state;
616 +
617 + /* Handled by DB code */
618 + if (expr->right->type == EXPR_CALL || __in_fake_parameter_assign)
619 + return;
620 +
505 621 if (!get_user_rl(expr->right, &rl))
506 622 goto clear_old_state;
507 623
508 624 rl = cast_rl(get_type(expr->left), rl);
509 - set_state_expr(my_id, expr->left, alloc_estate_rl(rl));
625 + state = alloc_estate_rl(rl);
626 + if (user_rl_capped(expr->right))
627 + estate_set_capped(state);
628 + set_state_expr(my_id, expr->left, state);
510 629
511 630 return;
512 631
513 632 clear_old_state:
514 633 if (get_state_expr(my_id, expr->left))
515 634 set_state_expr(my_id, expr->left, alloc_estate_empty());
516 635 }
517 636
518 637 static void handle_eq_noteq(struct expression *expr)
519 638 {
520 639 struct smatch_state *left_orig, *right_orig;
521 640
522 641 left_orig = get_state_expr(my_id, expr->left);
523 642 right_orig = get_state_expr(my_id, expr->right);
524 643
525 644 if (!left_orig && !right_orig)
526 645 return;
527 646 if (left_orig && right_orig)
528 647 return;
529 648
530 649 if (left_orig) {
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
531 650 set_true_false_states_expr(my_id, expr->left,
532 651 expr->op == SPECIAL_EQUAL ? alloc_estate_empty() : NULL,
533 652 expr->op == SPECIAL_EQUAL ? NULL : alloc_estate_empty());
534 653 } else {
535 654 set_true_false_states_expr(my_id, expr->right,
536 655 expr->op == SPECIAL_EQUAL ? alloc_estate_empty() : NULL,
537 656 expr->op == SPECIAL_EQUAL ? NULL : alloc_estate_empty());
538 657 }
539 658 }
540 659
541 -static void handle_unsigned_lt_gt(struct expression *expr)
660 +static struct range_list *strip_negatives(struct range_list *rl)
542 661 {
662 + sval_t min = rl_min(rl);
663 + sval_t minus_one;
664 + sval_t over;
665 + sval_t max = sval_type_max(rl_type(rl));
666 +
667 + minus_one.type = rl_type(rl);
668 + minus_one.value = INT_MAX + 1ULL;
669 + over.type = rl_type(rl);
670 + over.value = -1;
671 +
672 + if (!rl)
673 + return NULL;
674 +
675 + if (type_unsigned(rl_type(rl)) && type_bits(rl_type(rl)) > 31)
676 + return remove_range(rl, over, max);
677 +
678 + return remove_range(rl, min, minus_one);
679 +}
680 +
681 +static void handle_compare(struct expression *expr)
682 +{
683 + struct expression *left, *right;
684 + struct range_list *left_rl = NULL;
685 + struct range_list *right_rl = NULL;
686 + struct range_list *user_rl;
687 + struct smatch_state *capped_state;
688 + struct smatch_state *left_true = NULL;
689 + struct smatch_state *left_false = NULL;
690 + struct smatch_state *right_true = NULL;
691 + struct smatch_state *right_false = NULL;
543 692 struct symbol *type;
544 - struct range_list *left;
545 - struct range_list *right;
546 - struct range_list *non_negative;
547 - sval_t min, minus_one;
693 + sval_t sval;
548 694
695 + left = strip_expr(expr->left);
696 + right = strip_expr(expr->right);
697 +
698 + while (left->type == EXPR_ASSIGNMENT)
699 + left = strip_expr(left->left);
700 +
549 701 /*
550 - * conditions are mostly handled by smatch_extra.c. The special case
551 - * here is that say you have if (user_int < unknown_u32) {
552 - * In Smatch extra we say that, We have no idea what value
553 - * unknown_u32 is so the only thin we can say for sure is that
554 - * user_int is not -1 (UINT_MAX). But in check_user_data2.c we should
555 - * assume that unless unknown_u32 is user data, it's probably less than
556 - * INT_MAX.
702 + * Conditions are mostly handled by smatch_extra.c, but there are some
703 + * times where the exact values are not known so we can't do that.
557 704 *
705 + * Normally, we might consider using smatch_capped.c to supliment smatch
706 + * extra but that doesn't work when we merge unknown uncapped kernel
707 + * data with unknown capped user data. The result is uncapped user
708 + * data. We need to keep it separate and say that the user data is
709 + * capped. In the past, I would have marked this as just regular
710 + * kernel data (not user data) but we can't do that these days because
711 + * we need to track user data for Spectre.
712 + *
713 + * The other situation which we have to handle is when we do have an
714 + * int and we compare against an unknown unsigned kernel variable. In
715 + * that situation we assume that the kernel data is less than INT_MAX.
716 + * Otherwise then we get all sorts of array underflow false positives.
717 + *
558 718 */
559 719
560 - type = get_type(expr);
561 - if (!type_unsigned(type))
720 + /* Handled in smatch_extra.c */
721 + if (get_implied_value(left, &sval) ||
722 + get_implied_value(right, &sval))
562 723 return;
563 724
564 - /*
565 - * Assume if (user < trusted) { ... because I am lazy and because this
566 - * is the correct way to write code.
567 - */
568 - if (!get_user_rl(expr->left, &left))
725 + get_user_rl(left, &left_rl);
726 + get_user_rl(right, &right_rl);
727 +
728 + /* nothing to do */
729 + if (!left_rl && !right_rl)
569 730 return;
570 - if (get_user_rl(expr->right, &right))
731 + /* if both sides are user data that's not a good limit */
732 + if (left_rl && right_rl)
571 733 return;
572 734
573 - if (!sval_is_negative(rl_min(left)))
574 - return;
575 - min = rl_min(left);
576 - minus_one.type = rl_type(left);
577 - minus_one.value = -1;
578 - non_negative = remove_range(left, min, minus_one);
735 + if (left_rl)
736 + user_rl = left_rl;
737 + else
738 + user_rl = right_rl;
579 739
740 + type = get_type(expr);
741 + if (type_unsigned(type))
742 + user_rl = strip_negatives(user_rl);
743 + capped_state = alloc_estate_rl(user_rl);
744 + estate_set_capped(capped_state);
745 +
580 746 switch (expr->op) {
581 747 case '<':
582 748 case SPECIAL_UNSIGNED_LT:
583 749 case SPECIAL_LTE:
584 750 case SPECIAL_UNSIGNED_LTE:
585 - set_true_false_states_expr(my_id, expr->left,
586 - alloc_estate_rl(non_negative), NULL);
751 + if (left_rl)
752 + left_true = capped_state;
753 + else
754 + right_false = capped_state;
587 755 break;
588 756 case '>':
589 757 case SPECIAL_UNSIGNED_GT:
590 758 case SPECIAL_GTE:
591 759 case SPECIAL_UNSIGNED_GTE:
592 - set_true_false_states_expr(my_id, expr->left,
593 - NULL, alloc_estate_rl(non_negative));
760 + if (left_rl)
761 + left_false = capped_state;
762 + else
763 + right_true = capped_state;
594 764 break;
595 765 }
766 +
767 + set_true_false_states_expr(my_id, left, left_true, left_false);
768 + set_true_false_states_expr(my_id, right, right_true, right_false);
596 769 }
597 770
598 771 static void match_condition(struct expression *expr)
599 772 {
600 773 if (expr->type != EXPR_COMPARE)
601 774 return;
602 775
603 776 if (expr->op == SPECIAL_EQUAL ||
604 777 expr->op == SPECIAL_NOTEQUAL) {
605 778 handle_eq_noteq(expr);
606 779 return;
607 780 }
608 781
609 - handle_unsigned_lt_gt(expr);
782 + handle_compare(expr);
610 783 }
611 784
612 785 static void match_user_assign_function(const char *fn, struct expression *expr, void *unused)
613 786 {
614 787 tag_as_user_data(expr->left);
615 788 set_points_to_user_data(expr->left);
616 789 }
617 790
618 791 static void match_returns_user_rl(const char *fn, struct expression *expr, void *unused)
619 792 {
620 793 func_gets_user_data = true;
621 794 }
622 795
623 796 static int get_user_macro_rl(struct expression *expr, struct range_list **rl)
624 797 {
625 798 struct expression *parent;
626 799 char *macro;
627 800
628 801 if (!expr)
629 802 return 0;
630 803
631 804 macro = get_macro_name(expr->pos);
632 805 if (!macro)
633 806 return 0;
634 807
635 808 /* handle ntohl(foo[i]) where "i" is trusted */
636 809 parent = expr_get_parent_expr(expr);
637 810 while (parent && parent->type != EXPR_BINOP)
638 811 parent = expr_get_parent_expr(parent);
639 812 if (parent && parent->type == EXPR_BINOP) {
640 813 char *parent_macro = get_macro_name(parent->pos);
641 814
642 815 if (parent_macro && strcmp(macro, parent_macro) == 0)
643 816 return 0;
644 817 }
645 818
646 819 if (strcmp(macro, "ntohl") == 0) {
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
647 820 *rl = alloc_whole_rl(&uint_ctype);
648 821 return 1;
649 822 }
650 823 if (strcmp(macro, "ntohs") == 0) {
651 824 *rl = alloc_whole_rl(&ushort_ctype);
652 825 return 1;
653 826 }
654 827 return 0;
655 828 }
656 829
657 -struct db_info {
658 - struct range_list *rl;
659 - struct expression *call;
660 -};
661 -static int returned_rl_callback(void *_info, int argc, char **argv, char **azColName)
662 -{
663 - struct db_info *db_info = _info;
664 - struct range_list *rl;
665 - char *return_ranges = argv[0];
666 - char *user_ranges = argv[1];
667 - struct expression *arg;
668 - int comparison;
669 -
670 - if (argc != 2)
671 - return 0;
672 -
673 - call_results_to_rl(db_info->call, get_type(db_info->call), user_ranges, &rl);
674 - if (str_to_comparison_arg(return_ranges, db_info->call, &comparison, &arg) &&
675 - comparison == SPECIAL_EQUAL) {
676 - struct range_list *orig_rl;
677 -
678 - if (!get_user_rl(arg, &orig_rl))
679 - return 0;
680 - rl = rl_intersection(rl, orig_rl);
681 - if (!rl)
682 - return 0;
683 - }
684 - db_info->rl = rl_union(db_info->rl, rl);
685 -
686 - return 0;
687 -}
688 -
689 830 static int has_user_data(struct symbol *sym)
690 831 {
691 832 struct sm_state *tmp;
692 833
693 834 FOR_EACH_MY_SM(my_id, __get_cur_stree(), tmp) {
694 835 if (tmp->sym == sym)
695 836 return 1;
696 837 } END_FOR_EACH_SM(tmp);
697 838 return 0;
698 839 }
699 840
700 841 static int we_pass_user_data(struct expression *call)
701 842 {
702 843 struct expression *arg;
703 844 struct symbol *sym;
704 845
705 846 FOR_EACH_PTR(call->args, arg) {
706 847 sym = expr_to_sym(arg);
707 848 if (!sym)
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
708 849 continue;
709 850 if (has_user_data(sym))
710 851 return 1;
711 852 } END_FOR_EACH_PTR(arg);
712 853
713 854 return 0;
714 855 }
715 856
716 857 static int db_returned_user_rl(struct expression *call, struct range_list **rl)
717 858 {
718 - struct db_info db_info = {};
859 + struct smatch_state *state;
860 + char buf[48];
719 861
720 - /* for function pointers assume everything is used */
721 - if (call->fn->type != EXPR_SYMBOL)
722 - return 0;
723 862 if (is_fake_call(call))
724 863 return 0;
725 -
726 - db_info.call = call;
727 - run_sql(&returned_rl_callback, &db_info,
728 - "select return, value from return_states where %s and type = %d and parameter = -1 and key = '$';",
729 - get_static_filter(call->fn->symbol), USER_DATA3_SET);
730 - if (db_info.rl) {
731 - func_gets_user_data = true;
732 - *rl = db_info.rl;
733 - return 1;
734 - }
735 -
736 - run_sql(&returned_rl_callback, &db_info,
737 - "select return, value from return_states where %s and type = %d and parameter = -1 and key = '$';",
738 - get_static_filter(call->fn->symbol), USER_DATA3);
739 - if (db_info.rl) {
740 - if (!we_pass_user_data(call))
741 - return 0;
742 - *rl = db_info.rl;
743 - return 1;
744 - }
745 -
746 - return 0;
864 + snprintf(buf, sizeof(buf), "return %p", call);
865 + state = get_state(my_id, buf, NULL);
866 + if (!state || !estate_rl(state))
867 + return 0;
868 + *rl = estate_rl(state);
869 + return 1;
747 870 }
748 871
749 872 struct stree *get_user_stree(void)
750 873 {
751 874 return get_all_states_stree(my_id);
752 875 }
753 876
754 877 static int user_data_flag;
755 878 static int no_user_data_flag;
756 -static struct range_list *var_user_rl(struct expression *expr)
879 +struct range_list *var_user_rl(struct expression *expr)
757 880 {
758 881 struct smatch_state *state;
759 882 struct range_list *rl;
760 883 struct range_list *absolute_rl;
761 884
885 + if (expr->type == EXPR_PREOP && expr->op == '&') {
886 + no_user_data_flag = 1;
887 + return NULL;
888 + }
889 +
762 890 if (expr->type == EXPR_BINOP && expr->op == '%') {
763 891 struct range_list *left, *right;
764 892
765 893 if (!get_user_rl(expr->right, &right))
766 894 return NULL;
767 895 get_absolute_rl(expr->left, &left);
768 896 rl = rl_binop(left, '%', right);
769 897 goto found;
770 898 }
771 899
772 - if (!option_spammy && expr->type == EXPR_BINOP && expr->op == '/') {
900 + if (expr->type == EXPR_BINOP && expr->op == '/') {
773 901 struct range_list *left = NULL;
774 902 struct range_list *right = NULL;
775 903 struct range_list *abs_right;
776 904
777 905 /*
778 906 * The specific bug I'm dealing with is:
779 907 *
780 908 * foo = capped_user / unknown;
781 909 *
782 910 * Instead of just saying foo is now entirely user_rl we should
783 911 * probably say instead that it is not at all user data.
784 912 *
785 913 */
786 914
787 915 get_user_rl(expr->left, &left);
788 916 get_user_rl(expr->right, &right);
789 917 get_absolute_rl(expr->right, &abs_right);
790 918
791 919 if (left && !right) {
792 920 rl = rl_binop(left, '/', abs_right);
793 921 if (sval_cmp(rl_max(left), rl_max(rl)) < 0)
794 922 no_user_data_flag = 1;
795 923 }
796 924
797 925 return NULL;
798 926 }
799 927
800 928 if (get_rl_from_function(expr, &rl))
801 929 goto found;
802 930
803 931 if (get_user_macro_rl(expr, &rl))
804 932 goto found;
805 933
806 934 if (comes_from_skb_data(expr)) {
807 935 rl = alloc_whole_rl(get_type(expr));
808 936 goto found;
809 937 }
810 938
811 939 state = get_state_expr(my_id, expr);
812 940 if (state && estate_rl(state)) {
813 941 rl = estate_rl(state);
814 942 goto found;
815 943 }
816 944
817 945 if (expr->type == EXPR_CALL && db_returned_user_rl(expr, &rl))
818 946 goto found;
819 947
820 948 if (is_array(expr)) {
821 949 struct expression *array = get_array_base(expr);
822 950
823 951 if (!get_state_expr(my_id, array)) {
824 952 no_user_data_flag = 1;
825 953 return NULL;
826 954 }
827 955 }
828 956
829 957 if (expr->type == EXPR_PREOP && expr->op == '*' &&
830 958 is_user_rl(expr->unop)) {
831 959 rl = var_to_absolute_rl(expr);
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
832 960 goto found;
833 961 }
834 962
835 963 return NULL;
836 964 found:
837 965 user_data_flag = 1;
838 966 absolute_rl = var_to_absolute_rl(expr);
839 967 return clone_rl(rl_intersection(rl, absolute_rl));
840 968 }
841 969
970 +static bool is_ptr_subtract(struct expression *expr)
971 +{
972 + expr = strip_expr(expr);
973 + if (!expr)
974 + return false;
975 + if (expr->type == EXPR_BINOP && expr->op == '-' &&
976 + type_is_ptr(get_type(expr->left))) {
977 + return true;
978 + }
979 + return false;
980 +}
981 +
842 982 int get_user_rl(struct expression *expr, struct range_list **rl)
843 983 {
984 + if (is_ptr_subtract(expr))
985 + return 0;
986 +
844 987 user_data_flag = 0;
845 988 no_user_data_flag = 0;
846 989 custom_get_absolute_rl(expr, &var_user_rl, rl);
847 990 if (!user_data_flag || no_user_data_flag)
848 991 *rl = NULL;
849 992
850 993 return !!*rl;
851 994 }
852 995
853 -int get_user_rl_spammy(struct expression *expr, struct range_list **rl)
854 -{
855 - int ret;
856 -
857 - option_spammy++;
858 - ret = get_user_rl(expr, rl);
859 - option_spammy--;
860 -
861 - return ret;
862 -}
863 -
864 996 int is_user_rl(struct expression *expr)
865 997 {
866 998 struct range_list *tmp;
867 999
868 - return get_user_rl_spammy(expr, &tmp);
1000 + return !!get_user_rl(expr, &tmp);
869 1001 }
870 1002
871 1003 int get_user_rl_var_sym(const char *name, struct symbol *sym, struct range_list **rl)
872 1004 {
873 1005 struct smatch_state *state;
874 1006
875 1007 state = get_state(my_id, name, sym);
876 1008 if (state && estate_rl(state)) {
877 1009 *rl = estate_rl(state);
878 1010 return 1;
879 1011 }
880 1012 return 0;
881 1013 }
882 1014
883 -static void match_call_info(struct expression *expr)
1015 +static char *get_user_rl_str(struct expression *expr, struct symbol *type)
884 1016 {
885 1017 struct range_list *rl;
1018 + static char buf[64];
1019 +
1020 + if (!get_user_rl(expr, &rl))
1021 + return NULL;
1022 + rl = cast_rl(type, rl);
1023 + snprintf(buf, sizeof(buf), "%s%s",
1024 + show_rl(rl), user_rl_capped(expr) ? "[c]" : "");
1025 + return buf;
1026 +}
1027 +
1028 +static void match_call_info(struct expression *expr)
1029 +{
886 1030 struct expression *arg;
887 1031 struct symbol *type;
888 - int i = 0;
1032 + char *str;
1033 + int i;
889 1034
890 1035 i = -1;
891 1036 FOR_EACH_PTR(expr->args, arg) {
892 1037 i++;
893 1038 type = get_arg_type(expr->fn, i);
894 -
895 - if (!get_user_rl(arg, &rl))
1039 + str = get_user_rl_str(arg, type);
1040 + if (!str)
896 1041 continue;
897 1042
898 - rl = cast_rl(type, rl);
899 - sql_insert_caller_info(expr, USER_DATA3, i, "$", show_rl(rl));
1043 + sql_insert_caller_info(expr, USER_DATA, i, "$", str);
900 1044 } END_FOR_EACH_PTR(arg);
901 1045 }
902 1046
903 1047 static int is_struct_ptr(struct symbol *sym)
904 1048 {
905 1049 struct symbol *type;
906 1050
907 1051 if (!sym)
908 1052 return 0;
909 1053 type = get_real_base_type(sym);
910 1054 if (!type || type->type != SYM_PTR)
911 1055 return 0;
912 1056 type = get_real_base_type(type);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
913 1057 if (!type || type->type != SYM_STRUCT)
914 1058 return 0;
915 1059 return 1;
916 1060 }
917 1061
918 1062 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
919 1063 {
920 1064 struct smatch_state *state;
921 1065 struct range_list *rl;
922 1066 struct symbol *type;
1067 + char buf[64];
923 1068
924 1069 /*
925 1070 * Smatch uses a hack where if we get an unsigned long we say it's
926 1071 * both user data and it points to user data. But if we pass it to a
927 1072 * function which takes an int, then it's just user data. There's not
928 1073 * enough bytes for it to be a pointer.
929 1074 *
930 1075 */
931 1076 type = get_arg_type(call->fn, param);
932 1077 if (type && type_bits(type) < type_bits(&ptr_ctype))
933 1078 return;
934 1079
935 1080 if (strcmp(sm->state->name, "") == 0)
936 1081 return;
937 1082
938 1083 if (strcmp(printed_name, "*$") == 0 &&
939 1084 is_struct_ptr(sm->sym))
940 1085 return;
941 1086
942 - state = get_state(SMATCH_EXTRA, sm->name, sm->sym);
1087 + state = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
943 1088 if (!state || !estate_rl(state))
944 1089 rl = estate_rl(sm->state);
945 1090 else
946 1091 rl = rl_intersection(estate_rl(sm->state), estate_rl(state));
947 1092
948 - sql_insert_caller_info(call, USER_DATA3, param, printed_name, show_rl(rl));
1093 + if (!rl)
1094 + return;
1095 +
1096 + snprintf(buf, sizeof(buf), "%s%s", show_rl(rl),
1097 + estate_capped(sm->state) ? "[c]" : "");
1098 + sql_insert_caller_info(call, USER_DATA, param, printed_name, buf);
949 1099 }
950 1100
1101 +static void db_param_set(struct expression *expr, int param, char *key, char *value)
1102 +{
1103 + struct expression *arg;
1104 + char *name;
1105 + struct symbol *sym;
1106 + struct smatch_state *state;
1107 +
1108 + while (expr->type == EXPR_ASSIGNMENT)
1109 + expr = strip_expr(expr->right);
1110 + if (expr->type != EXPR_CALL)
1111 + return;
1112 +
1113 + arg = get_argument_from_call_expr(expr->args, param);
1114 + if (!arg)
1115 + return;
1116 + name = get_variable_from_key(arg, key, &sym);
1117 + if (!name || !sym)
1118 + goto free;
1119 +
1120 + state = get_state(my_id, name, sym);
1121 + if (!state)
1122 + goto free;
1123 +
1124 + set_state(my_id, name, sym, alloc_estate_empty());
1125 +free:
1126 + free_string(name);
1127 +}
1128 +
1129 +static bool param_data_capped(const char *value)
1130 +{
1131 + if (strstr(value, ",c") || strstr(value, "[c"))
1132 + return true;
1133 + return false;
1134 +}
1135 +
951 1136 static void set_param_user_data(const char *name, struct symbol *sym, char *key, char *value)
952 1137 {
953 1138 struct range_list *rl = NULL;
954 1139 struct smatch_state *state;
1140 + struct expression *expr;
955 1141 struct symbol *type;
956 1142 char fullname[256];
1143 + char *key_orig = key;
1144 + bool add_star = false;
957 1145
958 - if (strcmp(key, "*$") == 0)
959 - snprintf(fullname, sizeof(fullname), "*%s", name);
960 - else if (strncmp(key, "$", 1) == 0)
961 - snprintf(fullname, 256, "%s%s", name, key + 1);
962 - else
963 - return;
1146 + if (strcmp(key, "**$") == 0) {
1147 + snprintf(fullname, sizeof(fullname), "**%s", name);
1148 + } else {
1149 + if (key[0] == '*') {
1150 + add_star = true;
1151 + key++;
1152 + }
964 1153
965 - type = get_member_type_from_key(symbol_expression(sym), key);
1154 + snprintf(fullname, 256, "%s%s%s", add_star ? "*" : "", name, key + 1);
1155 + }
966 1156
967 - /* if the caller passes a void pointer with user data */
968 - if (strcmp(key, "*$") == 0 && type && type != &void_ctype) {
969 - struct expression *expr = symbol_expression(sym);
1157 + expr = symbol_expression(sym);
1158 + type = get_member_type_from_key(expr, key_orig);
970 1159
971 - tag_as_user_data(expr);
972 - set_points_to_user_data(expr);
973 - return;
1160 + /*
1161 + * Say this function takes a struct ponter but the caller passes
1162 + * this_function(skb->data). We have two options, we could pass *$
1163 + * as user data or we could pass foo->bar, foo->baz as user data.
1164 + * The second option is easier to implement so we do that.
1165 + *
1166 + */
1167 + if (strcmp(key_orig, "*$") == 0) {
1168 + struct symbol *tmp = type;
1169 +
1170 + while (tmp && tmp->type == SYM_PTR)
1171 + tmp = get_real_base_type(tmp);
1172 +
1173 + if (tmp && (tmp->type == SYM_STRUCT || tmp->type == SYM_UNION)) {
1174 + tag_as_user_data(symbol_expression(sym));
1175 + return;
1176 + }
974 1177 }
1178 +
975 1179 str_to_rl(type, value, &rl);
976 1180 state = alloc_estate_rl(rl);
1181 + if (param_data_capped(value) || is_capped(expr))
1182 + estate_set_capped(state);
977 1183 set_state(my_id, fullname, sym, state);
978 1184 }
979 1185
980 1186 static void set_called(const char *name, struct symbol *sym, char *key, char *value)
981 1187 {
982 1188 set_state(my_call_id, "this_function", NULL, &called);
983 1189 }
984 1190
985 1191 static void match_syscall_definition(struct symbol *sym)
986 1192 {
987 1193 struct symbol *arg;
988 1194 char *macro;
989 1195 char *name;
990 1196 int is_syscall = 0;
991 1197
992 1198 macro = get_macro_name(sym->pos);
993 1199 if (macro &&
994 1200 (strncmp("SYSCALL_DEFINE", macro, strlen("SYSCALL_DEFINE")) == 0 ||
995 1201 strncmp("COMPAT_SYSCALL_DEFINE", macro, strlen("COMPAT_SYSCALL_DEFINE")) == 0))
996 1202 is_syscall = 1;
997 1203
998 1204 name = get_function();
999 1205 if (!option_no_db && get_state(my_call_id, "this_function", NULL) != &called) {
1000 1206 if (name && strncmp(name, "sys_", 4) == 0)
1001 1207 is_syscall = 1;
1002 1208 }
1003 1209
1004 1210 if (name && strncmp(name, "compat_sys_", 11) == 0)
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
1005 1211 is_syscall = 1;
1006 1212
1007 1213 if (!is_syscall)
1008 1214 return;
1009 1215
1010 1216 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
1011 1217 set_state(my_id, arg->ident->name, arg, alloc_estate_whole(get_real_base_type(arg)));
1012 1218 } END_FOR_EACH_PTR(arg);
1013 1219 }
1014 1220
1221 +static void store_user_data_return(struct expression *expr, char *key, char *value)
1222 +{
1223 + struct range_list *rl;
1224 + struct symbol *type;
1225 + char buf[48];
1226 +
1227 + if (strcmp(key, "$") != 0)
1228 + return;
1229 +
1230 + type = get_type(expr);
1231 + snprintf(buf, sizeof(buf), "return %p", expr);
1232 + call_results_to_rl(expr, type, value, &rl);
1233 +
1234 + set_state(my_id, buf, NULL, alloc_estate_rl(rl));
1235 +}
1236 +
1015 1237 static void set_to_user_data(struct expression *expr, char *key, char *value)
1016 1238 {
1239 + struct smatch_state *state;
1017 1240 char *name;
1018 1241 struct symbol *sym;
1019 1242 struct symbol *type;
1020 1243 struct range_list *rl = NULL;
1021 1244
1022 1245 type = get_member_type_from_key(expr, key);
1023 1246 name = get_variable_from_key(expr, key, &sym);
1024 1247 if (!name || !sym)
1025 1248 goto free;
1026 1249
1027 1250 call_results_to_rl(expr, type, value, &rl);
1028 1251
1029 - set_state(my_id, name, sym, alloc_estate_rl(rl));
1252 + state = alloc_estate_rl(rl);
1253 + if (param_data_capped(value))
1254 + estate_set_capped(state);
1255 + set_state(my_id, name, sym, state);
1030 1256 free:
1031 1257 free_string(name);
1032 -
1033 1258 }
1034 1259
1035 1260 static void returns_param_user_data(struct expression *expr, int param, char *key, char *value)
1036 1261 {
1037 1262 struct expression *arg;
1038 1263 struct expression *call;
1039 1264
1040 1265 call = expr;
1041 1266 while (call->type == EXPR_ASSIGNMENT)
1042 1267 call = strip_expr(call->right);
1043 1268 if (call->type != EXPR_CALL)
1044 1269 return;
1045 1270
1046 1271 if (!we_pass_user_data(call))
1047 1272 return;
1048 1273
1049 1274 if (param == -1) {
1050 - if (expr->type != EXPR_ASSIGNMENT)
1275 + if (expr->type != EXPR_ASSIGNMENT) {
1276 + store_user_data_return(expr, key, value);
1051 1277 return;
1278 + }
1052 1279 set_to_user_data(expr->left, key, value);
1053 1280 return;
1054 1281 }
1055 1282
1056 1283 arg = get_argument_from_call_expr(call->args, param);
1057 1284 if (!arg)
1058 1285 return;
1059 1286 set_to_user_data(arg, key, value);
1060 1287 }
1061 1288
1062 1289 static void returns_param_user_data_set(struct expression *expr, int param, char *key, char *value)
1063 1290 {
1064 1291 struct expression *arg;
1065 1292
1066 1293 func_gets_user_data = true;
1067 1294
1068 1295 if (param == -1) {
1069 - if (expr->type != EXPR_ASSIGNMENT)
1296 + if (expr->type != EXPR_ASSIGNMENT) {
1297 + store_user_data_return(expr, key, value);
1070 1298 return;
1299 + }
1071 1300 if (strcmp(key, "*$") == 0) {
1072 1301 set_points_to_user_data(expr->left);
1073 1302 tag_as_user_data(expr->left);
1074 1303 } else {
1075 1304 set_to_user_data(expr->left, key, value);
1076 1305 }
1077 1306 return;
1078 1307 }
1079 1308
1080 1309 while (expr->type == EXPR_ASSIGNMENT)
1081 1310 expr = strip_expr(expr->right);
1082 1311 if (expr->type != EXPR_CALL)
1083 1312 return;
1084 1313
1085 1314 arg = get_argument_from_call_expr(expr->args, param);
1086 1315 if (!arg)
1087 1316 return;
1088 1317 set_to_user_data(arg, key, value);
1089 1318 }
1090 1319
1091 -static int has_empty_state(struct sm_state *sm)
1092 -{
1093 - struct sm_state *tmp;
1094 -
1095 - FOR_EACH_PTR(sm->possible, tmp) {
1096 - if (!estate_rl(tmp->state))
1097 - return 1;
1098 - } END_FOR_EACH_PTR(tmp);
1099 -
1100 - return 0;
1101 -}
1102 -
1103 1320 static void param_set_to_user_data(int return_id, char *return_ranges, struct expression *expr)
1104 1321 {
1105 1322 struct sm_state *sm;
1106 1323 struct smatch_state *start_state;
1107 1324 struct range_list *rl;
1108 1325 int param;
1109 1326 char *return_str;
1110 1327 const char *param_name;
1111 1328 struct symbol *ret_sym;
1112 1329 bool return_found = false;
1330 + bool pointed_at_found = false;
1331 + char buf[64];
1113 1332
1114 1333 expr = strip_expr(expr);
1115 1334 return_str = expr_to_str(expr);
1116 1335 ret_sym = expr_to_sym(expr);
1117 1336
1118 1337 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
1119 - if (has_empty_state(sm))
1120 - continue;
1121 -
1122 1338 param = get_param_num_from_sym(sm->sym);
1123 1339 if (param < 0)
1124 1340 continue;
1125 1341
1342 + if (!param_was_set_var_sym(sm->name, sm->sym))
1343 + continue;
1344 +
1126 1345 /* The logic here was that if we were passed in a user data then
1127 1346 * we don't record that. It's like the difference between
1128 1347 * param_filter and param_set. When I think about it, I'm not
1129 1348 * sure it actually works. It's probably harmless because we
1130 1349 * checked earlier that we're not returning a parameter...
1131 1350 * Let's mark this as a TODO.
1132 1351 */
1133 1352 start_state = get_state_stree(start_states, my_id, sm->name, sm->sym);
1134 1353 if (start_state && rl_equiv(estate_rl(sm->state), estate_rl(start_state)))
1135 1354 continue;
1136 1355
1137 1356 param_name = get_param_name(sm);
1138 1357 if (!param_name)
1139 1358 continue;
1140 1359 if (strcmp(param_name, "$") == 0) /* The -1 param is handled after the loop */
1141 1360 continue;
1142 1361
1362 + snprintf(buf, sizeof(buf), "%s%s",
1363 + show_rl(estate_rl(sm->state)),
1364 + estate_capped(sm->state) ? "[c]" : "");
1143 1365 sql_insert_return_states(return_id, return_ranges,
1144 - func_gets_user_data ? USER_DATA3_SET : USER_DATA3,
1145 - param, param_name, show_rl(estate_rl(sm->state)));
1366 + func_gets_user_data ? USER_DATA_SET : USER_DATA,
1367 + param, param_name, buf);
1146 1368 } END_FOR_EACH_SM(sm);
1147 1369
1148 - if (points_to_user_data(expr)) {
1149 - sql_insert_return_states(return_id, return_ranges,
1150 - (is_skb_data(expr) || !func_gets_user_data) ?
1151 - USER_DATA3_SET : USER_DATA3,
1152 - -1, "*$", "");
1153 - goto free_string;
1154 - }
1155 -
1156 -
1370 + /* This if for "return foo;" where "foo->bar" is user data. */
1157 1371 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
1158 1372 if (!ret_sym)
1159 1373 break;
1160 1374 if (ret_sym != sm->sym)
1161 1375 continue;
1162 1376
1163 1377 param_name = state_name_to_param_name(sm->name, return_str);
1164 1378 if (!param_name)
1165 1379 continue;
1166 1380 if (strcmp(param_name, "$") == 0)
1167 1381 return_found = true;
1382 + if (strcmp(param_name, "*$") == 0)
1383 + pointed_at_found = true;
1384 + snprintf(buf, sizeof(buf), "%s%s",
1385 + show_rl(estate_rl(sm->state)),
1386 + estate_capped(sm->state) ? "[c]" : "");
1168 1387 sql_insert_return_states(return_id, return_ranges,
1169 - func_gets_user_data ? USER_DATA3_SET : USER_DATA3,
1170 - -1, param_name, show_rl(estate_rl(sm->state)));
1388 + func_gets_user_data ? USER_DATA_SET : USER_DATA,
1389 + -1, param_name, buf);
1171 1390 } END_FOR_EACH_SM(sm);
1172 1391
1173 -
1392 + /* This if for "return ntohl(foo);" */
1174 1393 if (!return_found && get_user_rl(expr, &rl)) {
1394 + snprintf(buf, sizeof(buf), "%s%s",
1395 + show_rl(rl), user_rl_capped(expr) ? "[c]" : "");
1175 1396 sql_insert_return_states(return_id, return_ranges,
1176 - func_gets_user_data ? USER_DATA3_SET : USER_DATA3,
1177 - -1, "$", show_rl(rl));
1178 - goto free_string;
1397 + func_gets_user_data ? USER_DATA_SET : USER_DATA,
1398 + -1, "$", buf);
1179 1399 }
1180 1400
1181 -free_string:
1401 + /*
1402 + * This is to handle things like return skb->data where we don't set a
1403 + * state for that.
1404 + */
1405 + if (!pointed_at_found && points_to_user_data(expr)) {
1406 + sql_insert_return_states(return_id, return_ranges,
1407 + (is_skb_data(expr) || func_gets_user_data) ?
1408 + USER_DATA_SET : USER_DATA,
1409 + -1, "*$", "s64min-s64max");
1410 + }
1411 +
1182 1412 free_string(return_str);
1183 1413 }
1184 1414
1415 +static void returns_param_capped(struct expression *expr, int param, char *key, char *value)
1416 +{
1417 + struct smatch_state *state, *new;
1418 + struct symbol *sym;
1419 + char *name;
1420 +
1421 + name = return_state_to_var_sym(expr, param, key, &sym);
1422 + if (!name || !sym)
1423 + goto free;
1424 +
1425 + state = get_state(my_id, name, sym);
1426 + if (!state || estate_capped(state))
1427 + goto free;
1428 +
1429 + new = clone_estate(state);
1430 + estate_set_capped(new);
1431 +
1432 + set_state(my_id, name, sym, new);
1433 +free:
1434 + free_string(name);
1435 +}
1436 +
1185 1437 static struct int_stack *gets_data_stack;
1186 1438 static void match_function_def(struct symbol *sym)
1187 1439 {
1188 1440 func_gets_user_data = false;
1189 1441 }
1190 1442
1191 1443 static void match_inline_start(struct expression *expr)
1192 1444 {
1193 1445 push_int(&gets_data_stack, func_gets_user_data);
1194 1446 }
1195 1447
1196 1448 static void match_inline_end(struct expression *expr)
1197 1449 {
1198 1450 func_gets_user_data = pop_int(&gets_data_stack);
1199 1451 }
1200 1452
1201 -void register_kernel_user_data2(int id)
1453 +void register_kernel_user_data(int id)
1202 1454 {
1203 1455 int i;
1204 1456
1205 1457 my_id = id;
1206 1458
1207 1459 if (option_project != PROJ_KERNEL)
1208 1460 return;
1209 1461
1462 + set_dynamic_states(my_id);
1463 +
1210 1464 add_hook(&match_function_def, FUNC_DEF_HOOK);
1211 1465 add_hook(&match_inline_start, INLINE_FN_START);
1212 1466 add_hook(&match_inline_end, INLINE_FN_END);
1213 1467
1214 1468 add_hook(&save_start_states, AFTER_DEF_HOOK);
1215 1469 add_hook(&free_start_states, AFTER_FUNC_HOOK);
1216 1470 add_hook(&match_save_states, INLINE_FN_START);
1217 1471 add_hook(&match_restore_states, INLINE_FN_END);
1218 1472
1219 1473 add_unmatched_state_hook(my_id, &empty_state);
1220 1474 add_extra_nomod_hook(&extra_nomod_hook);
1221 1475 add_pre_merge_hook(my_id, &pre_merge_hook);
1222 1476 add_merge_hook(my_id, &merge_estates);
1223 1477
1224 1478 add_function_hook("copy_from_user", &match_user_copy, INT_PTR(0));
1225 1479 add_function_hook("__copy_from_user", &match_user_copy, INT_PTR(0));
1226 1480 add_function_hook("memcpy_fromiovec", &match_user_copy, INT_PTR(0));
1227 1481 for (i = 0; i < ARRAY_SIZE(kstr_funcs); i++)
1228 1482 add_function_hook(kstr_funcs[i], &match_user_copy, INT_PTR(2));
1229 1483 add_function_hook("usb_control_msg", &match_user_copy, INT_PTR(6));
1230 1484
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1231 1485 for (i = 0; i < ARRAY_SIZE(returns_user_data); i++) {
1232 1486 add_function_assign_hook(returns_user_data[i], &match_user_assign_function, NULL);
1233 1487 add_function_hook(returns_user_data[i], &match_returns_user_rl, NULL);
1234 1488 }
1235 1489
1236 1490 add_function_hook("sscanf", &match_sscanf, NULL);
1237 1491
1238 1492 add_hook(&match_syscall_definition, AFTER_DEF_HOOK);
1239 1493
1240 1494 add_hook(&match_assign, ASSIGNMENT_HOOK);
1495 + select_return_states_hook(PARAM_SET, &db_param_set);
1241 1496 add_hook(&match_condition, CONDITION_HOOK);
1242 1497
1243 1498 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
1244 1499 add_member_info_callback(my_id, struct_member_callback);
1245 - select_caller_info_hook(set_param_user_data, USER_DATA3);
1246 - select_return_states_hook(USER_DATA3, &returns_param_user_data);
1247 - select_return_states_hook(USER_DATA3_SET, &returns_param_user_data_set);
1500 + select_caller_info_hook(set_param_user_data, USER_DATA);
1501 + select_return_states_hook(USER_DATA, &returns_param_user_data);
1502 + select_return_states_hook(USER_DATA_SET, &returns_param_user_data_set);
1503 + select_return_states_hook(CAPPED_DATA, &returns_param_capped);
1248 1504 add_split_return_callback(¶m_set_to_user_data);
1249 1505 }
1250 1506
1251 -void register_kernel_user_data3(int id)
1507 +void register_kernel_user_data2(int id)
1252 1508 {
1253 1509 my_call_id = id;
1254 1510
1255 1511 if (option_project != PROJ_KERNEL)
1256 1512 return;
1257 1513 select_caller_info_hook(set_called, INTERNAL);
1258 1514 }
1259 -
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX