]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#10164 back-meta hangs when used with dynlist overlay
authorNadezhda Ivanova <nivanova@symas.com>
Wed, 7 Feb 2024 14:35:48 +0000 (16:35 +0200)
committerQuanah Gibson-Mount <quanah@openldap.org>
Thu, 15 Feb 2024 18:12:46 +0000 (18:12 +0000)
Make sure every proxied operation has a separate candidates structure.

servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c

index ec75db1d3a82afa78121342deeefa3e936598cb5..8e3137519ed0f99997000bc85ac0975c677fe097 100644 (file)
@@ -47,15 +47,17 @@ meta_back_add( Operation *op, SlapReply *rs )
        int             msgid;
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
-
+       SlapReply *candidates = NULL;
        Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
                        op->o_req_dn.bv_val );
 
        /*
         * get the current connection
         */
-       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       candidates = meta_back_candidates_get( op );
+       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
+       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
@@ -181,7 +183,7 @@ retry:;
                mt->mt_timeout[ SLAP_OP_ADD ], ( LDAP_BACK_SENDRESULT | retrying ) );
        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
                retrying &= ~LDAP_BACK_RETRYING;
-               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                        goto retry;
@@ -205,7 +207,7 @@ done:;
        if ( mc ) {
                meta_back_release_conn( mi, mc );
        }
-
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }
 
index 82b210509391f1f2ce73c408a00cceaab6fc41d6..1ddf5a2f84b05c48655a2add486993f679949dee 100644 (file)
@@ -489,7 +489,8 @@ meta_back_getconn(
        Operation               *op,
        SlapReply               *rs,
        int                     *candidate,
-       ldap_back_send_t        sendok );
+       ldap_back_send_t        sendok,
+       SlapReply *candidates );
 
 extern void
 meta_back_release_conn_lock(
@@ -504,7 +505,8 @@ meta_back_retry(
        SlapReply               *rs,
        metaconn_t              **mcp,
        int                     candidate,
-       ldap_back_send_t        sendok );
+       ldap_back_send_t        sendok,
+       SlapReply    *candidates );
 
 extern void
 meta_back_conn_free(
@@ -538,7 +540,8 @@ meta_back_dobind(
        Operation               *op,
        SlapReply               *rs,
        metaconn_t              *mc,
-       ldap_back_send_t        sendok );
+       ldap_back_send_t        sendok,
+       SlapReply               *candidates );
 
 extern int
 meta_back_single_dobind(
@@ -625,7 +628,8 @@ meta_back_select_unique_candidate(
 extern int
 meta_clear_unused_candidates(
        Operation               *op,
-       int                     candidate );
+       int                     candidate,
+       SlapReply *candidates );
 
 extern int
 meta_clear_one_candidate(
index edfabbb440728932f189c5ee49eb0155a79f83f5..dded298da23bfb23e2d89db2878ba93f35a15add 100644 (file)
@@ -89,10 +89,11 @@ meta_back_bind( Operation *op, SlapReply *rs )
                return rs->sr_err;
        }
 
+       candidates = meta_back_candidates_get( op );
        /* we need meta_back_getconn() not send result even on error,
         * because we want to intercept the error and make it
         * invalidCredentials */
-       mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND );
+       mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND, candidates );
        if ( !mc ) {
                Debug(LDAP_DEBUG_ANY,
                      "%s meta_back_bind: no target " "for dn \"%s\" (%d%s%s).\n",
@@ -110,11 +111,10 @@ meta_back_bind( Operation *op, SlapReply *rs )
                        break;
                }
                send_ldap_result( op, rs );
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
-       candidates = meta_back_candidates_get( op );
-
        /*
         * Each target is scanned ...
         */
@@ -284,10 +284,12 @@ meta_back_bind( Operation *op, SlapReply *rs )
                        rs->sr_err = slap_map_api2result( rs );
                }
                send_ldap_result( op, rs );
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
 
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return LDAP_SUCCESS;
 }
 
@@ -672,7 +674,8 @@ meta_back_dobind(
        Operation               *op,
        SlapReply               *rs,
        metaconn_t              *mc,
-       ldap_back_send_t        sendok )
+       ldap_back_send_t        sendok,
+       SlapReply               *candidates )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
 
