[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
back-ldbm/modrdn.c corrupts dn2id.gdbm (ITS#3059)
Full_Name: Wout van Albada
Version: 2.2.6
OS: Solaris 9
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (146.50.3.34)
The back-ldbm backend has a bug in the modify DN operation
which results in entries remaining in the tree but disappearing
from ancestral subtrees.
Example:
My suffix is:
dc=science,dc=uva,dc=nl
My tree has several branches, one being:
ou=ethers,dc=science,dc=uva,dc=nl
I have the following entry:
cn=pc-bor19.science.uva.nl,dc=science,dc=uva,dc=nl
When I do a modrdn of the cn attribute, the entry's id
disappears from the ou=ethers,... subtree and one id lists
in dn2id.gdbm. This is because of the following code in
back-ldbm/modrdn.c:
/* add new one */
if ( dn2id_add( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
send_ldap_error( op, rs, LDAP_OTHER,
"DN index add failed" );
goto return_results;
}
/* delete old one */
if ( dn2id_delete( op->o_bd, &old_ndn, e->e_id ) != 0 ) {
/* undo add of new one */
dn2id_delete( op->o_bd, &e->e_nname, e->e_id );
send_ldap_error( op, rs, LDAP_OTHER,
"DN index delete fail" );
goto return_results;
}
The modified entry is first added to dn2id.gdbm using the old
id of the entry: e->e_id. This means that the id is added to
the one and subtree id lists for ou=ethers,dc=science,dc=uva,dc=nl.
Then the old entry is removed from dn2id.gdbm using the same
old id. This means that the id is removed from the one and
subtree id lists for ou=ethers,dc=science,dc=uva,dc=nl.
Result is the id is no longer in the one and subtree id
lists for ou=ethers,dc=science,dc=uva,dc=nl.
If the entry was deeper in the tree, more subtrees would be
corrupted. The subtree for dc=science,dc=uva,dc=nl (suffix)
does not exist in dn2id.gdbm because it is treated as a
special case.
The following patch swaps the dn2id_add() and dn2id_delete()
calls and removes the problem:
--- modrdn.c.orig Thu Jan 1 19:16:37 2004
+++ modrdn.c Tue Apr 6 12:43:21 2004
@@ -613,21 +613,22 @@
case SLAPD_ABANDON:
goto return_results;
}
-
- /* add new one */
- if ( dn2id_add( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
- send_ldap_error( op, rs, LDAP_OTHER,
- "DN index add failed" );
- goto return_results;
- }
+
/* delete old one */
if ( dn2id_delete( op->o_bd, &old_ndn, e->e_id ) != 0 ) {
- /* undo add of new one */
- dn2id_delete( op->o_bd, &e->e_nname, e->e_id );
send_ldap_error( op, rs, LDAP_OTHER,
"DN index delete fail" );
goto return_results;
}
+
+ /* add new one */
+ if ( dn2id_add( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
+ /* add failed, try to repair old entry - probably hopeless */
+ dn2id_add( op->o_bd, &old_ndn, e->e_id);
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "DN index add failed" );
+ goto return_results;
+ }
/* id2entry index */
if ( id2entry_add( op->o_bd, e ) != 0 ) {