Changeset 228 for trunk


Ignore:
Timestamp:
04/18/11 16:25:46 (13 years ago)
Author:
tim
Message:

added a test case for pyregfi multithreaded use
updated the regfi multithreaded test case
fixed several ctypes interface problems in pyregfi
added locking to pyregfi iterators for thread safety
fixed regfi talloc race conditions with an additional lock

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r226 r228  
    821821  pthread_mutex_t sk_lock;
    822822
     823  /* Needed to protect various talloc calls */
     824  pthread_mutex_t mem_lock;
     825
    823826} REGFI_FILE;
    824827
     
    971974/** Frees a record previously returned by one of the API functions.
    972975 *
    973  * Can be used to free REGFI_NK, REGFI_VK, REGFI_SK, REGFI_DATA, and
    974  * REGFI_CLASSNAME records.
    975  *
    976  * @note The "const" in the data type is a bit misleading and is there just for
     976 * @param file The file from which the record originated. 
     977 *             (This is needed for memory management reasons.)
     978 *
     979 * @param record Any of the following record types: REGFI_NK, REGFI_VK,
     980 *        REGFI_SK, REGFI_DATA, and REGFI_CLASSNAME records.
     981 *
     982 * @note The "const" in the record data type is a bit misleading and is there just for
    977983 * convenience.  Since records returned previously must not be modified by users
    978984 * of the API due to internal caching, these are returned as const, so this
     
    982988 */
    983989_EXPORT
    984 void regfi_free_record(const void* record);
     990void regfi_free_record(REGFI_FILE* file, const void* record);
    985991
    986992
     
    992998 * without requiring them to be in sync with when it is freed.
    993999 *
    994  * Can be used on REGFI_NK, REGFI_VK, REGFI_SK, REGFI_DATA, and
    995  * REGFI_CLASSNAME records.
     1000 * @param file The file from which the record originated. 
     1001 *             (This is needed for memory management reasons.)
     1002 *
     1003 * @param record Any of the following record types: REGFI_NK, REGFI_VK,
     1004 *        REGFI_SK, REGFI_DATA, and REGFI_CLASSNAME records.
    9961005 *
    9971006 * @return true on success, false otherwise
     
    10001009 */
    10011010_EXPORT
    1002 bool regfi_reference_record(const void* record);
     1011bool regfi_reference_record(REGFI_FILE* file, const void* record);
    10031012
    10041013
  • trunk/lib/regfi.c

    r226 r228  
    16171617  }
    16181618
     1619  if(pthread_mutex_init(&rb->mem_lock, NULL) != 0)
     1620  {
     1621    regfi_log_add(REGFI_LOG_ERROR, "Failed to create mem_lock mutex.");
     1622    goto fail;
     1623  }
     1624
    16191625  rb->hbins = range_list_new();
    16201626  if(rb->hbins == NULL)
     
    16571663  pthread_rwlock_destroy(&rb->hbins_lock);
    16581664  pthread_mutex_destroy(&rb->sk_lock);
     1665  pthread_mutex_destroy(&rb->mem_lock);
    16591666
    16601667  range_list_free(rb->hbins);
     
    17211728/******************************************************************************
    17221729 *****************************************************************************/
    1723 void regfi_free_record(const void* record)
    1724 {
     1730void regfi_free_record(REGFI_FILE* file, const void* record)
     1731{
     1732  if(!regfi_lock(file, &file->mem_lock, "regfi_free_record"))
     1733    return;
     1734
    17251735  talloc_unlink(NULL, (void*)record);
     1736
     1737  regfi_unlock(file, &file->mem_lock, "regfi_free_record");
    17261738}
    17271739
     
    17291741/******************************************************************************
    17301742 *****************************************************************************/
    1731 bool regfi_reference_record(const void* record)
    1732 {
     1743bool regfi_reference_record(REGFI_FILE* file, const void* record)
     1744{
     1745  bool ret_val = false;
     1746  if(!regfi_lock(file, &file->mem_lock, "regfi_reference_record"))
     1747    return ret_val;
     1748 
    17331749  if(talloc_reference(NULL, record) != NULL)
    1734     return true;
    1735   return false;
     1750    ret_val = true;
     1751
     1752  regfi_unlock(file, &file->mem_lock, "regfi_reference_record");
     1753  return ret_val;
    17361754}
    17371755
     
    18231841void regfi_iterator_free(REGFI_ITERATOR* i)
    18241842{
    1825   talloc_free(i);
     1843  talloc_unlink(NULL, i);
    18261844}
    18271845
     
    18541872    talloc_unlink(NULL, subkey);
    18551873    return false;
    1856   }
     1874  } 
    18571875  talloc_reparent(NULL, i, subkey);
    18581876
     
    18751893    return false;
    18761894
     1895  if(!regfi_lock(i->f, &i->f->mem_lock, "regfi_iterator_up"))
     1896    return false;
     1897 
    18771898  talloc_unlink(i, i->cur_key);
     1899  regfi_unlock(i->f, &i->f->mem_lock, "regfi_iterator_up");
     1900
    18781901  i->cur_key = pos->nk;
    18791902  i->cur_subkey = pos->cur_subkey;
     
    19431966const REGFI_NK* regfi_iterator_cur_key(REGFI_ITERATOR* i)
    19441967{
    1945   return talloc_reference(NULL, i->cur_key);
     1968  const REGFI_NK* ret_val = NULL;
     1969  if(!regfi_lock(i->f, &i->f->mem_lock, "regfi_iterator_cur_key"))
     1970    return ret_val;
     1971
     1972  ret_val = talloc_reference(NULL, i->cur_key);
     1973
     1974  regfi_unlock(i->f, &i->f->mem_lock, "regfi_iterator_cur_key"); 
     1975  return ret_val;
    19461976}
    19471977
     
    21742204    }
    21752205
    2176     regfi_free_record(cur);
     2206    regfi_free_record(file, cur);
    21772207  }
    21782208
     
    22112241    }
    22122242
    2213     regfi_free_record(cur);
     2243    regfi_free_record(file, cur);
    22142244  }
    22152245
     
    22572287{
    22582288  if(key != NULL && key->parent_off != REGFI_OFFSET_NONE)
    2259   {
    2260     /*    fprintf(stderr, "key->parent_off=%.8X\n", key->parent_off);*/
    22612289    return regfi_load_key(file,
    22622290                          key->parent_off+REGFI_REGF_SIZE,
    22632291                          file->string_encoding, true);
    2264   }
    2265  
     2292
    22662293  return NULL;
    22672294}
  • trunk/python/pyregfi/__init__.py

    r227 r228  
    9595import sys
    9696import time
    97 from pyregfi.structures import *
    98 
    9997import ctypes
    10098import ctypes.util
     99import threading
     100from pyregfi.structures import *
     101
    101102
    102103## An enumeration of registry Value data types
     
    218219
    219220
    220 
    221221## Abstract class for most objects returned by the library
    222222class _StructureWrapper(object):
     
    239239    # Memory management for most regfi structures is taken care of here
    240240    def __del__(self):
    241         regfi.regfi_free_record(self._base)
     241        regfi.regfi_free_record(self._hive.file, self._base)
    242242
    243243
     
    299299                            + "Current log:\n" + GetLogMessages())
    300300       
    301         if not regfi.regfi_reference_record(key._base):
     301        if not regfi.regfi_reference_record(key._hive.file, key._base):
    302302            raise Exception("Could not create _GenericList; memory error."
    303303                            + "Current log:\n" + GetLogMessages())
     
    308308   
    309309    def __del__(self):
    310         regfi.regfi_free_record(self._key_base)
    311    
     310        regfi.regfi_free_record(self._hive.file, self._key_base)
     311
    312312
    313313    ## Length of list
     
    486486                ret_val = _buffer2bytearray(cn_struct.raw,
    487487                                            cn_struct.size)
    488             regfi.regfi_free_record(cn_p)
     488            regfi.regfi_free_record(self._hive.file, cn_p)
    489489
    490490        return ret_val
     
    581581                                        data_struct.interpreted_size)
    582582
    583         regfi.regfi_free_record(data_p)
     583        regfi.regfi_free_record(self._hive.file, data_p)
    584584        return ret_val
    585585   
     
    599599        ret_val = _buffer2bytearray(data_struct.raw,
    600600                                    data_struct.size)
    601         regfi.regfi_free_record(data_p)
     601        regfi.regfi_free_record(self._hive.file, data_p)
    602602        return ret_val
    603603
     
    747747    _iter = None
    748748    _iteration_root = None
     749    _lock = None
    749750
    750751    def __init__(self, hive):
    751         self._iter = regfi.regfi_iterator_new(hive.file, REGFI_ENCODING_UTF8)
     752        self._iter = regfi.regfi_iterator_new(hive.file)
    752753        if not self._iter:
    753754            raise Exception("Could not create iterator.  Current log:\n"
    754755                            + GetLogMessages())
    755756        self._hive = hive
    756        
     757        self._lock = threading.RLock()
     758   
    757759    def __getattr__(self, name):
    758         return getattr(self.file.contents, name)
    759 
    760     def __del__(self):   
     760        self._lock.acquire()
     761        ret_val = getattr(self._iter.contents, name)
     762        self._lock.release()
     763        return ret_val
     764
     765    def __del__(self):
     766        self._lock.acquire()
    761767        regfi.regfi_iterator_free(self._iter)
     768        self._lock.release()
    762769
    763770    def __iter__(self):
     771        self._lock.acquire()
    764772        self._iteration_root = None
     773        self._lock.release()
    765774        return self
    766775
    767776    def __next__(self):
     777        self._lock.acquire()
    768778        if self._iteration_root == None:
    769             self._iteration_root = self.current_key()
     779            self._iteration_root = self.current_key().offset
    770780        elif not regfi.regfi_iterator_down(self._iter):
    771781            up_ret = regfi.regfi_iterator_up(self._iter)
    772782            while (up_ret and
    773783                   not regfi.regfi_iterator_next_subkey(self._iter)):
    774                 if self._iteration_root == self.current_key():
     784                if self._iteration_root == self.current_key().offset:
    775785                    self._iteration_root = None
     786                    self._lock.release()
    776787                    raise StopIteration('')
    777788                up_ret = regfi.regfi_iterator_up(self._iter)
     
    779790            if not up_ret:
    780791                self._iteration_root = None
     792                self._lock.release()
    781793                raise StopIteration('')
    782794           
    783795            # XXX: Use non-generic exception
    784796            if not regfi.regfi_iterator_down(self._iter):
     797                self._lock.release()
    785798                raise Exception('Error traversing iterator downward.'+
    786799                                ' Current log:\n'+ GetLogMessages())
    787800
    788801        regfi.regfi_iterator_first_subkey(self._iter)
    789         return self.current_key()
     802        ret_val = self.current_key()
     803        self._lock.release()
     804
     805        return ret_val
     806
    790807
    791808    # For Python 2.x
     
    806823    # @return True if successful, False otherwise
    807824    def down(self, subkey_name=None):
     825        ret_val = None
    808826        if subkey_name == None:
    809             return regfi.regfi_iterator_down(self._iter)
     827            self._lock.acquire()
     828            ret_val = regfi.regfi_iterator_down(self._iter)
    810829        else:
    811830            if name != None:
    812831                name = name.encode('utf-8')
    813             return (regfi.regfi_iterator_find_subkey(self._iter, name)
    814                     and regfi.regfi_iterator_down(self._iter))
     832            self._lock.acquire()
     833            ret_val = (regfi.regfi_iterator_find_subkey(self._iter, name)
     834                       and regfi.regfi_iterator_down(self._iter))
     835       
     836        self._lock.release()
     837        return ret_val
    815838
    816839
     
    824847    #       default selections.
    825848    def up(self):
    826         return regfi.regfi_iterator_up(self._iter)
     849        self._lock.acquire()
     850        ret_val = regfi.regfi_iterator_up(self._iter)
     851        self._lock.release()
     852        return ret_val
    827853
    828854
     
    832858    #         None on error or if the current key has no subkeys.
    833859    def first_subkey(self):
     860        ret_val = None
     861        self._lock.acquire()
    834862        if regfi.regfi_iterator_first_subkey(self._iter):
    835             return self.current_subkey()
    836         return None
     863            ret_val = self.current_subkey()
     864        self._lock.release()
     865        return ret_val
    837866
    838867
     
    842871    #         None on error or if the current key has no values.
    843872    def first_value(self):
     873        ret_val = None
     874        self._lock.acquire()
    844875        if regfi.regfi_iterator_first_value(self._iter):
    845             return self.current_value()
    846         return None
     876            ret_val = self.current_value()
     877        self._lock.release()
     878        return ret_val
    847879
    848880
     
    852884    #         None if there are no remaining subkeys or an error occurred.
    853885    def next_subkey(self):
     886        ret_val = None
     887        self._lock.acquire()
    854888        if regfi.regfi_iterator_next_subkey(self._iter):
    855             return self.current_subkey()
    856         return None
     889            ret_val = self.current_subkey()
     890        self._lock.release()
     891        return ret_val
    857892
    858893
     
    862897    #         None if there are no remaining values or an error occurred.
    863898    def next_value(self):
     899        ret_val = None
     900        self._lock.acquire()
    864901        if regfi.regfi_iterator_next_value(self._iter):
    865             return self.current_value()
    866         return None
     902            ret_val = self.current_value()
     903        self._lock.release()
     904        return ret_val
    867905
    868906
     
    874912        if name != None:
    875913            name = name.encode('utf-8')
     914        ret_val = None
     915        self._lock.acquire()
    876916        if regfi.regfi_iterator_find_subkey(self._iter, name):
    877             return self.current_subkey()
    878         return None
     917            ret_val = self.current_subkey()
     918        self._lock.release()
     919        return ret_val
    879920
    880921
     
    886927        if name != None:
    887928            name = name.encode('utf-8')
     929        ret_val = None
     930        self._lock.acquire()
    888931        if regfi.regfi_iterator_find_value(self._iter, name):
    889             return self.current_value()
    890         return None
     932            ret_val = self.current_value()
     933        self._lock.release()
     934        return ret_val
    891935
    892936    ## Retrieves the currently selected subkey
     
    894938    # @return A Key instance of the current subkey
    895939    def current_subkey(self):
    896         return Key(self._hive, regfi.regfi_iterator_cur_subkey(self._iter))
     940        self._lock.acquire()
     941        ret_val = Key(self._hive, regfi.regfi_iterator_cur_subkey(self._iter))
     942        self._lock.release()
     943        return ret_val
    897944
    898945    ## Retrieves the currently selected value
     
    900947    # @return A Value instance of the current value
    901948    def current_value(self):
    902         return Value(self._hive, regfi.regfi_iterator_cur_value(self._iter))
     949        self._lock.acquire()
     950        ret_val = Value(self._hive, regfi.regfi_iterator_cur_value(self._iter))
     951        self._lock.release()
     952        return ret_val
    903953
    904954    ## Retrieves the current key
     
    906956    # @return A Key instance of the current position of the iterator
    907957    def current_key(self):
    908         return Key(self._hive, regfi.regfi_iterator_cur_key(self._iter))
     958        self._lock.acquire()
     959        ret_val = Key(self._hive, regfi.regfi_iterator_cur_key(self._iter))
     960        self._lock.release()
     961        return ret_val
    909962
    910963
     
    919972        cpath = _strlist2charss(path)
    920973
    921         # XXX: Use non-generic exception
    922         if not regfi.regfi_iterator_walk_path(self._iter, cpath):
     974        self._lock.acquire()
     975        result = regfi.regfi_iterator_walk_path(self._iter, cpath)
     976        self._lock.release()
     977        if not result:
     978            # XXX: Use non-generic exception
    923979            raise Exception('Could not locate path.\n'+GetLogMessages())
    924980
  • trunk/python/pyregfi/structures.py

    r227 r228  
    171171REGFI_VALUE_LIST._fields_ = [('offset', c_uint32),
    172172                             ('cell_size', c_uint32),
    173                              ('num_children', c_uint32),
    174173                             ('num_values', c_uint32),
    175174                             ('elements', c_void_p),
     
    247246regfi.regfi_get_rootkey.restype = POINTER(REGFI_NK)
    248247
    249 regfi.regfi_free_record.argtypes = [c_void_p]
     248regfi.regfi_free_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
    250249regfi.regfi_free_record.restype = None
    251250
    252 regfi.regfi_reference_record.argtypes = [c_void_p]
     251regfi.regfi_reference_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
    253252regfi.regfi_reference_record.restype = c_bool
    254253
     
    290289regfi.regfi_nt2unix_time.restype = c_double
    291290
    292 regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
     291regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE)]
    293292regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
    294293
     
    305304regfi.regfi_iterator_to_root.restype = c_bool
    306305
    307 regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR)]
     306regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR), POINTER(c_char_p)]
    308307regfi.regfi_iterator_walk_path.restype = c_bool
    309308
  • trunk/src/reglookup-recover.c

    r223 r228  
    291291        {
    292292          /* XXX: Need to add a warning here */
    293           regfi_free_record(cur_ancestor);
     293          regfi_free_record(f, cur_ancestor);
    294294          void_stack_free(path_stack);
    295295          return NULL;
     
    303303        ret_val_size += path_element->len + 1;
    304304
    305         regfi_free_record(cur_ancestor);
     305        regfi_free_record(f, cur_ancestor);
    306306      }
    307307    }
     
    631631
    632632 fail:
    633   regfi_free_record(key);
     633  regfi_free_record(f, key);
    634634  return error_code;
    635635}
  • trunk/src/reglookup.c

    r213 r228  
    9595      fprintf(stderr, "WARN: While quoting value for '%s/%s', "
    9696              "warning returned: %s\n", prefix, quoted_name, conv_error);
    97     regfi_free_record(data);
     97    regfi_free_record(iter->f, data);
    9898  }
    9999
     
    282282    if(!type_filter_enabled || (value->type == type_filter))
    283283      printValue(iter, value, prefix);
    284     regfi_free_record(value);
     284    regfi_free_record(iter->f, value);
    285285    regfi_iterator_next_value(iter);
    286286    printMsgs(iter->f);
     
    310310    sacl = regfi_get_sacl(sk->sec_desc);
    311311    dacl = regfi_get_dacl(sk->sec_desc);
    312     regfi_free_record(sk);
     312    regfi_free_record(iter->f, sk);
    313313
    314314    if(owner == NULL)
     
    345345    else
    346346      quoted_classname = empty_str;
    347     regfi_free_record(classname);
     347    regfi_free_record(iter->f, classname);
    348348
    349349    printMsgs(iter->f);
     
    365365    printf("%s,KEY,,%s\n", full_path, mtime);
    366366
    367   regfi_free_record(key);
     367  regfi_free_record(iter->f, key);
    368368}
    369369
     
    406406      if(cur != root)
    407407      {
    408         regfi_free_record(cur);
     408        regfi_free_record(iter->f, cur);
    409409        /* We're done with this sub-tree, going up and hitting other branches. */
    410410        if(!regfi_iterator_up(iter))
     
    430430       * Let's move down and print this first sub-tree out.
    431431       */
    432       regfi_free_record(cur);
     432      regfi_free_record(iter->f, cur);
    433433      if(!regfi_iterator_down(iter))
    434434      {
     
    438438
    439439      cur = regfi_iterator_cur_key(iter);
    440       regfi_free_record(sub);
     440      regfi_free_record(iter->f, sub);
    441441      regfi_iterator_first_subkey(iter);
    442442      sub = regfi_iterator_cur_subkey(iter);
     
    445445    printMsgs(iter->f);
    446446  } while(!((cur == root) && (sub == NULL)));
    447   regfi_free_record(root);
     447  regfi_free_record(iter->f, root);
    448448
    449449  if(print_verbose)
     
    518518      printValue(iter, value, tmp_path_joined);
    519519
    520     regfi_free_record(value);
     520    regfi_free_record(iter->f, value);
    521521    free(tmp_path);
    522522    free(tmp_path_joined);
Note: See TracChangeset for help on using the changeset viewer.