@@ -680,8 +683,6 @@ meta_back_dobind(
                                i,
                                isroot = 0;
 
-       SlapReply               *candidates;
-
        if ( be_isroot( op ) ) {
                isroot = 1;
        }
@@ -704,8 +705,6 @@ meta_back_dobind(
                goto done;
        }
 
-       candidates = meta_back_candidates_get( op );
-
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                metatarget_t            *mt = mi->mi_targets[ i ];
                metasingleconn_t        *msc = &mc->mc_conns[ i ];
@@ -761,7 +760,7 @@ retry_binding:;
                        if ( rc == LDAP_UNAVAILABLE ) {
                                /* FIXME: meta_back_retry() already re-calls
                                 * meta_back_single_dobind() */
-                               if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
+                               if ( meta_back_retry( op, rs, &mc, i, sendok, candidates ) ) {
                                        goto retry_ok;
                                }
 
index ffb5992de3861d5490f18f5506a3b32b96a79fd0..3cc3dab3c490dcbad7cb3cb132079af64ba875a3 100644 (file)
@@ -222,11 +222,11 @@ meta_back_select_unique_candidate(
 int
 meta_clear_unused_candidates(
        Operation       *op,
-       int             candidate )
+       int             candidate,
+       SlapReply       *candidates )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
        int             i;
-       SlapReply       *candidates = meta_back_candidates_get( op );
        
        for ( i = 0; i < mi->mi_ntargets; ++i ) {
                if ( i == candidate ) {
index f6fd54dd67f7c951a38f7090fdf138ab30e119d7..4c77d49c96e997c43e106ddef13fe7a806dd2232 100644 (file)
@@ -46,9 +46,12 @@ meta_back_compare( Operation *op, SlapReply *rs )
        int             msgid;
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
+       SlapReply *candidates = NULL;
 
-       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       candidates = meta_back_candidates_get( op );
+       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
+       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
@@ -127,7 +130,7 @@ retry:;
                mt->mt_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) );
        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
                retrying &= ~LDAP_BACK_RETRYING;
-               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                        goto retry;
@@ -149,6 +152,7 @@ cleanup:;
                meta_back_release_conn( mi, mc );
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }
 
index 91fdad35e2a33b2b05fc28b8f009a58e05aca7d6..9b5fec4a81c9209a6c35739c6340ee806254082e 100644 (file)
@@ -699,7 +699,8 @@ meta_back_retry(
        SlapReply               *rs,
        metaconn_t              **mcp,
        int                     candidate,
-       ldap_back_send_t        sendok )
+       ldap_back_send_t        sendok,
+       SlapReply      *candidates )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metatarget_t            *mt = mi->mi_targets[ candidate ];
@@ -971,64 +972,14 @@ meta_back_get_candidate(
        return candidate;
 }
 
-static void    *meta_back_candidates_dummy;
-
-static void
-meta_back_candidates_keyfree(
-       void            *key,
-       void            *data )
-{
-       metacandidates_t        *mc = (metacandidates_t *)data;
-
-       ber_memfree_x( mc->mc_candidates, NULL );
-       ber_memfree_x( data, NULL );
-}
-
 SlapReply *
 meta_back_candidates_get( Operation *op )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metacandidates_t        *mc;
-
-       if ( op->o_threadctx ) {
-               void            *data = NULL;
-
-               ldap_pvt_thread_pool_getkey( op->o_threadctx,
-                               &meta_back_candidates_dummy, &data, NULL );
-               mc = (metacandidates_t *)data;
+       SlapReply       *candidates;
 
-       } else {
-               mc = mi->mi_candidates;
-       }
-
-       if ( mc == NULL ) {
-               mc = ch_calloc( sizeof( metacandidates_t ), 1 );
-               mc->mc_ntargets = mi->mi_ntargets;
-               mc->mc_candidates = ch_calloc( sizeof( SlapReply ), mc->mc_ntargets );
-               if ( op->o_threadctx ) {
-                       void            *data = NULL;
-
-                       data = (void *)mc;
-                       ldap_pvt_thread_pool_setkey( op->o_threadctx,
-                                       &meta_back_candidates_dummy, data,
-                                       meta_back_candidates_keyfree,
-                                       NULL, NULL );
-
-               } else {
-                       mi->mi_candidates = mc;
-               }
-
-       } else if ( mc->mc_ntargets < mi->mi_ntargets ) {
-               /* NOTE: in the future, may want to allow back-config
-                * to add/remove targets from back-meta... */
-               mc->mc_candidates = ch_realloc( mc->mc_candidates,
-                               sizeof( SlapReply ) * mi->mi_ntargets );
-               memset( &mc->mc_candidates[ mc->mc_ntargets ], 0,
-                       sizeof( SlapReply ) * ( mi->mi_ntargets - mc->mc_ntargets ) );
-               mc->mc_ntargets = mi->mi_ntargets;
-       }
-
-       return mc->mc_candidates;
+       candidates = op->o_tmpcalloc( mi->mi_ntargets, sizeof( SlapReply ), op->o_tmpmemctx );
+       return candidates;
 }
 
 /*
@@ -1066,10 +1017,11 @@ meta_back_candidates_get( Operation *op )
  */
 metaconn_t *
 meta_back_getconn(
-               Operation               *op,
+       Operation               *op,
        SlapReply               *rs,
        int                     *candidate,
-       ldap_back_send_t        sendok )
+       ldap_back_send_t        sendok,
+       SlapReply       *candidates )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
        metaconn_t      *mc = NULL,
