Ignore:
Timestamp:
11/22/09 19:47:22 (14 years ago)
Author:
tim
Message:

reorganized data parsing in regfi

simplified some length validation

added big data support to reglookup-recover

fixed reglookup-recover's handling of data values in the offset

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/reglookup-recover.c

    r152 r157  
    258258{
    259259  void_stack* path_stack = void_stack_new(REGFI_MAX_DEPTH);
    260   const REGFI_HBIN* hbin;
    261260  REGFI_NK_REC* cur_ancestor;
    262261  char* ret_val;
    263   uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used;
    264   uint32 max_length;
     262  uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used, offset;
     263  int32 max_size;
    265264  REGFI_BUFFER* path_element;
    266265 
     
    269268  ret_val_size = 1; /* NUL */
    270269  while(virt_offset != REGFI_OFFSET_NONE)
    271   { 
    272     hbin = regfi_lookup_hbin(f, virt_offset);
    273     if(hbin == NULL)
     270  {
     271    offset = virt_offset+REGFI_REGF_SIZE;
     272    max_size = regfi_calc_maxsize(f, offset);
     273    if(max_size < 0)
    274274      virt_offset = REGFI_OFFSET_NONE;
    275275    else
    276276    {
    277       max_length = hbin->block_size + hbin->file_off
    278         - (virt_offset+REGFI_REGF_SIZE);
    279       cur_ancestor = regfi_parse_nk(f, virt_offset+REGFI_REGF_SIZE,
    280                                     max_length, true);
     277      cur_ancestor = regfi_parse_nk(f, offset, max_size, true);
    281278      printMsgs(f);
    282279
     
    456453
    457454
    458 int extractDataCells(REGFI_FILE* f,
     455int extractDataCells(REGFI_FILE* file,
    459456                     range_list* unalloc_cells,
    460457                     range_list* unalloc_values)
     
    462459  const range_list_element* cur_elem;
    463460  REGFI_VK_REC* vk;
    464   const REGFI_HBIN* hbin;
     461  range_list* bd_cells;
    465462  REGFI_BUFFER data;
    466   uint32 i, off, data_offset, data_maxsize;
     463  uint32 i, j, offset, cell_length, length;
     464  int32 max_size;
     465  bool unalloc;
     466
     467  bd_cells = range_list_new();
     468  if(bd_cells == NULL)
     469    return 10;
    467470
    468471  for(i=0; i<range_list_size(unalloc_values); i++)
     
    471474    vk = (REGFI_VK_REC*)cur_elem->data;
    472475    if(vk == NULL)
    473       return 40;
    474 
    475     if(vk->data_size == 0)
    476       vk->data = NULL;
    477     else
    478     {
    479       off = vk->data_off+REGFI_REGF_SIZE;
     476      return 11;
     477
     478    length = vk->data_size;
     479    vk->data = NULL;
     480    if(vk->data_size != 0)
     481    {
     482      offset = vk->data_off+REGFI_REGF_SIZE;
    480483
    481484      if(vk->data_in_offset)
     485        data = regfi_parse_little_data(file, vk->data_off,
     486                                       length, false);
     487      else
    482488      {
    483         data = regfi_load_data(f, vk->type, vk->data_off,
    484                                vk->data_size, 4,
    485                                vk->data_in_offset, false);
     489        max_size = regfi_calc_maxsize(file, offset);
     490        if(max_size >= 0
     491           && regfi_parse_cell(file->fd, offset, NULL, 0,
     492                               &cell_length, &unalloc)
     493           && (cell_length & 0x00000007) == 0
     494           && cell_length <= max_size)
     495        {
     496          if(cell_length - 4 < length)
     497          {
     498            /* Multi-cell "big data" */
     499
     500            /* XXX: All big data records thus far have been 16 bytes long. 
     501             *      Should we check for this precise size instead of just
     502             *      relying upon the above check?
     503             */
     504            if (file->major_version >= 1 && file->minor_version >= 5)
     505            {
     506              /* Attempt to parse a big data record */
     507              data = regfi_load_big_data(file, offset, length,
     508                                         cell_length, bd_cells, false);
     509
     510              /* XXX: if this turns out NULL, should fall back to truncating cell */
     511              if(data.buf != NULL)
     512              {
     513                for(j=0; j<range_list_size(bd_cells); j++)
     514                {
     515                  cur_elem = range_list_get(bd_cells, j);
     516                  if(cur_elem == NULL)
     517                    return 20;
     518                  if(!range_list_has_range(unalloc_cells,
     519                                           cur_elem->offset,
     520                                           cur_elem->length))
     521                  {
     522                    fprintf(stderr,
     523                            "WARN: Successfully parsed big data at offset"
     524                            " 0x%.8X was rejected because some substructure"
     525                            " (offset=0x%.8X) is allocated or used in other"
     526                            " recovered structures.\n",
     527                            offset, cur_elem->offset);
     528                    talloc_free(data.buf);
     529                    data.buf = NULL;
     530                    data.len = 0;
     531                    break;
     532                  }
     533                }
     534               
     535                if(data.buf != NULL)
     536                {
     537                  for(j=0; j<range_list_size(bd_cells); j++)
     538                  {
     539                    cur_elem = range_list_get(bd_cells, j);
     540                    if(cur_elem == NULL)
     541                      return 21;
     542                   
     543                    if(!removeRange(unalloc_cells,
     544                                    cur_elem->offset,
     545                                    cur_elem->length))
     546                    { return 22; }
     547                  }
     548                }
     549              }
     550
     551            }
     552            else
     553            {
     554              fprintf(stderr,
     555                      "WARN: Data length (0x%.8X)"
     556                      " larger than remaining cell length (0x%.8X)"
     557                      " while parsing data record at offset 0x%.8X."
     558                      " Truncating...\n",
     559                      length, cell_length - 4, offset);
     560               length = cell_length - 4;
     561            }
     562          }
     563         
     564          /* Typical 1-cell data */
     565          if(range_list_has_range(unalloc_cells, offset, length))
     566          {
     567            data = regfi_parse_data(file, offset, length, false);
     568            if(data.buf != NULL)
     569              if(!removeRange(unalloc_cells, offset, length))
     570                return 30;
     571          }
     572        }
     573
    486574        vk->data = data.buf;
    487575        vk->data_size = data.len;
    488576      }
    489       else if(range_list_has_range(unalloc_cells, off, vk->data_size))
    490       {
    491         hbin = regfi_lookup_hbin(f, vk->data_off);
    492         if(hbin)
    493         {
    494           data_offset = vk->data_off+REGFI_REGF_SIZE;
    495           data_maxsize = hbin->block_size + hbin->file_off - data_offset;
    496           data = regfi_load_data(f, vk->type, data_offset,
    497                                  vk->data_size, data_maxsize,
    498                                  vk->data_in_offset, false);
    499           vk->data = data.buf;
    500           vk->data_size = data.len;
    501 
    502           if(vk->data != NULL)
    503           {
    504             /* XXX: The following may not make sense now in light of big data
    505              *      records.
    506              */
    507             /* XXX: This strict checking prevents partial recovery of data
    508              *      cells.  Also, see code for regfi_load_data and note that
    509              *      lengths indicated in VK records are sometimes just plain
    510              *      wrong.  Need a feedback mechanism to be more fuzzy with
    511              *      data cell lengths and the ranges removed.
    512              *
    513              *      The introduction of REGFI_BUFFER in regfi_load_data has
    514              *      fixed some of this.  Should review again with respect to
    515              *      the other issues mentioned above though.
    516              */
    517             /* A data record was recovered. Remove from unalloc_cells. */
    518             if(!removeRange(unalloc_cells, off, vk->data_size))
    519               return 50;
    520           }
    521         }
    522         else
    523           vk->data = NULL;
    524       }
    525     }
    526   }
    527 
     577    }
     578  }
     579
     580  range_list_free(bd_cells);
    528581  return 0;
    529582}
     
    590643  REGFI_NK_REC* nk;
    591644  REGFI_VK_REC* vk;
    592   const REGFI_HBIN* hbin;
    593645  const range_list_element* cur_elem;
    594   uint32 i, j, num_keys, off, values_length, max_length;
     646  uint32 i, j, num_keys, off, values_length;
     647  int32 max_size;
    595648
    596649  num_keys=range_list_size(unalloc_keys);
     
    604657    if(nk->num_values && (nk->values_off!=REGFI_OFFSET_NONE))
    605658    {
    606       hbin = regfi_lookup_hbin(f, nk->values_off);
    607      
    608       if(hbin != NULL)
     659      off = nk->values_off + REGFI_REGF_SIZE;
     660      max_size = regfi_calc_maxsize(f, off);
     661      if(max_size >= 0)
    609662      {
    610         off = nk->values_off + REGFI_REGF_SIZE;
    611         max_length = hbin->block_size + hbin->file_off - off;
    612663        nk->values = regfi_load_valuelist(f, off, nk->num_values,
    613                                           max_length, false);
     664                                          max_size, false);
    614665        if(nk->values != NULL && nk->values->elements != NULL)
    615666        {
Note: See TracChangeset for help on using the changeset viewer.