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