@@ -1090,8 +1042,6 @@ meta_back_getconn(
        struct berval   ndn = op->o_req_ndn,
                        pndn;
 
-       SlapReply       *candidates = meta_back_candidates_get( op );
-
        /* Internal searches are privileged and shared. So is root. */
        if ( ( !BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ALWAYS( mi ) )
                || ( BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ANON( mi ) )
@@ -1474,7 +1424,7 @@ retry_lock2:;
                /*
                 * Clear all other candidates
                 */
-               ( void )meta_clear_unused_candidates( op, i );
+               ( void )meta_clear_unused_candidates( op, i, candidates );
 
                mt = mi->mi_targets[ i ];
                msc = &mc->mc_conns[ i ];
index bec437aee15d3390e9f0352c20d7ae21db7dfc90..cc9799783f51bac1d97c19fc74ca14c769ae1045 100644 (file)
@@ -43,9 +43,12 @@ meta_back_delete( Operation *op, SlapReply *rs )
        int             msgid;
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
+       SlapReply *candidates = NULL;
 
-       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       candidates = meta_back_candidates_get( op );
+       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
+       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
@@ -79,7 +82,7 @@ retry:;
                mt->mt_timeout[ SLAP_OP_DELETE ], ( LDAP_BACK_SENDRESULT | retrying ) );
        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
                retrying &= ~LDAP_BACK_RETRYING;
-               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                        goto retry;
@@ -98,6 +101,7 @@ cleanup:;
                meta_back_release_conn( mi, mc );
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }
 
index 459e835a588633d7a8e8f04e964cea1c328d4bad..daa8efe5ca2edff431bfaf5de8adf1a8eebc51c1 100644 (file)
@@ -49,9 +49,12 @@ meta_back_modify( Operation *op, SlapReply *rs )
        int             msgid;
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
+       SlapReply *candidates = NULL;
 
-       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       candidates = meta_back_candidates_get( op );
+       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
+       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
@@ -180,7 +183,7 @@ retry:;
                mt->mt_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) );
        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
                retrying &= ~LDAP_BACK_RETRYING;
-               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                        goto retry;
@@ -205,6 +208,7 @@ cleanup:;
                meta_back_release_conn( mi, mc );
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }
 
index cf6e1be065f2ee94ef255c36187c6cfa445957a5..adcf16ee5abdfa9611ebb01fe398c8327d53b4fc 100644 (file)
@@ -45,9 +45,12 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
        struct berval   newrdn = BER_BVNULL;
+       SlapReply *candidates = NULL;
 
-       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
-       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
+       candidates = meta_back_candidates_get( op );
+       mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
+       if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
+               op->o_tmpfree( candidates, op->o_tmpmemctx );
                return rs->sr_err;
        }
 
@@ -142,7 +145,7 @@ retry:;
                mt->mt_timeout[ SLAP_OP_MODRDN ], ( LDAP_BACK_SENDRESULT | retrying ) );
        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
                retrying &= ~LDAP_BACK_RETRYING;
-               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                        goto retry;
@@ -172,6 +175,7 @@ cleanup:;
                meta_back_release_conn( mi, mc );
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }
 
index 727dbb3ca19fac8927509fb33fbc43cb11250a53..0466536da8756c93f1e14dfac3707b1207e4112f 100644 (file)
@@ -722,7 +722,7 @@ retry:;
                break;
        
        case LDAP_SERVER_DOWN:
-               if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
+               if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND, candidates ) ) {
                        nretries = 0;
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
@@ -798,8 +798,9 @@ meta_back_search( Operation *op, SlapReply *rs )
         * FIXME: in case of values return filter, we might want
         * to map attrs and maybe rewrite value
         */
+       candidates = meta_back_candidates_get( op );
 getconn:;
-       mc = meta_back_getconn( op, rs, NULL, sendok );
+       mc = meta_back_getconn( op, rs, NULL, sendok, candidates );
        if ( !mc ) {
                return rs->sr_err;
        }
@@ -807,7 +808,6 @@ getconn:;
        dc.conn = op->o_conn;
        dc.rs = rs;
 
-       if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
        /*
         * Inits searches
         */
@@ -1146,7 +1146,7 @@ really_bad:;
                                if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
                                        candidates[ i ].sr_type = REP_RESULT;
 
-                                       if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
+                                       if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND, candidates ) ) {
                                                candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                                switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
                                                {
@@ -1997,6 +1997,7 @@ finish:;
                ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
        }
 
+       op->o_tmpfree( candidates, op->o_tmpmemctx );
        return rs->sr_err;
 }