[Date Prev][Date Next] [Chronological] [Thread] [Top]

Openldap ldbm cache corruption



FYI, Same as previous just added the subject line (RWR)

> #
> # slapd ldbm cache problem. ITS#39
> #
> # This script will cause slapd to hang in a loop
> # after deleting the one entry.
> #
> # To cause the hanging loop you have to decrease the cache
> # size to 5 in slapd/back-ldbm/back-ldbm.h
> # sinze th loop is caused only when the system tries to free up
> # the corrupted cache entry that was caused by the delete.
> #
> # The problem is that the cache is sorted by using the dn's
> # however some dn's are normalized and others are not.
> # Using the data below the cache is not built in
> # normalized dn order, it's built based on the dn's
> # used by the calling routine. ldapsearch populates the
> # cache with non-normalized dn's, but delete search based on the
> # cache being sorted based on a normalized dn.  So if the
> # cache is out of order based on the noramlized dn the delete
> # fails to remove the item from the cache. (id2entry.c)
> # This corrupts the cache so that latter when the cache has reached
> # max size and the corrupted entry is tring to be cleared.
> # an infinite loop is encountered (back-ldbm/cache.c)
> 
> #		 /*
> #       * found at least one to delete - try to get back under
> #       * the max cache size.
> #       */
> #      while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
> #                    == 0 && cache->c_cursize > cache->c_maxsize ) {
> #
> #         e = cache->c_lrutail;
> #
> #         /* XXX check for writer lock - should also check no readers
> pending */
> ##ifdef LDAP_DEBUG
> #         assert(!pthread_rdwr_rwchk_np(&e->e_rdwr));
> ##endif
> #         /* delete from cache and lru q */
> #
> #			// This code fails, on the corrupted entry. RWR
> #         rc = cache_delete_entry_internal( cache, e );
> #
> #			// Since the above fails the conditions for this
> loop
> #			// this will be done until crash
> #         entry_free( e );
> #
> #      }
> 
> #
> # Fixes
> #   The easiest way for me was to add:
> #		dn_normalize( e->e_dn );
> #	at the start of cache_add_entry_lock() (back-ldbm/cache.c)
> #
> #  The problem with this is that all dn  entries in the database
> #	will be stored in normalized form.  ( not really a problem at
> least for
> #	me).  But ldif2ldbm should also reflect this since any existing
> #	dn's need to be changed.
> #
> #
> #  Anyways, if you run the script below it will cause the error.
> #  The last search is commented out since it will loop slapd,
> #  but if you search the err file you will see the could not delete
> from
> #  cache entry.
> #
> 
> 
> cat > testdata <<!
> dn: c=US
> objectclass: country
> c: US
> 
> dn: o=Cache Test1,c=Us
> objectclass: organization
> o: Cache Test1
> 
> dn: o=Cache Test2,c=Us
> objectclass: organization
> o: Cache Test2
> 
> dn: o=Cache Test3, c=Us
> objectclass: organization
> o: Cache Test3
> 
> dn: cn=CacheTest,o=Cache Test1,c=US
> cn: CacheTest
> sn: CacheTest
> o: Cache Test1
> 
> dn: cn=CacheTest,o=Cache Test2,c=US
> cn: CacheTest
> sn: CacheTest
> o: Cache Test2
> 
> dn: cn=CacheTest, o=Cache Test3, c=US
> cn: CacheTest
> sn: CacheTest
> o: Cache Test3
> 
> dn: cn=CacheTesta, o=Cache Test3, c=US
> cn: CacheTest
> sn: CacheTest
> o: Cache Test3
> !
> 
> ldif2ldbm -i testdata -f slapd.conf
> 
> ./slapd -d129 -f slapd.conf 2>err &
> 
> ldapsearch "cn=Ca*"
> 
> # This delete will cause slapd to generate a could not delete from
> cache
> # error.
> ldapdelete -D cn=xyzzy -w password "cn=CacheTest, o=Cache Test3, c=US"
> 
> 
> 
> # Warning on my system this search will cause slapd to hang
> # in a loop generating a large err file.
> # I had to kill it with a kill -9
> # ldapsearch "cn=Ca*"