From: Nadezhda Ivanova Date: Wed, 7 Feb 2024 14:35:48 +0000 (+0200) Subject: ITS#10164 back-meta hangs when used with dynlist overlay X-Git-Tag: OPENLDAP_REL_ENG_2_5_18~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ce2afd8edf0a9013fe1b5e7226ea34e8c3617e8;p=thirdparty%2Fopenldap.git ITS#10164 back-meta hangs when used with dynlist overlay Make sure every proxied operation has a separate candidates structure. --- diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index ec75db1d3a..8e3137519e 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -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; } diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index 82b2105093..1ddf5a2f84 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -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( diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index edfabbb440..dded298da2 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -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; } diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c index ffb5992de3..3cc3dab3c4 100644 --- a/servers/slapd/back-meta/candidates.c +++ b/servers/slapd/back-meta/candidates.c @@ -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 ) { diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c index f6fd54dd67..4c77d49c96 100644 --- a/servers/slapd/back-meta/compare.c +++ b/servers/slapd/back-meta/compare.c @@ -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; } diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 91fdad35e2..9b5fec4a81 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -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 ]; diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c index bec437aee1..cc9799783f 100644 --- a/servers/slapd/back-meta/delete.c +++ b/servers/slapd/back-meta/delete.c @@ -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; } diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index 459e835a58..daa8efe5ca 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -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; } diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c index cf6e1be065..adcf16ee5a 100644 --- a/servers/slapd/back-meta/modrdn.c +++ b/servers/slapd/back-meta/modrdn.c @@ -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; } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 727dbb3ca1..0466536da8 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -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; }