[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: back-ldbm/modrdn.c corrupts dn2id.gdbm (ITS#3059)
Your analysis is correct. I've committed a patch based upon
your suggestion to HEAD. Please test.
I note that adding the entry with a new ID might be a better
(safer) solution, but I do not have the time nor energy to
look into that. I'll leave that to others.
Kurt
At 04:30 AM 4/6/2004, wout@science.uva.nl wrote:
>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 ) {