From: Kevin Lam Date: Tue, 21 Feb 2017 04:20:38 +0000 (+0800) Subject: ITS#8592 Fix double free in sssvlv overlay X-Git-Tag: OPENLDAP_REL_ENG_2_4_45~9 X-Git-Url: https://git.sur5r.net/?p=openldap;a=commitdiff_plain;h=0c3b5b0fc169fdfbf27585f1078edf5f0ff4b7ea ITS#8592 Fix double free in sssvlv overlay --- diff --git a/servers/slapd/overlays/sssvlv.c b/servers/slapd/overlays/sssvlv.c index 8df3bf732f..17c7bf915a 100644 --- a/servers/slapd/overlays/sssvlv.c +++ b/servers/slapd/overlays/sssvlv.c @@ -116,6 +116,7 @@ typedef struct sort_op int so_vlv_target; int so_session; unsigned long so_vcontext; + int so_running; } sort_op; /* There is only one conn table for all overlay instances */ @@ -396,30 +397,35 @@ static int find_next_session( static void free_sort_op( Connection *conn, sort_op *so ) { int sess_id; - if ( so->so_tree ) { - if ( so->so_paged > SLAP_CONTROL_IGNORED ) { - Avlnode *cur_node, *next_node; - cur_node = so->so_tree; - while ( cur_node ) { - next_node = tavl_next( cur_node, TAVL_DIR_RIGHT ); - ch_free( cur_node->avl_data ); - ber_memfree( cur_node ); - - cur_node = next_node; - } - } else { - tavl_free( so->so_tree, ch_free ); - } - so->so_tree = NULL; - } - + ldap_pvt_thread_mutex_lock( &sort_conns_mutex ); sess_id = find_session_by_so( so->so_info->svi_max_percon, conn->c_conn_idx, so ); - sort_conns[conn->c_conn_idx][sess_id] = NULL; - so->so_info->svi_num--; + if ( sess_id > -1 ) { + sort_conns[conn->c_conn_idx][sess_id] = NULL; + so->so_info->svi_num--; + } ldap_pvt_thread_mutex_unlock( &sort_conns_mutex ); - - ch_free( so ); + + if ( sess_id > -1 ){ + if ( so->so_tree ) { + if ( so->so_paged > SLAP_CONTROL_IGNORED ) { + Avlnode *cur_node, *next_node; + cur_node = so->so_tree; + while ( cur_node ) { + next_node = tavl_next( cur_node, TAVL_DIR_RIGHT ); + ch_free( cur_node->avl_data ); + ber_memfree( cur_node ); + + cur_node = next_node; + } + } else { + tavl_free( so->so_tree, ch_free ); + } + so->so_tree = NULL; + } + + ch_free( so ); + } } static void free_sort_ops( Connection *conn, sort_op **sos, int svi_max_percon ) @@ -704,6 +710,8 @@ static void send_result( if ( so->so_tree == NULL ) { /* Search finished, so clean up */ free_sort_op( op->o_conn, so ); + } else { + so->so_running = 0; } } @@ -859,26 +867,40 @@ static int sssvlv_op_search( sess_id = find_session_by_context( si->svi_max_percon, op->o_conn->c_conn_idx, vc ? vc->vc_context : NO_VC_CONTEXT, ps ? ps->ps_cookie : NO_PS_COOKIE ); if ( sess_id >= 0 ) { so = sort_conns[op->o_conn->c_conn_idx][sess_id]; - /* Is it a continuation of a VLV search? */ - if ( !vc || so->so_vlv <= SLAP_CONTROL_IGNORED || - vc->vc_context != so->so_vcontext ) { - /* Is it a continuation of a paged search? */ - if ( !ps || so->so_paged <= SLAP_CONTROL_IGNORED || - op->o_conn->c_pagedresults_state.ps_cookie != ps->ps_cookie ) { - ok = 0; - } else if ( !ps->ps_size ) { - /* Abandoning current request */ - ok = 0; - so->so_nentries = 0; - rs->sr_err = LDAP_SUCCESS; - } - } - if (( vc && so->so_paged > SLAP_CONTROL_IGNORED ) || - ( ps && so->so_vlv > SLAP_CONTROL_IGNORED )) { - /* changed from paged to vlv or vice versa, abandon */ - ok = 0; - so->so_nentries = 0; - rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + + if( so->so_running > 0 ){ + /* another thread is handling, response busy to client */ + so = NULL; + ok = 0; + } else { + + /* Is it a continuation of a VLV search? */ + if ( !vc || so->so_vlv <= SLAP_CONTROL_IGNORED || + vc->vc_context != so->so_vcontext ) { + /* Is it a continuation of a paged search? */ + if ( !ps || so->so_paged <= SLAP_CONTROL_IGNORED || + op->o_conn->c_pagedresults_state.ps_cookie != ps->ps_cookie ) { + ok = 0; + } else if ( !ps->ps_size ) { + /* Abandoning current request */ + ok = 0; + so->so_nentries = 0; + rs->sr_err = LDAP_SUCCESS; + } + } + if (( vc && so->so_paged > SLAP_CONTROL_IGNORED ) || + ( ps && so->so_vlv > SLAP_CONTROL_IGNORED )) { + /* changed from paged to vlv or vice versa, abandon */ + ok = 0; + so->so_nentries = 0; + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + + if ( ok ) { + /* occupy before mutex unlock */ + so->so_running = 1; + } + } /* Are there too many running overall? */ } else if ( si->svi_num >= si->svi_max ) { @@ -947,6 +969,7 @@ static int sssvlv_op_search( so->so_vlv = op->o_ctrlflag[vlv_cid]; so->so_vcontext = (unsigned long)so; so->so_nentries = 0; + so->so_running = 1; op->o_callback = cb; }