Changeset 180


Ignore:
Timestamp:
03/14/10 16:02:38 (15 years ago)
Author:
tim
Message:

Added locks to make transactions on REGFI_FILE objects thread safe

Added initial version of a threading smoke test

Files:
3 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Makefile

    r159 r180  
    1414#OPTS=-std=gnu99 -pedantic -Wall
    1515INC:=-I$(PWD)/include -I/usr/local/include
    16 LIB=-L/usr/local/lib -lm
     16LIB=-L/usr/local/lib -lm -lpthread
    1717BIN_EXT=
    1818EXTRA_OBJ=
  • trunk/include/regfi.h

    r178 r180  
    6969#include <unistd.h>
    7070#include <iconv.h>
     71#include <pthread.h>
    7172
    7273#include "byteorder.h"
     
    674675  REGFI_RAW_FILE* cb;
    675676
     677  /* Mutex for all cb access.  This is done to prevent one thread from moving
     678   * the file offset while another thread is in the middle of a multi-read
     679   * parsing transaction */
     680  pthread_mutex_t* cb_lock;
     681
    676682  /* For sanity checking (not part of the registry header) */
    677683  uint32_t file_length;
     
    680686  range_list* hbins;
    681687
     688  /* Multiple read access allowed, write access is exclusive */
     689  pthread_rwlock_t* hbins_lock;
     690
    682691  /* SK record cached since they're repeatedly reused */
    683692  lru_cache* sk_cache;
     693
     694  /* Need exclusive access for LRUs, since lookups make changes */
     695  pthread_mutex_t* sk_lock;
    684696
    685697  /* Error/warning/info messages returned by lower layer functions */
  • trunk/lib/regfi.c

    r178 r180  
    422422
    423423
     424bool regfi_read_lock(REGFI_FILE* file, pthread_rwlock_t* lock, const char* context)
     425{
     426  int lock_ret = pthread_rwlock_rdlock(lock);
     427  if(lock_ret != 0)
     428  {
     429    regfi_add_message(file, REGFI_MSG_ERROR, "Error obtaining read lock in"
     430                      "%s due to: %s\n", context, strerror(lock_ret));
     431    return false;
     432  }
     433
     434  return true;
     435}
     436
     437
     438bool regfi_write_lock(REGFI_FILE* file, pthread_rwlock_t* lock, const char* context)
     439{
     440  int lock_ret = pthread_rwlock_wrlock(lock);
     441  if(lock_ret != 0)
     442  {
     443    regfi_add_message(file, REGFI_MSG_ERROR, "Error obtaining write lock in"
     444                      "%s due to: %s\n", context, strerror(lock_ret));
     445    return false;
     446  }
     447
     448  return true;
     449}
     450
     451
     452bool regfi_rw_unlock(REGFI_FILE* file, pthread_rwlock_t* lock, const char* context)
     453{
     454  int lock_ret = pthread_rwlock_unlock(lock);
     455  if(lock_ret != 0)
     456  {
     457    regfi_add_message(file, REGFI_MSG_ERROR, "Error releasing lock in"
     458                      "%s due to: %s\n", context, strerror(lock_ret));
     459    return false;
     460  }
     461
     462  return true;
     463}
     464
     465
     466bool regfi_lock(REGFI_FILE* file, pthread_mutex_t* lock, const char* context)
     467{
     468  int lock_ret = pthread_mutex_lock(lock);
     469  if(lock_ret != 0)
     470  {
     471    regfi_add_message(file, REGFI_MSG_ERROR, "Error obtaining mutex lock in"
     472                      "%s due to: %s\n", context, strerror(lock_ret));
     473    return false;
     474  }
     475
     476  return true;
     477}
     478
     479
     480bool regfi_unlock(REGFI_FILE* file, pthread_mutex_t* lock, const char* context)
     481{
     482  int lock_ret = pthread_mutex_unlock(lock);
     483  if(lock_ret != 0)
     484  {
     485    regfi_add_message(file, REGFI_MSG_ERROR, "Error releasing mutex lock in"
     486                      "%s due to: %s\n", context, strerror(lock_ret));
     487    return false;
     488  }
     489
     490  return true;
     491}
     492
     493
    424494off_t regfi_raw_seek(REGFI_RAW_FILE* self, off_t offset, int whence)
    425495{
     
    655725  bool recursive_type;
    656726
     727  if(!regfi_lock(file, file->cb_lock, "regfi_parse_subkeylist"))
     728     goto fail;
     729
    657730  if(!regfi_parse_cell(file->cb, offset, buf, REGFI_SUBKEY_LIST_MIN_LEN,
    658731                       &cell_length, &unalloc))
     
    660733    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while "
    661734                      "parsing subkey-list at offset 0x%.8X.", offset);
    662     return NULL;
     735    goto fail_locked;
    663736  }
    664737
     
    668741                      " while parsing subkey-list at offset 0x%.8X.", offset);
    669742    if(strict)
    670       return NULL;
     743      goto fail_locked;
    671744    cell_length = max_size & 0xFFFFFFF8;
    672745  }
     
    687760                      " (0x%.2X, 0x%.2X) encountered while parsing"
    688761                      " subkey-list at offset 0x%.8X.", buf[0], buf[1], offset);
    689     return NULL;
     762    goto fail_locked;
    690763  }
    691764
    692765  ret_val = talloc(NULL, REGFI_SUBKEY_LIST);
    693766  if(ret_val == NULL)
    694     return NULL;
     767    goto fail_locked;
    695768
    696769  ret_val->offset = offset;
     
    711784                      offset);
    712785    if(strict)
    713       goto fail;
     786      goto fail_locked;
    714787    length = cell_length - REGFI_SUBKEY_LIST_MIN_LEN - sizeof(uint32_t);
    715788  }
     
    718791                                   ret_val->num_children);
    719792  if(ret_val->elements == NULL)
    720     goto fail;
     793    goto fail_locked;
    721794
    722795  elements = (uint8_t*)malloc(length);
    723796  if(elements == NULL)
    724     goto fail;
     797    goto fail_locked;
    725798
    726799  read_len = length;
    727800  if(regfi_read(file->cb, elements, &read_len) != 0 || read_len!=length)
    728     goto fail;
     801    goto fail_locked;
     802
     803  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_subkeylist"))
     804     goto fail;
    729805
    730806  if(elem_size == sizeof(uint32_t))
     
    748824  return ret_val;
    749825
     826 fail_locked:
     827  regfi_unlock(file, file->cb_lock, "regfi_parse_subkeylist");
    750828 fail:
    751829  if(elements != NULL)
     
    817895                             bool strict)
    818896{
    819   REGFI_SK_REC* ret_val;
     897  REGFI_SK_REC* ret_val = NULL;
    820898  uint8_t* sec_desc_buf = NULL;
    821899  uint32_t cell_length, length;
     
    823901  bool unalloc = false;
    824902
     903  if(!regfi_lock(file, file->cb_lock, "regfi_parse_sk"))
     904     goto fail;
     905
    825906  if(!regfi_parse_cell(file->cb, offset, sk_header, REGFI_SK_MIN_LENGTH,
    826907                       &cell_length, &unalloc))
     
    828909    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse SK record cell"
    829910                      " at offset 0x%.8X.", offset);
    830     return NULL;
     911    goto fail_locked;
    831912  }
    832913   
     
    835916    regfi_add_message(file, REGFI_MSG_WARN, "Magic number mismatch in parsing"
    836917                      " SK record at offset 0x%.8X.", offset);
    837     return NULL;
     918    goto fail_locked;
    838919  }
    839920
    840921  ret_val = talloc(NULL, REGFI_SK_REC);
    841922  if(ret_val == NULL)
    842     return NULL;
     923    goto fail_locked;
    843924
    844925  ret_val->offset = offset;
     
    855936    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size found while"
    856937                      " parsing SK record at offset 0x%.8X.", offset);
    857     goto fail;
     938    goto fail_locked;
    858939  }
    859940
     
    873954                      " are not a multiple of 8 while parsing SK record at"
    874955                      " offset 0x%.8X.", offset);
    875     goto fail;
     956    goto fail_locked;
    876957  }
    877958
     
    881962                      " cell while parsing SK record at offset 0x%.8X.",
    882963                      offset);
    883     goto fail;
     964    goto fail_locked;
    884965  }
    885966
    886967  sec_desc_buf = (uint8_t*)malloc(ret_val->desc_size);
    887968  if(sec_desc_buf == NULL)
    888     goto fail;
     969    goto fail_locked;
    889970
    890971  length = ret_val->desc_size;
     
    895976                      " descriptor while parsing SK record at offset 0x%.8X.",
    896977                      offset);
    897     goto fail;
    898   }
     978    goto fail_locked;
     979  }
     980
     981  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_sk"))
     982     goto fail;
    899983
    900984  if(!(ret_val->sec_desc = winsec_parse_desc(ret_val, sec_desc_buf,
     
    910994  return ret_val;
    911995
     996 fail_locked:
     997  regfi_unlock(file, file->cb_lock, "regfi_parse_sk");
    912998 fail:
    913999  if(sec_desc_buf != NULL)
     
    9251011  bool unalloc;
    9261012
     1013  if(!regfi_lock(file, file->cb_lock, "regfi_parse_valuelist"))
     1014     goto fail;
     1015
    9271016  if(!regfi_parse_cell(file->cb, offset, NULL, 0, &cell_length, &unalloc))
    9281017  {
    9291018    regfi_add_message(file, REGFI_MSG_ERROR, "Failed to read cell header"
    9301019                      " while parsing value list at offset 0x%.8X.", offset);
    931     return NULL;
     1020    goto fail_locked;
    9321021  }
    9331022
     
    9371026                      " while parsing value list at offset 0x%.8X.", offset);
    9381027    if(strict)
    939       return NULL;
     1028      goto fail_locked;
    9401029    cell_length = cell_length & 0xFFFFFFF8;
    9411030  }
     
    9461035                      " while parsing value list at offset 0x%.8X.", offset);
    9471036    if(strict)
    948       return NULL;
     1037      goto fail_locked;
    9491038    num_values = cell_length/sizeof(uint32_t) - sizeof(uint32_t);
    9501039  }
     
    9531042  ret_val = talloc(NULL, REGFI_VALUE_LIST);
    9541043  if(ret_val == NULL)
    955     return NULL;
     1044    goto fail_locked;
    9561045
    9571046  ret_val->elements = (REGFI_VALUE_LIST_ELEM*)talloc_size(ret_val, read_len);
    9581047  if(ret_val->elements == NULL)
    959   {
    960     talloc_free(ret_val);
    961     return NULL;
    962   }
     1048    goto fail_locked;
     1049
    9631050  ret_val->num_values = num_values;
    9641051
     
    9691056    regfi_add_message(file, REGFI_MSG_ERROR, "Failed to read value pointers"
    9701057                      " while parsing value list at offset 0x%.8X.", offset);
    971     talloc_free(ret_val);
    972     return NULL;
    973   }
    974  
     1058    goto fail_locked;
     1059  }
     1060 
     1061  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_valuelist"))
     1062     goto fail;
     1063
    9751064  for(i=0; i < num_values; i++)
    9761065  {
     
    9891078                          " (0x%.8X) found while parsing value list at offset"
    9901079                          " 0x%.8X.", ret_val->elements[i], offset);
    991         talloc_free(ret_val);
    992         return NULL;
     1080        goto fail;
    9931081      }
    9941082    }
     
    9961084
    9971085  return ret_val;
     1086
     1087 fail_locked:
     1088  regfi_unlock(file, file->cb_lock, "regfi_parse_valuelist");
     1089 fail:
     1090  talloc_free(ret_val);
     1091  return NULL;
    9981092}
    9991093
     
    11951289        }
    11961290      }
    1197       talloc_steal(nk, nk->values);
     1291      talloc_reference(nk, nk->values);
    11981292    }
    11991293  }
     
    12251319        nk->num_subkeys = 0;
    12261320      }
    1227       talloc_steal(nk, nk->subkeys);
     1321      talloc_reference(nk, nk->subkeys);
    12281322    }
    12291323  }
     
    12411335  void* failure_ptr = NULL;
    12421336 
     1337  if(!regfi_lock(file, file->sk_lock, "regfi_load_sk"))
     1338    return NULL;
     1339
    12431340  /* First look if we have already parsed it */
    12441341  ret_val = (REGFI_SK_REC*)lru_cache_find(file->sk_cache, &offset, 4);
     
    12681365  }
    12691366
     1367  if(!regfi_unlock(file, file->sk_lock, "regfi_load_sk"))
     1368    return NULL;
     1369
    12701370  return ret_val;
    12711371}
     
    12861386  while(cur_offset < hbin_end)
    12871387  {
     1388
     1389    if(!regfi_lock(file, file->cb_lock, "regfi_find_root_nk"))
     1390      return NULL;
     1391
    12881392    if(!regfi_parse_cell(file->cb, cur_offset, NULL, 0, &cell_length, &unalloc))
    12891393    {
     
    12921396      return NULL;
    12931397    }
    1294    
     1398
     1399    if(!regfi_unlock(file, file->cb_lock, "regfi_find_root_nk"))
     1400      return NULL;
     1401
    12951402    if(!unalloc)
    12961403    {
     
    13351442
    13361443  /* In this case, we want file_cb to be freed when ret_val is */
    1337   talloc_steal(ret_val, file_cb);
     1444  talloc_reference(ret_val, file_cb);
    13381445  return ret_val;
    13391446
     
    13691476  rb->file_length = file_length; 
    13701477  rb->cb = file_cb;
     1478  rb->cb_lock = NULL;
     1479  rb->hbins_lock = NULL;
     1480  rb->sk_lock = NULL;
     1481
     1482  rb->cb_lock = talloc(rb, pthread_mutex_t);
     1483  if(rb->cb_lock == NULL || pthread_mutex_init(rb->cb_lock, NULL) != 0)
     1484    goto fail;
     1485
     1486  rb->hbins_lock = talloc(rb, pthread_rwlock_t);
     1487  if(rb->hbins_lock == NULL || pthread_rwlock_init(rb->hbins_lock, NULL) != 0)
     1488    goto fail;
     1489
     1490  rb->sk_lock = talloc(rb, pthread_mutex_t);
     1491  if(rb->sk_lock == NULL || pthread_mutex_init(rb->sk_lock, NULL) != 0)
     1492    goto fail;
    13711493
    13721494  rb->hbins = range_list_new();
    13731495  if(rb->hbins == NULL)
    1374   {
    1375     /* fprintf(stderr, "regfi_alloc_cb: Failed to create HBIN list.\n"); */
    1376     talloc_free(rb);
    1377     return NULL;
    1378   }
    1379   talloc_steal(rb, rb->hbins);
     1496    goto fail;
     1497  talloc_reference(rb, rb->hbins);
    13801498
    13811499  rla = true;
     
    13861504    rla = range_list_add(rb->hbins, hbin->file_off, hbin->block_size, hbin);
    13871505    if(rla)
    1388       talloc_steal(rb->hbins, hbin);
     1506      talloc_reference(rb->hbins, hbin);
     1507
    13891508    hbin_off = hbin->file_off + hbin->block_size;
    13901509    hbin = regfi_parse_hbin(rb, hbin_off, true);
     
    14051524  /* success */
    14061525  return rb;
     1526
     1527 fail:
     1528  if(rb->cb_lock != NULL)
     1529    pthread_mutex_destroy(rb->cb_lock);
     1530  if(rb->hbins_lock != NULL)
     1531    pthread_rwlock_destroy(rb->hbins_lock);
     1532  if(rb->sk_lock != NULL)
     1533    pthread_mutex_destroy(rb->sk_lock);
     1534
     1535  range_list_free(rb->hbins);
     1536  talloc_free(rb->cb_lock);
     1537  talloc_free(rb->hbins_lock);
     1538  talloc_free(rb);
     1539  return NULL;
    14071540}
    14081541
     
    14151548    free(file->last_message);
    14161549
     1550  pthread_mutex_destroy(file->cb_lock);
     1551  pthread_rwlock_destroy(file->hbins_lock);
     1552  pthread_mutex_destroy(file->sk_lock);
    14171553  talloc_free(file);
    14181554}
     
    14471583   * block at a time looking for an NK record with a root key type.
    14481584   */
     1585 
     1586  if(!regfi_read_lock(file, file->hbins_lock, "regfi_rootkey"))
     1587    return NULL;
     1588
    14491589  num_hbins = range_list_size(file->hbins);
    14501590  for(i=0; i < num_hbins && nk == NULL; i++)
     
    14531593    nk = regfi_find_root_nk(file, hbin, output_encoding);
    14541594  }
     1595
     1596  if(!regfi_rw_unlock(file, file->hbins_lock, "regfi_rootkey"))
     1597    return NULL;
    14551598
    14561599  return nk;
     
    15191662    return NULL;
    15201663  }
    1521   talloc_steal(ret_val, ret_val->key_positions);
     1664  talloc_reference(ret_val, ret_val->key_positions);
    15221665
    15231666  ret_val->f = file;
     
    15671710    return false;
    15681711  }
    1569   talloc_steal(i, subkey);
     1712  talloc_reference(i, subkey);
    15701713
    15711714  i->cur_key = subkey;
     
    18521995  ret_val->raw = raw;
    18531996  ret_val->size = parse_length;
    1854   talloc_steal(ret_val, raw);
     1997  talloc_reference(ret_val, raw);
    18551998
    18561999  interpreted = talloc_array(NULL, char, parse_length);
     
    18722015    interpreted = talloc_realloc(NULL, interpreted, char, conv_size);
    18732016    ret_val->interpreted = interpreted;
    1874     talloc_steal(ret_val, interpreted);
     2017    talloc_reference(ret_val, interpreted);
    18752018  }
    18762019
     
    19522095    return NULL;
    19532096 
    1954   talloc_steal(ret_val, raw_data.buf);
     2097  talloc_reference(ret_val, raw_data.buf);
    19552098  ret_val->raw = raw_data.buf;
    19562099  ret_val->size = raw_data.len;
     
    20072150    data->interpreted.string = tmp_str;
    20082151    data->interpreted_size = tmp_size;
    2009     talloc_steal(data, tmp_str);
     2152    talloc_reference(data, tmp_str);
    20102153    break;
    20112154
     
    20922235    /* XXX: how meaningful is this?  should we store number of strings instead? */
    20932236    data->interpreted_size = tmp_size;
    2094     talloc_steal(tmp_array, tmp_str);
    2095     talloc_steal(data, tmp_array);
     2237    talloc_reference(tmp_array, tmp_str);
     2238    talloc_reference(data, tmp_array);
    20962239    break;
    20972240
     
    22812424 
    22822425  if(offset >= file->file_length)
    2283     return NULL;
     2426    goto fail;
     2427 
     2428  if(!regfi_lock(file, file->cb_lock, "regfi_parse_hbin"))
     2429    goto fail;
    22842430
    22852431  if(regfi_seek(file->cb, offset, SEEK_SET) == -1)
     
    22872433    regfi_add_message(file, REGFI_MSG_ERROR, "Seek failed"
    22882434                      " while parsing hbin at offset 0x%.8X.", offset);
    2289     return NULL;
     2435    goto fail_locked;
    22902436  }
    22912437
     
    22932439  if((regfi_read(file->cb, hbin_header, &length) != 0)
    22942440     || length != REGFI_HBIN_HEADER_SIZE)
    2295     return NULL;
    2296 
    2297   if(regfi_seek(file->cb, offset, SEEK_SET) == -1)
    2298   {
    2299     regfi_add_message(file, REGFI_MSG_ERROR, "Seek failed"
    2300                       " while parsing hbin at offset 0x%.8X.", offset);
    2301     return NULL;
    2302   }
     2441    goto fail_locked;
     2442
     2443  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_hbin"))
     2444    goto fail;
    23032445
    23042446  hbin = talloc(NULL, REGFI_HBIN);
    23052447  if(hbin == NULL)
    2306     return NULL;
     2448    goto fail;
    23072449  hbin->file_off = offset;
    23082450
     
    23142456                      " 0x%.8X.", hbin->magic[0], hbin->magic[1],
    23152457                      hbin->magic[2], hbin->magic[3], offset);
    2316     talloc_free(hbin);
    2317     return NULL;
     2458    goto fail;
    23182459  }
    23192460
     
    23362477                      " or runs off the end of the file"
    23372478                      " while parsing hbin at offset 0x%.8X.", offset);
    2338     talloc_free(hbin);
    2339     return NULL;
     2479    goto fail;
    23402480  }
    23412481
    23422482  return hbin;
     2483
     2484 fail_locked:
     2485  regfi_unlock(file, file->cb_lock, "regfi_parse_hbin");
     2486 fail:
     2487  talloc_free(hbin);
     2488  return NULL;
    23432489}
    23442490
     
    23542500  bool unalloc = false;
    23552501
     2502  ret_val = talloc(NULL, REGFI_NK_REC);
     2503  if(ret_val == NULL)
     2504  {
     2505    regfi_add_message(file, REGFI_MSG_ERROR, "Failed to allocate memory while"
     2506                      " parsing NK record at offset 0x%.8X.", offset);
     2507    goto fail;
     2508  }
     2509
     2510  if(!regfi_lock(file, file->cb_lock, "regfi_parse_nk"))
     2511    goto fail;
     2512
    23562513  if(!regfi_parse_cell(file->cb, offset, nk_header, REGFI_NK_MIN_LENGTH,
    23572514                       &cell_length, &unalloc))
     
    23592516    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell header"
    23602517                      " while parsing NK record at offset 0x%.8X.", offset);
    2361     return NULL;
    2362   }
    2363 
    2364   /* A bit of validation before bothering to allocate memory */
     2518    goto fail_locked;
     2519  }
     2520
    23652521  if((nk_header[0x0] != 'n') || (nk_header[0x1] != 'k'))
    23662522  {
    23672523    regfi_add_message(file, REGFI_MSG_WARN, "Magic number mismatch in parsing"
    23682524                      " NK record at offset 0x%.8X.", offset);
    2369     return NULL;
    2370   }
    2371 
    2372   ret_val = talloc(NULL, REGFI_NK_REC);
    2373   if(ret_val == NULL)
    2374   {
    2375     regfi_add_message(file, REGFI_MSG_ERROR, "Failed to allocate memory while"
    2376                       " parsing NK record at offset 0x%.8X.", offset);
    2377     return NULL;
     2525    goto fail_locked;
    23782526  }
    23792527
     
    23902538    regfi_add_message(file, REGFI_MSG_WARN, "A length check failed while"
    23912539                      " parsing NK record at offset 0x%.8X.", offset);
    2392     talloc_free(ret_val);
    2393     return NULL;
     2540    goto fail_locked;
    23942541  }
    23952542
     
    24142561     && (ret_val->mtime.high < REGFI_MTIME_MIN_HIGH
    24152562         || ret_val->mtime.high > REGFI_MTIME_MAX_HIGH))
    2416   {
    2417     talloc_free(ret_val);
    2418     return NULL;
    2419   }
     2563  { goto fail_locked; }
    24202564
    24212565  ret_val->unknown1 = IVAL(nk_header, 0xC);
     
    24462590      regfi_add_message(file, REGFI_MSG_ERROR, "Contents too large for cell"
    24472591                        " while parsing NK record at offset 0x%.8X.", offset);
    2448       talloc_free(ret_val);
    2449       return NULL;
     2592      goto fail_locked;
    24502593    }
    24512594    else
     
    24662609  ret_val->keyname_raw = talloc_array(ret_val, uint8_t, ret_val->name_length);
    24672610  if(ret_val->keyname_raw == NULL)
    2468   {
    2469     talloc_free(ret_val);
    2470     return NULL;
    2471   }
     2611    goto fail_locked;
    24722612
    24732613  /* Don't need to seek, should be at the right offset */
     
    24782618    regfi_add_message(file, REGFI_MSG_ERROR, "Failed to read key name"
    24792619                      " while parsing NK record at offset 0x%.8X.", offset);
    2480     talloc_free(ret_val);
    2481     return NULL;
    2482   }
     2620    goto fail_locked;
     2621  }
     2622
     2623  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_nk"))
     2624    goto fail;
    24832625
    24842626  return ret_val;
     2627
     2628 fail_locked:
     2629  regfi_unlock(file, file->cb_lock, "regfi_parse_nk");
     2630 fail:
     2631  talloc_free(ret_val);
     2632  return NULL;
    24852633}
    24862634
     
    24942642  bool unalloc = false;
    24952643
    2496   if(*name_length > 0 && offset != REGFI_OFFSET_NONE
    2497      && (offset & 0x00000007) == 0)
    2498   {
    2499     if(!regfi_parse_cell(file->cb, offset, NULL, 0, &cell_length, &unalloc))
    2500     {
    2501       regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell header"
     2644  if(*name_length <= 0 || offset == REGFI_OFFSET_NONE 
     2645     || (offset & 0x00000007) != 0)
     2646  { goto fail; }
     2647
     2648  if(!regfi_lock(file, file->cb_lock, "regfi_parse_classname"))
     2649    goto fail;
     2650
     2651  if(!regfi_parse_cell(file->cb, offset, NULL, 0, &cell_length, &unalloc))
     2652  {
     2653    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell header"
     2654                      " while parsing class name at offset 0x%.8X.", offset);
     2655    goto fail_locked;
     2656  }
     2657 
     2658  if((cell_length & 0x0000007) != 0)
     2659  {
     2660    regfi_add_message(file, REGFI_MSG_ERROR, "Cell length not a multiple of 8"
     2661                      " while parsing class name at offset 0x%.8X.", offset);
     2662    goto fail_locked;
     2663  }
     2664 
     2665  if(cell_length > max_size)
     2666  {
     2667    regfi_add_message(file, REGFI_MSG_WARN, "Cell stretches past hbin "
     2668                      "boundary while parsing class name at offset 0x%.8X.",
     2669                      offset);
     2670    if(strict)
     2671      goto fail_locked;
     2672    cell_length = max_size;
     2673  }
     2674 
     2675  if((cell_length - 4) < *name_length)
     2676  {
     2677    regfi_add_message(file, REGFI_MSG_WARN, "Class name is larger than"
     2678                      " cell_length while parsing class name at offset"
     2679                      " 0x%.8X.", offset);
     2680    if(strict)
     2681      goto fail_locked;
     2682    *name_length = cell_length - 4;
     2683  }
     2684 
     2685  ret_val = talloc_array(NULL, uint8_t, *name_length);
     2686  if(ret_val != NULL)
     2687  {
     2688    length = *name_length;
     2689    if((regfi_read(file->cb, ret_val, &length) != 0)
     2690       || length != *name_length)
     2691    {
     2692      regfi_add_message(file, REGFI_MSG_ERROR, "Could not read class name"
    25022693                        " while parsing class name at offset 0x%.8X.", offset);
    2503         return NULL;
    2504     }
    2505 
    2506     if((cell_length & 0x0000007) != 0)
    2507     {
    2508       regfi_add_message(file, REGFI_MSG_ERROR, "Cell length not a multiple of 8"
    2509                         " while parsing class name at offset 0x%.8X.", offset);
    2510       return NULL;
    2511     }
    2512 
    2513     if(cell_length > max_size)
    2514     {
    2515       regfi_add_message(file, REGFI_MSG_WARN, "Cell stretches past hbin "
    2516                         "boundary while parsing class name at offset 0x%.8X.",
    2517                         offset);
    2518       if(strict)
    2519         return NULL;
    2520       cell_length = max_size;
    2521     }
    2522 
    2523     if((cell_length - 4) < *name_length)
    2524     {
    2525       regfi_add_message(file, REGFI_MSG_WARN, "Class name is larger than"
    2526                         " cell_length while parsing class name at offset"
    2527                         " 0x%.8X.", offset);
    2528       if(strict)
    2529         return NULL;
    2530       *name_length = cell_length - 4;
    2531     }
    2532    
    2533     ret_val = talloc_array(NULL, uint8_t, *name_length);
    2534     if(ret_val != NULL)
    2535     {
    2536       length = *name_length;
    2537       if((regfi_read(file->cb, ret_val, &length) != 0)
    2538          || length != *name_length)
    2539       {
    2540         regfi_add_message(file, REGFI_MSG_ERROR, "Could not read class name"
    2541                           " while parsing class name at offset 0x%.8X.", offset);
    2542         talloc_free(ret_val);
    2543         return NULL;
    2544       }
    2545     }
    2546   }
     2694      goto fail_locked;
     2695    }
     2696  }
     2697
     2698  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_classname"))
     2699    goto fail;
    25472700
    25482701  return ret_val;
     2702
     2703 fail_locked:
     2704  regfi_unlock(file, file->cb_lock, "regfi_parse_classname");
     2705 fail:
     2706  talloc_free(ret_val);
     2707  return NULL;
    25492708}
    25502709
     
    25602719  bool unalloc = false;
    25612720
     2721  ret_val = talloc(NULL, REGFI_VK_REC);
     2722  if(ret_val == NULL)
     2723    goto fail;
     2724
     2725  if(!regfi_lock(file, file->cb_lock, "regfi_parse_nk"))
     2726    goto fail;
     2727
    25622728  if(!regfi_parse_cell(file->cb, offset, vk_header, REGFI_VK_MIN_LENGTH,
    25632729                       &cell_length, &unalloc))
     
    25652731    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell header"
    25662732                      " while parsing VK record at offset 0x%.8X.", offset);
    2567     return NULL;
    2568   }
    2569 
    2570   ret_val = talloc(NULL, REGFI_VK_REC);
    2571   if(ret_val == NULL)
    2572     return NULL;
     2733    goto fail_locked;
     2734  }
    25732735
    25742736  ret_val->offset = offset;
     
    25842746    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size encountered"
    25852747                      " while parsing VK record at offset 0x%.8X.", offset);
    2586     talloc_free(ret_val);
    2587     return NULL;
     2748    goto fail_locked;
    25882749  }
    25892750
     
    25982759    regfi_add_message(file, REGFI_MSG_WARN, "Magic number mismatch"
    25992760                      " while parsing VK record at offset 0x%.8X.", offset);
    2600     talloc_free(ret_val);
    2601     return NULL;
     2761    goto fail_locked;
    26022762  }
    26032763
     
    26222782                        offset);
    26232783      if(strict)
    2624       {
    2625         talloc_free(ret_val);
    2626         return NULL;
    2627       }
     2784        goto fail_locked;
    26282785      else
    26292786        ret_val->name_length = ret_val->cell_size - REGFI_VK_MIN_LENGTH - 4;
     
    26372794    ret_val->valuename_raw = talloc_array(ret_val, uint8_t, ret_val->name_length);
    26382795    if(ret_val->valuename_raw == NULL)
    2639     {
    2640       talloc_free(ret_val);
    2641       return NULL;
    2642     }
     2796      goto fail_locked;
    26432797
    26442798    length = ret_val->name_length;
     
    26482802      regfi_add_message(file, REGFI_MSG_ERROR, "Could not read value name"
    26492803                        " while parsing VK record at offset 0x%.8X.", offset);
    2650       talloc_free(ret_val);
    2651       return NULL;
     2804      goto fail_locked;
    26522805    }
    26532806  }
    26542807  else
    26552808    cell_length = REGFI_VK_MIN_LENGTH + 4;
     2809
     2810  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_nk"))
     2811    goto fail;
    26562812
    26572813  if(unalloc)
     
    26632819
    26642820  return ret_val;
     2821 
     2822 fail_locked:
     2823  regfi_unlock(file, file->cb_lock, "regfi_parse_vk");
     2824 fail:
     2825  talloc_free(ret_val);
     2826  return NULL;
    26652827}
    26662828
     
    27112873    }
    27122874   
     2875    if(!regfi_lock(file, file->cb_lock, "regfi_load_data"))
     2876      goto fail;
     2877
    27132878    if(!regfi_parse_cell(file->cb, offset, NULL, 0,
    27142879                         &cell_length, &unalloc))
     
    27162881      regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    27172882                        " parsing data record at offset 0x%.8X.", offset);
     2883      goto fail_locked;
     2884    }
     2885
     2886    if(!regfi_unlock(file, file->cb_lock, "regfi_load_data"))
    27182887      goto fail;
    2719     }
    27202888
    27212889    if((cell_length & 0x00000007) != 0)
     
    27652933  return ret_val;
    27662934
     2935 fail_locked:
     2936  regfi_unlock(file, file->cb_lock, "regfi_load_data");
    27672937 fail:
    27682938  ret_val.buf = NULL;
     
    27842954  ret_val.len = 0;
    27852955 
     2956  if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2957    goto fail;
     2958  ret_val.len = length;
     2959
     2960  if(!regfi_lock(file, file->cb_lock, "regfi_parse_data"))
     2961    goto fail;
     2962
    27862963  if(regfi_seek(file->cb, offset+4, SEEK_SET) == -1)
    27872964  {
    27882965    regfi_add_message(file, REGFI_MSG_WARN, "Could not seek while "
    27892966                      "reading data at offset 0x%.8X.", offset);
    2790     return ret_val;
    2791   }
    2792 
    2793   if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
    2794     return ret_val;
    2795   ret_val.len = length;
     2967    goto fail_locked;
     2968  }
    27962969 
    27972970  read_length = length;
     
    28012974    regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
    28022975                      " parsing data record at offset 0x%.8X.", offset);
    2803     talloc_free(ret_val.buf);
    2804     ret_val.buf = NULL;
    2805     ret_val.buf = 0;
    2806   }
    2807 
     2976    goto fail_locked;
     2977  }
     2978
     2979  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_data"))
     2980    goto fail;
     2981
     2982  return ret_val;
     2983
     2984 fail_locked:
     2985  regfi_unlock(file, file->cb_lock, "regfi_parse_data");
     2986 fail:
     2987  talloc_free(ret_val.buf);
     2988  ret_val.buf = NULL;
     2989  ret_val.buf = 0;
    28082990  return ret_val;
    28092991}
     
    28623044  }
    28633045
     3046  if(!regfi_lock(file, file->cb_lock, "regfi_parse_big_data_header"))
     3047    goto fail;
     3048
     3049
    28643050  if(!regfi_parse_cell(file->cb, offset, ret_val.buf, REGFI_BIG_DATA_MIN_LENGTH,
    28653051                       &cell_length, &unalloc))
     
    28673053    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    28683054                      " parsing big data header at offset 0x%.8X.", offset);
    2869     goto fail;
    2870   }
     3055    goto fail_locked;
     3056  }
     3057
     3058  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_header"))
     3059    goto fail;
    28713060
    28723061  if((ret_val.buf[0] != 'd') || (ret_val.buf[1] != 'b'))
     
    28823071  return ret_val;
    28833072
     3073 fail_locked:
     3074  regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_header");
    28843075 fail:
    2885   if(ret_val.buf != NULL)
    2886   {
    2887     talloc_free(ret_val.buf);
    2888     ret_val.buf = NULL;
    2889   }
     3076  talloc_free(ret_val.buf);
     3077  ret_val.buf = NULL;
    28903078  ret_val.len = 0;
    28913079  return ret_val;
     
    29163104    goto fail;
    29173105
     3106  if(!regfi_lock(file, file->cb_lock, "regfi_parse_big_data_indirect"))
     3107    goto fail;
     3108
    29183109  if(!regfi_parse_cell(file->cb, offset, (uint8_t*)ret_val,
    29193110                       num_chunks*sizeof(uint32_t),
     
    29233114                      " parsing big data indirect record at offset 0x%.8X.",
    29243115                      offset);
    2925     goto fail;
    2926   }
     3116    goto fail_locked;
     3117  }
     3118
     3119  if(!regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_indirect"))
     3120    goto fail;
    29273121
    29283122  /* Convert pointers to proper endianess, verify they are aligned. */
     
    29363130  return ret_val;
    29373131
     3132 fail_locked:
     3133  regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_indirect");
    29383134 fail:
    2939   if(ret_val != NULL)
    2940     talloc_free(ret_val);
     3135  talloc_free(ret_val);
    29413136  return NULL;
    29423137}
     
    29703165  for(i=0; i<num_chunks; i++)
    29713166  {
     3167    if(!regfi_lock(file, file->cb_lock, "regfi_parse_big_data_cells"))
     3168      goto fail;
     3169
    29723170    chunk_offset = offsets[i]+REGFI_REGF_SIZE;
    29733171    if(!regfi_parse_cell(file->cb, chunk_offset, NULL, 0,
     
    29773175                        " parsing big data chunk at offset 0x%.8X.",
    29783176                        chunk_offset);
     3177      goto fail_locked;
     3178    }
     3179
     3180    if(!regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_cells"))
    29793181      goto fail;
    2980     }
    29813182
    29823183    if(!range_list_add(ret_val, chunk_offset, cell_length, NULL))
     
    29863187  return ret_val;
    29873188
     3189 fail_locked:
     3190  regfi_unlock(file, file->cb_lock, "regfi_parse_big_data_cells");
    29883191 fail:
    29893192  if(ret_val != NULL)
     
    30793282    }
    30803283
     3284    if(!regfi_lock(file, file->cb_lock, "regfi_load_big_data"))
     3285      goto fail;
     3286
    30813287    if(regfi_seek(file->cb, cell_info->offset+sizeof(uint32_t), SEEK_SET) == -1)
    30823288    {
     
    30843290                        "constructing big data at offset 0x%.8X "
    30853291                        "(chunk offset 0x%.8X).", offset, cell_info->offset);
    3086       goto fail;
     3292      goto fail_locked;
    30873293    }
    30883294
     
    30943300                        " constructing big data at offset 0x%.8X"
    30953301                        " (chunk offset 0x%.8X).", offset, cell_info->offset);
     3302      goto fail_locked;
     3303    }
     3304
     3305    if(!regfi_unlock(file, file->cb_lock, "regfi_load_big_data"))
    30963306      goto fail;
    3097     }
    30983307
    30993308    if(used_ranges != NULL)
     
    31083317  return ret_val;
    31093318
     3319 fail_locked:
     3320  regfi_unlock(file, file->cb_lock, "regfi_load_big_data");
    31103321 fail:
    3111   if(ret_val.buf != NULL)
    3112     talloc_free(ret_val.buf);
    3113   if(indirect_ptrs != NULL)
    3114     talloc_free(indirect_ptrs);
     3322  talloc_free(ret_val.buf);
     3323  talloc_free(indirect_ptrs);
    31153324  if(bd_cells != NULL)
    31163325    range_list_free(bd_cells);
     
    31333342    return NULL;
    31343343
     3344  if(!regfi_read_lock(file, file->hbins_lock, "regfi_parse_unalloc_cells"))
     3345  {
     3346    range_list_free(ret_val);
     3347    return NULL;
     3348  }
     3349
    31353350  num_hbins = range_list_size(file->hbins);
    31363351  for(i=0; i<num_hbins; i++)
     
    31443359    while(curr_off < hbin->block_size)
    31453360    {
     3361      if(!regfi_lock(file, file->cb_lock, "regfi_parse_unalloc_cells"))
     3362        break;
     3363
    31463364      if(!regfi_parse_cell(file->cb, hbin->file_off+curr_off, NULL, 0,
    31473365                           &cell_len, &is_unalloc))
     3366      {
     3367        regfi_unlock(file, file->cb_lock, "regfi_parse_unalloc_cells");
    31483368        break;
    3149      
     3369      }
     3370
     3371      if(!regfi_unlock(file, file->cb_lock, "regfi_parse_unalloc_cells"))
     3372        break;
     3373
    31503374      if((cell_len == 0) || ((cell_len & 0x00000007) != 0))
    31513375      {
     
    31713395  }
    31723396
     3397  if(!regfi_rw_unlock(file, file->hbins_lock, "regfi_parse_unalloc_cells"))
     3398  {
     3399    range_list_free(ret_val);
     3400    return NULL;
     3401  }
     3402
    31733403  return ret_val;
    31743404}
Note: See TracChangeset for help on using the changeset viewer.