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

Cache corruption caused by delete (ITS#39)



Full_Name: Robert Rothlisberger
Version: 1.1.2
OS: SunOS 2.5.1
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (208.220.157.29)


#
# slapd ldbm cache problem.
#
# 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*"