From 268070ea2bef973a7630c81389fa2f28ffd12d17 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Jan 12 2016 21:42:16 +0000 Subject: Ticket 48388 - db2ldif -r segfaults from time to time Bug Description: db2ldif starts all the plugins before generating the ldif file. If the retro changelog is enabled and it starts to trim itself the server can crash when cos tries to process the retrocl triming operations. Fix Description: First, fix the NULL dereferences in COS. Then when doing a "db2ldif -r" only startup the plugins that "db2ldif -r" needs (which is just the replication plugin and its dependencies). Revised the plugin_startall() function to remove unused parameters (start_backends & global_plugins) Also did a little code clean up slapi_utf8casecmp. https://fedorahosted.org/389/ticket/48388 Valgrind: passed Reviewed by: nhosoi(Thanks!) (cherry picked from commit c7c3d5963243574f8f8cf5f292fba27486a40d4a) --- diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c index e0b841d..f3ea7db 100644 --- a/ldap/servers/plugins/cos/cos_cache.c +++ b/ldap/servers/plugins/cos/cos_cache.c @@ -3034,7 +3034,8 @@ static int cos_cache_attr_compare(const void *e1, const void *e2) cosTemplates *pTemplate1 = (cosTemplates*)pAttr1->pParent; /* Now compare the names of the attributes */ - com_Result = slapi_utf8casecmp((unsigned char*)(*(cosAttributes**)e1)->pAttrName,(unsigned char*)(*(cosAttributes**)e2)->pAttrName); + com_Result = slapi_utf8casecmp((unsigned char*)(*(cosAttributes**)e1)->pAttrName, + (unsigned char*)(*(cosAttributes**)e2)->pAttrName); if(0 == com_Result){ /* Now compare the cosPriorities */ com_Result = pTemplate->cosPriority - pTemplate1->cosPriority; @@ -3047,6 +3048,13 @@ static int cos_cache_attr_compare(const void *e1, const void *e2) static int cos_cache_string_compare(const void *e1, const void *e2) { + if (!e1 && e2) { + return 1; + } else if (e1 && !e2) { + return -1; + } else if (!e1 && !e2) { + return 0; + } return slapi_utf8casecmp((*(unsigned char**)e1),(*(unsigned char**)e2)); } @@ -3054,6 +3062,13 @@ static int cos_cache_template_index_compare(const void *e1, const void *e2) { int ret = 0; + if (!e1 && e2) { + return 1; + } else if (e1 && !e2) { + return -1; + } else if (!e1 && !e2) { + return 0; + } if(0 == slapi_dn_issuffix((const char*)e1,*(const char**)e2)) ret = slapi_utf8casecmp(*(unsigned char**)e2,(unsigned char*)e1); else diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c index 4f9fbfe..b048dc5 100644 --- a/ldap/servers/slapd/main.c +++ b/ldap/servers/slapd/main.c @@ -1051,7 +1051,7 @@ main( int argc, char **argv) pw_exp_init (); plugin_print_lists(); - plugin_startall(argc, argv, 1 /* Start Backends */, 1 /* Start Globals */); + plugin_startall(argc, argv, NULL /* specific plugin list */); compute_plugins_started(); if (housekeeping_start((time_t)0, NULL) == NULL) { return_value = 1; @@ -2216,13 +2216,24 @@ slapd_exemode_db2ldif(int argc, char** argv) else pb.pb_server_running = 0; - if (db2ldif_dump_replica) { - eq_init(); /* must be done before plugins started */ - ps_init_psearch_system(); /* must come before plugin_startall() */ - plugin_startall(argc, argv, 1 /* Start Backends */, - 1 /* Start Globals */); - eq_start(); /* must be done after plugins started */ - } + if (db2ldif_dump_replica) { + char **plugin_list = NULL; + char *repl_plg_name = "Multimaster Replication Plugin"; + + /* + * Only start the necessary plugins for "db2ldif -r" + * + * We need replication, but replication has its own + * dependencies + */ + plugin_get_plugin_dependencies(repl_plg_name, &plugin_list); + + eq_init(); /* must be done before plugins started */ + ps_init_psearch_system(); /* must come before plugin_startall() */ + plugin_startall(argc, argv, plugin_list); + eq_start(); /* must be done after plugins started */ + charray_free(plugin_list); + } pb.pb_ldif_file = NULL; if ( archive_name ) { /* redirect stdout to this file: */ diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c index 0e99095..496f9e8 100644 --- a/ldap/servers/slapd/plugin.c +++ b/ldap/servers/slapd/plugin.c @@ -1390,6 +1390,47 @@ plugin_free_plugin_dep_config(plugin_dep_config **cfg) } } +/* + * Take a given plugin and recursively set all the plugin dependency names + */ +void +plugin_get_plugin_dependencies(char *plugin_name, char ***names) +{ + entry_and_plugin_t *ep = dep_plugin_entries; + char **depends = NULL; + char *dep_attr = "nsslapd-plugin-depends-on-named"; + int i; + + /* Add the original plugin name to the list */ + if (!charray_inlist(*names, plugin_name)){ + charray_add(names, slapi_ch_strdup(plugin_name)); + } + + /* Find the plugin and grab its dependencies */ + while(ep) + { + if (ep->plugin){ + if(strcasecmp(ep->plugin->plg_name, plugin_name) == 0){ + /* We found our plugin, now grab its dependencies */ + depends = slapi_entry_attr_get_charray(ep->e, dep_attr); + break; + } + } + ep = ep->next; + } + + if (depends){ + /* Add the plugin's dependencies */ + charray_merge_nodup(names, depends, 1); + + /* Add each dependency's dependencies */ + for (i = 0; depends[i]; i++){ + /* recurse */ + plugin_get_plugin_dependencies(depends[i], names); + } + slapi_ch_array_free(depends); + } +} /* * plugin_dependency_startall() @@ -1407,7 +1448,7 @@ plugin_free_plugin_dep_config(plugin_dep_config **cfg) */ static int -plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation) +plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation, char** plugin_list) { int ret = 0; Slapi_PBlock pb; @@ -1419,7 +1460,7 @@ plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation) int i = 0; /* general index iterator */ plugin_dep_type the_plugin_type; int index = 0; - char * value; + char *value = NULL; int plugins_started; int num_plg_started; struct slapdplugin *plugin; @@ -1435,25 +1476,50 @@ plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation) global_plugin_callbacks_enabled = 0; /* Count the plugins so we can allocate memory for the config array */ - while(ep) + while(ep) { total_plugins++; - ep = ep->next; } /* allocate the config array */ config = (plugin_dep_config*)slapi_ch_calloc(total_plugins + 1, sizeof(plugin_dep_config)); - ep = dep_plugin_entries; + if (plugin_list){ + /* We have a plugin list, so we need to reset the plugin count */ + total_plugins = 0; + } /* Collect relevant config */ - while(ep) + while(ep) { plugin = ep->plugin; - if(plugin == 0) + if(plugin == 0){ + ep = ep->next; continue; + } + + if (plugin_list){ + /* + * We have a specific list of plugins to start, skip the others... + */ + int found = 0; + for (i = 0; plugin_list[i]; i++){ + if (strcasecmp(plugin->plg_name, plugin_list[i]) == 0){ + found = 1; + break; + } + } + + if (!found){ + /* Skip this plugin, it's not in the list */ + ep = ep->next; + continue; + } else { + total_plugins++; + } + } pblock_init(&pb); slapi_pblock_set( &pb, SLAPI_ARGC, &argc); @@ -1824,12 +1890,13 @@ plugin_dependency_closeall() * stuff is done with. So this function goes through and starts all plugins */ void -plugin_startall(int argc, char** argv, int start_backends, int start_global) +plugin_startall(int argc, char** argv, char **plugin_list) { /* initialize special plugin structures */ default_plugin_init (); - plugin_dependency_startall(argc, argv, "plugin startup failed\n", SLAPI_PLUGIN_START_FN); + plugin_dependency_startall(argc, argv, "plugin startup failed\n", + SLAPI_PLUGIN_START_FN, plugin_list); } /* diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 8fcebb8..f745852 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -853,11 +853,14 @@ int plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid *group, int plugin_call_exop_plugins( Slapi_PBlock *pb, char *oid ); const char *plugin_extended_op_oid2string( const char *oid ); void plugin_closeall(int close_backends, int close_globals); -void plugin_startall(int argc,char **argv,int start_backends, int start_global); +void plugin_startall(int argc, char **argv, char **plugin_list); +void plugin_get_plugin_dependencies(char *plugin_name, char ***names); struct slapdplugin *get_plugin_list(int plugin_list_index); -PRBool plugin_invoke_plugin_sdn (struct slapdplugin *plugin, int operation, Slapi_PBlock *pb, Slapi_DN *target_spec); +PRBool plugin_invoke_plugin_sdn (struct slapdplugin *plugin, int operation, + Slapi_PBlock *pb, Slapi_DN *target_spec); struct slapdplugin *plugin_get_by_name(char *name); -struct slapdplugin *plugin_get_pwd_storage_scheme(char *name, int len, int index); +struct slapdplugin *plugin_get_pwd_storage_scheme(char *name, int len, + int index); char *plugin_get_pwd_storage_scheme_list(int index); int plugin_add_descriptive_attributes( Slapi_Entry *e, struct slapdplugin *plugin ); diff --git a/ldap/servers/slapd/utf8compare.c b/ldap/servers/slapd/utf8compare.c index 3201df7..592f039 100644 --- a/ldap/servers/slapd/utf8compare.c +++ b/ldap/servers/slapd/utf8compare.c @@ -2115,15 +2115,15 @@ slapi_utf8casecmp(unsigned char *s0, unsigned char *s1) d0 = d1 = NULL; if (s0 == NULL || *s0 == '\0') { - if (s1 == NULL || *s1 == '\0') { - rval = 0; - } else { - rval = -1; /* regardless s1, s0 < s1 */ - } - goto end; + if (s1 == NULL || *s1 == '\0') { + rval = 0; + } else { + rval = -1; /* regardless s1, s0 < s1 */ + } + goto end; } else if (s1 == NULL || *s1 == '\0') { - rval = 1; /* regardless s0, s0 > s1 */ - goto end; + rval = 1; /* regardless s0, s0 > s1 */ + goto end; } has8_s0 = slapi_has8thBit(s0); @@ -2141,9 +2141,9 @@ slapi_utf8casecmp(unsigned char *s0, unsigned char *s1) d0 = slapi_utf8StrToLower(s0); d1 = slapi_utf8StrToLower(s1); if (d0 == NULL || d1 == NULL || /* either is not a UTF-8 string */ - (d0 && *d0 == '\0') || (d1 && *d1 == '\0')) { - rval = strcasecmp((char *)s0, (char *)s1); - goto end; + (d0 && *d0 == '\0') || (d1 && *d1 == '\0')) { + rval = strcasecmp((char *)s0, (char *)s1); + goto end; } p0 = d0; @@ -2157,25 +2157,25 @@ slapi_utf8casecmp(unsigned char *s0, unsigned char *s1) n0 = (unsigned char *)ldap_utf8next((char *)p0); n1 = (unsigned char *)ldap_utf8next((char *)p1); if (n0 > t0 || n1 > t1) { - break; - } + break; + } i0 = n0 - p0; i1 = n1 - p1; - rval = i0 - i1; + rval = i0 - i1; if (rval) { /* length is different */ goto end; - } + } /* i0 == i1: same length */ for (x0 = p0, x1 = p1; x0 < n0; x0++, x1++) { rval = *x0 - *x1; if (rval) { goto end; - } + } } - p0 = n0; p1 = n1; /* goto next */ + p0 = n0; p1 = n1; /* goto next */ } /* finished scanning the shared part and check the leftover */ l0 = t0 - n0;