Print this page
11972 resync 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
↓ 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))
↓ 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) {
↓ 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  {
↓ 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;
↓ 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)
↓ 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)
↓ 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  
↓ 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  
↓ 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  
↓ 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  {
↓ 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  
↓ 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)) {
↓ 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