From: Howard Chu Date: Thu, 6 Dec 2007 05:48:02 +0000 (+0000) Subject: ITS#5262 must protect dn2id between the time it's read from the DB X-Git-Tag: OPENLDAP_REL_ENG_2_4_9~20^2~350 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=cb0e31fc65e155d3627e70ee1f3489e7951f3862;p=openldap ITS#5262 must protect dn2id between the time it's read from the DB and it's inserted into EntryInfo cache. --- diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 6e49d132a2..c83ddf0764 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -70,13 +70,15 @@ typedef struct __db_locker * BDB_LOCKER; extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret); #define CURSOR_SETLOCKER(cursor, id) cursor->locker = id -#define CURSOR_GETLOCKER(cursor) cursor->locker +#define CURSOR_GETLOCKER(cursor) cursor->locker +#define BDB_LOCKID(locker) locker->id #else typedef u_int32_t BDB_LOCKER; #define CURSOR_SETLOCKER(cursor, id) cursor->locker = id #define CURSOR_GETLOCKER(cursor) cursor->locker +#define BDB_LOCKID(locker) locker #endif diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 93be806635..ffe8580cfc 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -155,12 +155,6 @@ bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei ) * alternatives though. */ -#if DB_VERSION_FULL >= 0x04060012 -#define BDB_LOCKID(locker) locker->id -#else -#define BDB_LOCKID(locker) locker -#endif - /* Atomically release and reacquire a lock */ int bdb_cache_entry_db_relock( @@ -426,6 +420,7 @@ bdb_cache_find_ndn( ei.bei_parent = eip; ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp ); if ( !ei2 ) { + DB_LOCK lock; int len = ei.bei_nrdn.bv_len; if ( BER_BVISEMPTY( ndn )) { @@ -442,9 +437,11 @@ bdb_cache_find_ndn( ei.bei_nrdn.bv_val ); #endif - rc = bdb_dn2id( op, locker, &ei.bei_nrdn, &ei ); + lock.mode = DB_LOCK_NG; + rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, locker, &lock ); if (rc) { bdb_cache_entryinfo_lock( eip ); + bdb_cache_entry_db_unlock( bdb, &lock ); *res = eip; return rc; } @@ -461,6 +458,7 @@ bdb_cache_find_ndn( ei.bei_nrdn.bv_val, ei.bei_id, 0 ); /* add_internal left eip and c_rwlock locked */ ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); + bdb_cache_entry_db_unlock( bdb, &lock ); if ( rc ) { *res = eip; return rc; diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 0f6b1927bb..33234ceaa0 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -23,6 +23,29 @@ #include "idl.h" #include "lutil.h" +#define bdb_dn2id_lock BDB_SYMBOL(dn2id_lock) + +static int +bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn, + int rw, BDB_LOCKER locker, DB_LOCK *lock ) +{ + int rc; + DBT lockobj; + int db_rw; + + if (rw) + db_rw = DB_LOCK_WRITE; + else + db_rw = DB_LOCK_READ; + + lockobj.data = dn->bv_val; + lockobj.size = dn->bv_len; + + rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), DB_LOCK_NOWAIT, + &lockobj, db_rw, lock); + return rc; +} + #ifndef BDB_HIER int bdb_dn2id_add( @@ -146,10 +169,11 @@ bdb_dn2id_delete( { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; - int rc; - DBT key; char *buf; + DBT key; + DB_LOCK lock; struct berval pdn, ptr; + int rc; Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n", e->e_ndn, e->e_id, 0 ); @@ -165,6 +189,10 @@ bdb_dn2id_delete( AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len ); ptr.bv_val[ptr.bv_len] = '\0'; + /* We hold this lock until the TXN completes */ + rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock ); + if ( rc ) return rc; + /* delete it */ rc = db->del( db, txn, &key, 0 ); if( rc != 0 ) { @@ -244,9 +272,10 @@ done: int bdb_dn2id( Operation *op, - BDB_LOCKER locker, struct berval *dn, - EntryInfo *ei ) + EntryInfo *ei, + BDB_LOCKER locker, + DB_LOCK *lock ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; @@ -268,6 +297,9 @@ bdb_dn2id( data.ulen = sizeof(ID); data.flags = DB_DBT_USERMEM; + rc = bdb_dn2id_lock( bdb, dn, 0, locker, lock ); + if ( rc ) return rc; + rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; if ( locker ) { @@ -576,6 +608,7 @@ hdb_dn2id_delete( int rc; ID nid; unsigned char dlen[2]; + DB_LOCK lock; DBTzero(&key); key.size = sizeof(ID); @@ -589,6 +622,10 @@ hdb_dn2id_delete( data.dlen = data.size; data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; + /* We hold this lock until the TXN completes */ + rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock ); + if ( rc ) return rc; + key.data = &nid; rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; @@ -646,9 +683,10 @@ hdb_dn2id_delete( int hdb_dn2id( Operation *op, - BDB_LOCKER locker, struct berval *in, - EntryInfo *ei ) + EntryInfo *ei, + BDB_LOCKER locker, + DB_LOCK *lock ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; @@ -677,6 +715,9 @@ hdb_dn2id( data.dlen = data.ulen; data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; + rc = bdb_dn2id_lock( bdb, in, 0, locker, lock ); + if ( rc ) return rc; + rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; if ( locker ) { diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index d0f01989ad..d1691b0808 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -97,9 +97,10 @@ int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid, int bdb_dn2id( Operation *op, - BDB_LOCKER locker, struct berval *dn, - EntryInfo *ei ); + EntryInfo *ei, + BDB_LOCKER locker, + DB_LOCK *lock ); int bdb_dn2id_add( Operation *op,