diff --git a/.gitignore b/.gitignore index 45aeca8..811bcba 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/slapi-nis-0.56.0.tar.gz +SOURCES/slapi-nis-0.56.5.tar.gz diff --git a/.slapi-nis.metadata b/.slapi-nis.metadata index 6769a0c..8e1fbca 100644 --- a/.slapi-nis.metadata +++ b/.slapi-nis.metadata @@ -1 +1 @@ -097cb06b3adfd66664ec785186c47ff3b0c52c16 SOURCES/slapi-nis-0.56.0.tar.gz +3766addae0581012e6f2429270f093c3862db68c SOURCES/slapi-nis-0.56.5.tar.gz diff --git a/SOURCES/slapi-0001-Move-advance-definition-of-backend_passwdmod_extop-b.patch b/SOURCES/slapi-0001-Move-advance-definition-of-backend_passwdmod_extop-b.patch deleted file mode 100644 index 729ed8f..0000000 --- a/SOURCES/slapi-0001-Move-advance-definition-of-backend_passwdmod_extop-b.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 55efe7e2be2ed7664e2d5bb5b2b0d9d11d5e3f70 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 20 Jun 2016 21:41:12 +0300 -Subject: [PATCH 1/4] Move advance definition of backend_passwdmod_extop before - use - ---- - src/back-sch.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 5ba04f4..ff8e8a2 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -54,6 +54,7 @@ - #include "map.h" - #include "back-sch.h" - -+static int backend_passwdmod_extop(Slapi_PBlock *pb); - backend_extop_handlers_t extop_handlers[] = {{EXTOP_PASSWD_OID, (IFP) backend_passwdmod_extop}, - {NULL, NULL}}; - static void --- -2.7.4 - diff --git a/SOURCES/slapi-0002-Initialize-ret-before-use.patch b/SOURCES/slapi-0002-Initialize-ret-before-use.patch deleted file mode 100644 index 948a14f..0000000 --- a/SOURCES/slapi-0002-Initialize-ret-before-use.patch +++ /dev/null @@ -1,25 +0,0 @@ -From a65243050c2c765b8c9edfdab9164c82c754c39b Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 20 Jun 2016 21:41:35 +0300 -Subject: [PATCH 2/4] Initialize ret before use - ---- - src/back-sch.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index ff8e8a2..bb2aa74 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2376,7 +2376,7 @@ static int - backend_extop_cb(Slapi_PBlock *pb) - { - struct plugin_state *state; -- int ret; -+ int ret = 0; - int i; - char *oid = NULL; - IFP fct = NULL; --- -2.7.4 - diff --git a/SOURCES/slapi-0003-slapi-nis-resolve-IPA-groups-with-fully-qualified-su.patch b/SOURCES/slapi-0003-slapi-nis-resolve-IPA-groups-with-fully-qualified-su.patch deleted file mode 100644 index dfa973f..0000000 --- a/SOURCES/slapi-0003-slapi-nis-resolve-IPA-groups-with-fully-qualified-su.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0a5e61c042679679646f6f8f673028f8fbcf3ea7 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 15 Jun 2016 12:15:46 +0300 -Subject: [PATCH 03/17] slapi-nis: resolve IPA groups with fully qualified - suffix - -With SSSD 1.14+ there is a logic change to handling of a default domain -suffix. - -SSSD has two different formats to handle: the input and output. The -input format is parsed into (name,domain) tuples with the re_expression -option and the output is formatted with the full_name_format option. - -Because of the way SSSD used to store the usernames in sysdb, it was -tied to the full_name_format option, just changing the output format -changed the way the names are stored internally. SSSD changed the cache -to always store names in a unified format (foo@bar) and use the -full_name_format only for output, as it should be. - -This changed a logic of use_fully_qualified_names=True. It now mandates -that the /input/ contains both the name and the domain part and then -SSSD formats the output using the full_name_format option. The -default_domain_suffix is a hack that just appends its value to an -unqualified input, making all queries for "foo" into "foo@bar". - -In new SSSD if configuration contains: - default_domain_suffix = win.domain - full_name_format = $1 # only name - -then a request for "foo" will internally turn into "foo@win.domain" but -return "foo" on the output. However, queries for IPA's foo will have to -be qualified by the admin manually like "foo@ipa.domain" otherwise sssd -doesn't know which foo you meant. - -Support this logic by querying associatedDomain attribute of the -restricted bases of the data set. IPA stores this information in the -$SUFFIX base dn (dc=example,dc=com) and configures slapi-nis with -restricted base set to $SUFFIX (and the plugin config). While -associatedDomain attribute is multivalued, the $SUFFIX object always has -a single value corresponding to the IPA domain name that is the same as -SSSD domain suffix. ---- - src/back-sch.c | 41 +++++++++++++++++++++++++++++++++++++++++ - src/back-sch.h | 1 + - 2 files changed, 42 insertions(+) - -diff --git a/src/back-sch.c b/src/back-sch.c -index bb2aa74..cdd2b3c 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -98,6 +98,7 @@ backend_set_config_free_config_contents(void *data) - slapi_sdn_free(&set_data->container_sdn); - free(set_data->rdn_format); - backend_shr_free_strlist(set_data->attribute_format); -+ slapi_ch_free_string(&set_data->associated_domain); - } - } - void -@@ -149,6 +150,7 @@ backend_copy_set_config(const struct backend_set_data *data) - ret->check_access = data->check_access; - ret->check_nsswitch = data->check_nsswitch; - ret->nsswitch_min_id = data->nsswitch_min_id; -+ ret->associated_domain = data->associated_domain ? slapi_ch_strdup(data->associated_domain) : NULL; - - if ((ret->common.group == NULL) || - (ret->common.set == NULL) || -@@ -266,6 +268,39 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, - free(nsswitch_min_id); - } - -+ ret.associated_domain = NULL; -+ if (ret.common.restrict_subtrees != NULL) { -+ Slapi_PBlock *pb = NULL; -+ int result = 0; -+ Slapi_Entry **entries = NULL; -+ int i,j; -+ for (i=0; ret.common.restrict_subtrees[i] != NULL; i++) { -+ pb = wrap_pblock_new(NULL); -+ if (pb != NULL) { -+ slapi_search_internal_set_pb_ext(pb, (Slapi_DN*) ret.common.restrict_subtrees[i], LDAP_SCOPE_BASE, -+ "(&(objectclass=domainRelatedObject)(associatedDomain=*))", -+ NULL, 0, NULL, NULL, state->plugin_identity, 0); -+ result = slapi_search_internal_pb(pb); -+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); -+ if (result == 0) { -+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); -+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, NULL); -+ for (j=0; entries[j] != NULL; j++) { -+ ret.associated_domain = slapi_entry_attr_get_charptr(entries[j], "associatedDomain"); -+ slapi_entry_free(entries[i]); -+ if (ret.associated_domain != NULL) -+ break; -+ } -+ slapi_ch_free((void**)entries); -+ } -+ } -+ slapi_pblock_destroy(pb); -+ pb = NULL; -+ if (ret.associated_domain != NULL) -+ break; -+ } -+ } -+ - *pret = backend_copy_set_config(&ret); - if (*pret == NULL) { - if (strlen(container) > 0) { -@@ -437,6 +472,7 @@ backend_set_process_external_members(Slapi_PBlock *pb, - struct backend_staged_search staged = {0, }; - struct backend_search_cbdata cbdata = {0, }; - char *plugin_id = state->plugin_desc->spd_id; -+ char *gname = NULL; - - is_attr_exists = slapi_entry_attr_find(e, IPA_ATTR_EXTERNAL_MEMBER, &attr) == 0; - -@@ -448,6 +484,11 @@ backend_set_process_external_members(Slapi_PBlock *pb, - * and update entry's memberUid attribute */ - - staged.name = slapi_entry_attr_get_charptr(e, "cn"); -+ if (data->associated_domain != NULL) { -+ gname = slapi_ch_smprintf("%s@%s", staged.name, data->associated_domain); -+ slapi_ch_free_string(&staged.name); -+ staged.name = gname; -+ } - staged.type = SCH_NSSWITCH_GROUP; - staged.search_members = FALSE; - staged.is_id = FALSE; -diff --git a/src/back-sch.h b/src/back-sch.h -index 72ba641..c15d1ed 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -38,6 +38,7 @@ struct backend_set_data { - bool_t check_access; - enum sch_search_nsswitch_t check_nsswitch; - unsigned long nsswitch_min_id; -+ char *associated_domain; - }; - - struct backend_entry_data { --- -2.13.6 - diff --git a/SOURCES/slapi-0004-Declare-int-backend_init_extop-for-reuse-in-plug-sch.patch b/SOURCES/slapi-0004-Declare-int-backend_init_extop-for-reuse-in-plug-sch.patch deleted file mode 100644 index 83f9592..0000000 --- a/SOURCES/slapi-0004-Declare-int-backend_init_extop-for-reuse-in-plug-sch.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 84c0767f794ca339275f9ec2d4936903d0ac3a42 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 20 Jun 2016 21:45:37 +0300 -Subject: [PATCH 4/4] Declare int backend_init_extop for reuse in plug-sch.c - ---- - src/back-sch.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/back-sch.h b/src/back-sch.h -index c15d1ed..1258ae0 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -164,6 +164,7 @@ bool_t backend_retrieve_from_nsswitch(struct backend_staged_search *staged, - struct backend_search_cbdata *cbdata); - - int backend_sch_do_pam_auth(Slapi_PBlock *pb, const char *username); -+int backend_init_extop(Slapi_PBlock *pb, struct plugin_state *state); - - #ifdef USE_IPA_IDVIEWS - void idview_get_overrides(struct backend_search_cbdata *cbdata); --- -2.7.4 - diff --git a/SOURCES/slapi-0005-Double-free-on-ldap-entry-during-priming.patch b/SOURCES/slapi-0005-Double-free-on-ldap-entry-during-priming.patch deleted file mode 100644 index 375cfe3..0000000 --- a/SOURCES/slapi-0005-Double-free-on-ldap-entry-during-priming.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 66177cbab545374ccc0bcacdd7a8ffea1ca7be6d Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Tue, 12 Jul 2016 11:43:28 +0200 -Subject: [PATCH 05/17] Double free on ldap entry during priming - -During Schema-compat cache priming, If it exists an associated domain -the entry returned by the internal search is freed twice. - -This was introduced in order for slapi-nis to resolve IPA groups with -fully qualified suffix. To support SSSD 1.14+ change of logic to handle -a default domain suffix. ---- - src/back-sch.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index cdd2b3c..0745329 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -284,15 +284,13 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e, - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); - if (result == 0) { - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); -- slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, NULL); - for (j=0; entries[j] != NULL; j++) { - ret.associated_domain = slapi_entry_attr_get_charptr(entries[j], "associatedDomain"); -- slapi_entry_free(entries[i]); - if (ret.associated_domain != NULL) - break; - } -- slapi_ch_free((void**)entries); - } -+ slapi_free_search_results_internal(pb); - } - slapi_pblock_destroy(pb); - pb = NULL; --- -2.13.6 - diff --git a/SOURCES/slapi-0006-back-sch-do-not-clobber-target-of-the-pblock-for-idv.patch b/SOURCES/slapi-0006-back-sch-do-not-clobber-target-of-the-pblock-for-idv.patch deleted file mode 100644 index 4007ce1..0000000 --- a/SOURCES/slapi-0006-back-sch-do-not-clobber-target-of-the-pblock-for-idv.patch +++ /dev/null @@ -1,198 +0,0 @@ -From b59b9c87042cb8f4d99421e101349c5f48f91235 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 26 Jul 2016 18:11:53 +0300 -Subject: [PATCH 6/8] back-sch: do not clobber target of the pblock for idview - -When extracting idview all we care is the DN of new target. -We don't really use the rewritten target as a string anymore, -so there is no need to rewrite the string in the pblock. - -This fixes a bug when running with 389-ds 1.3.5.10+ which is more -strict about modification of the values in pblock. - -Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1360245 ---- - src/back-sch.c | 43 ++++++++++++++++++++++--------------------- - src/back-sch.h | 2 +- - 2 files changed, 23 insertions(+), 22 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 0745329..e15988f 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -1652,6 +1652,8 @@ backend_search_cb(Slapi_PBlock *pb) - struct backend_search_cbdata cbdata; - struct backend_staged_search *staged, *next; - int i, isroot, ret; -+ char *original_target = NULL; -+ char *target = NULL; - - if (wrap_get_call_level() > 0) { - return 0; -@@ -1676,7 +1678,7 @@ backend_search_cb(Slapi_PBlock *pb) - return 0; - } - -- slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &cbdata.target); -+ slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &original_target); - slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &cbdata.scope); - slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &cbdata.sizelimit); - slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &cbdata.timelimit); -@@ -1697,15 +1699,15 @@ backend_search_cb(Slapi_PBlock *pb) - /* Okay, we can search. */ - slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, - "searching from \"%s\" for \"%s\" with scope %d%s\n", -- cbdata.target, cbdata.strfilter, cbdata.scope, -+ original_target, cbdata.strfilter, cbdata.scope, - backend_sch_scope_as_string(cbdata.scope)); -- cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); -+ cbdata.target_dn = slapi_sdn_new_dn_byval(original_target); - /* Check if there's a backend handling this search. */ - if (!slapi_be_exist(cbdata.target_dn)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata.state->plugin_desc->spd_id, - "slapi_be_exists(\"%s\") = 0, " -- "ignoring search\n", cbdata.target); -+ "ignoring search\n", original_target); - slapi_sdn_free(&cbdata.target_dn); - return 0; - } -@@ -1716,22 +1718,23 @@ backend_search_cb(Slapi_PBlock *pb) - * detect the ID view use. Unless the ID view is within the set we control, don't consider the override */ - map_data_foreach_domain(cbdata.state, backend_search_find_set_dn_cb, &cbdata); - if (cbdata.answer == FALSE) { -- idview_replace_target_dn(&cbdata.target, &cbdata.idview); -+ target = slapi_ch_strdup(original_target); -+ idview_replace_target_dn(&target, &cbdata.idview); - if (cbdata.idview != NULL) { - slapi_sdn_free(&cbdata.target_dn); - /* Perform another check, now for rewritten DN */ -- cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); -+ cbdata.target_dn = slapi_sdn_new_dn_byval(target); - map_data_foreach_domain(cbdata.state, backend_search_find_set_dn_cb, &cbdata); - /* Rewritten DN might still be outside of our trees */ - if (cbdata.answer == TRUE) { - slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, - "Use of ID view '%s' is detected, searching from \"%s\" " - "for \"%s\" with scope %d%s. Filter may get overridden later.\n", -- cbdata.idview, cbdata.target, cbdata.strfilter, cbdata.scope, -+ cbdata.idview, target, cbdata.strfilter, cbdata.scope, - backend_sch_scope_as_string(cbdata.scope)); - } else { - slapi_sdn_free(&cbdata.target_dn); -- slapi_ch_free_string(&cbdata.target); -+ slapi_ch_free_string(&target); - slapi_ch_free_string(&cbdata.idview); - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata.state->plugin_desc->spd_id, -@@ -1739,6 +1742,8 @@ backend_search_cb(Slapi_PBlock *pb) - "ignoring search\n"); - return 0; - } -+ } else { -+ slapi_ch_free_string(&target); - } - } - cbdata.answer = FALSE; -@@ -1890,7 +1895,7 @@ backend_search_cb(Slapi_PBlock *pb) - } - slapi_sdn_free(&cbdata.target_dn); - if (cbdata.idview != NULL) { -- slapi_ch_free_string(&cbdata.target); -+ slapi_ch_free_string(&target); - } - slapi_ch_free_string(&cbdata.idview); - #ifdef USE_IPA_IDVIEWS -@@ -1904,7 +1909,6 @@ backend_search_cb(Slapi_PBlock *pb) - /* Locate the entry for a given DN. */ - struct backend_locate_cbdata { - struct plugin_state *state; -- char *target; - Slapi_DN *target_dn; - - struct backend_entry_data *entry_data; -@@ -1953,6 +1957,7 @@ static void - backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char **group, const char**set) - { - struct backend_locate_cbdata cbdata; -+ char *original_target = NULL; - - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); - if (cbdata.state->plugin_base == NULL) { -@@ -1960,9 +1965,9 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char ** - *data = NULL; - return; - } -- slapi_pblock_get(pb, SLAPI_TARGET_DN, &cbdata.target); -+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &original_target); - -- cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); -+ cbdata.target_dn = slapi_sdn_new_dn_byval(original_target); - cbdata.entry_data = NULL; - cbdata.entry_group = NULL; - cbdata.entry_set = NULL; -@@ -1972,12 +1977,9 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char ** - * rebuild the target's RDN to use original attribute's value */ - if (cbdata.entry_data == NULL) { - char *idview = NULL; -- char *target, *original_target; -- target = original_target = slapi_ch_strdup(cbdata.target); -+ char *target = NULL; -+ target = slapi_ch_strdup(original_target); - idview_replace_target_dn(&target, &idview); -- if (target != original_target) { -- slapi_ch_free_string(&original_target); -- } - if (idview != NULL) { - char *rdnstr; - char *val; -@@ -1992,7 +1994,6 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char ** - bval.bv_val = slapi_ch_strdup(val); - memset(&scbdata, 0, sizeof(scbdata)); - scbdata.idview = idview; -- scbdata.target = target; - scbdata.pb = pb; - scbdata.state = cbdata.state; - scbdata.target_dn = slapi_sdn_new_dn_byval(target); -@@ -2025,7 +2026,6 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char ** - * insufficient-access error. */ - struct backend_group_check_scope_cbdata { - struct plugin_state *state; -- const char *target; - Slapi_DN *target_dn; - bool_t ours; - }; -@@ -2050,14 +2050,15 @@ static bool_t - backend_check_scope_pb(Slapi_PBlock *pb) - { - struct backend_group_check_scope_cbdata cbdata; -+ char *original_target = NULL; - - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); - if (cbdata.state->plugin_base == NULL) { - /* The plugin was not actually started. */ - return FALSE; - } -- slapi_pblock_get(pb, SLAPI_TARGET_DN, &cbdata.target); -- cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target); -+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &original_target); -+ cbdata.target_dn = slapi_sdn_new_dn_byval(original_target); - cbdata.ours = FALSE; - map_data_foreach_domain(cbdata.state, backend_group_check_scope_cb, - &cbdata); -diff --git a/src/back-sch.h b/src/back-sch.h -index 1258ae0..9a9abc7 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -88,7 +88,7 @@ struct entries_to_send { - struct backend_search_cbdata { - Slapi_PBlock *pb; - struct plugin_state *state; -- char *target, *strfilter, **attrs; -+ char *strfilter, **attrs; - char *idview; - Slapi_Entry **overrides; - int scope, sizelimit, timelimit, attrsonly; --- -2.7.4 - diff --git a/SOURCES/slapi-0007-back-sch-nss-for-users-with-aliases-return-alias-as-.patch b/SOURCES/slapi-0007-back-sch-nss-for-users-with-aliases-return-alias-as-.patch deleted file mode 100644 index 77d404d..0000000 --- a/SOURCES/slapi-0007-back-sch-nss-for-users-with-aliases-return-alias-as-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From e6f9e2c9282905fa41046379e0bc5c2ac82ae3a9 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 27 Jul 2016 17:37:14 +0300 -Subject: [PATCH 7/8] back-sch-nss: for users with aliases, return alias as uid - -When SSSD resolves AD users on behalf of slapi-nis, it can accept -any user identifier, including user principal name (UPN) which -may be different than the canonical user name which SSSD returns. - -As result, the entry created by slapi-nis will be using canonical user -name but the filter for search will refer to the original (aliased) -name. The search will not match the newly created entry. - -Fix this issue by returning two values for 'uid' attribute: the -canonical one and the aliased one. This way search will match. - -Verified that SSSD with id_provider=ldap happily consumes such entries. -By LDAP schema, 'uid' attribute can have multiple values. - -Fixes https://fedorahosted.org/slapi-nis/ticket/12 ---- - src/back-sch-nss.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c -index 702590c..db63e59 100644 ---- a/src/back-sch-nss.c -+++ b/src/back-sch-nss.c -@@ -230,6 +230,7 @@ backend_build_dn(const char *attribute, const char *value, - static Slapi_Entry * - backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, - char *container_sdn, -+ char *user_name, - struct backend_search_cbdata *cbdata) - { - Slapi_Entry *entry; -@@ -272,6 +273,18 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, - "objectClass", "posixAccount"); - slapi_entry_add_string(entry, - "uid", name); -+ if (user_name != NULL) { -+ /* For non-NULL original user name check if it was -+ * an alias/UPN. If so, add it to the entry. -+ * Yes, LDAP schema allows multiple values of 'uid' -+ * attribute. -+ */ -+ if (slapi_utf8casecmp((unsigned char*) user_name, -+ (unsigned char*) name) != 0) { -+ slapi_entry_add_string(entry, "uid", user_name); -+ } -+ } -+ - slapi_entry_attr_set_uint(entry, - "uidNumber", pwd->pw_uid); - slapi_entry_attr_set_uint(entry, -@@ -510,6 +523,7 @@ repeat: - } - - entry = backend_make_user_entry_from_nsswitch_passwd(&pwd, container_sdn, -+ is_uid ? NULL : user_name, - cbdata); - entries = malloc(sizeof(entries[0]) * 2); - if (entries != NULL) { --- -2.7.4 - diff --git a/SOURCES/slapi-0011-Move-a-helper-to-build-DN-to-a-format.c.patch b/SOURCES/slapi-0011-Move-a-helper-to-build-DN-to-a-format.c.patch deleted file mode 100644 index 73c9504..0000000 --- a/SOURCES/slapi-0011-Move-a-helper-to-build-DN-to-a-format.c.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 96ff6873b024718fcbb7b011eee58aab84c3086f Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 11 Sep 2017 15:32:38 +0300 -Subject: [PATCH 11/17] Move a helper to build DN to a format.c - ---- - src/back-sch-nss.c | 45 ++------------------------------------------- - src/format.c | 41 +++++++++++++++++++++++++++++++++++++++++ - src/format.h | 2 ++ - 3 files changed, 45 insertions(+), 43 deletions(-) - -diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c -index db63e59..e4d027e 100644 ---- a/src/back-sch-nss.c -+++ b/src/back-sch-nss.c -@@ -186,47 +186,6 @@ backend_search_filter_has_cn_uid(Slapi_Filter *filter, void *arg) - return SLAPI_FILTER_SCAN_CONTINUE; - } - --static char * --backend_build_dn(const char *attribute, const char *value, -- const char *container_sdn) --{ -- Slapi_RDN *rdn; -- Slapi_DN *sdn; -- char *val, *dn = NULL; -- const char *ndn, *hexchars = "0123456789ABCDEF"; -- int i; -- -- val = malloc(strlen(value) * 3 + 1); -- if (val == NULL) { -- return NULL; -- } -- rdn = slapi_rdn_new(); -- if (rdn == NULL) { -- free(val); -- return NULL; -- } -- for (i = 0; value[i] != '\0'; i++) { -- val[i * 3] = '\\'; -- val[i * 3 + 1] = hexchars[(value[i] & 0xf0) >> 4]; -- val[i * 3 + 2] = hexchars[value[i] & 0xf]; -- } -- val[i * 3] = '\0'; -- if (slapi_rdn_add(rdn, attribute, val) == 1) { -- sdn = slapi_sdn_new_dn_byval(container_sdn); -- if (sdn != NULL) { -- sdn = slapi_sdn_add_rdn(sdn, rdn); -- ndn = slapi_sdn_get_ndn(sdn); -- if (ndn != NULL) { -- dn = slapi_ch_strdup(ndn); -- } -- slapi_sdn_free(&sdn); -- } -- } -- free(val); -- slapi_rdn_free(&rdn); -- return dn; --} -- - static Slapi_Entry * - backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, - char *container_sdn, -@@ -257,7 +216,7 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, - return NULL; - } - -- dn = backend_build_dn("uid", name, container_sdn); -+ dn = format_build_dn("uid", name, container_sdn); - if (dn == NULL) { - slapi_log_error(SLAPI_LOG_FATAL, - cbdata->state->plugin_desc->spd_id, -@@ -556,7 +515,7 @@ backend_make_group_entry_from_nsswitch_group(struct group *grp, - return NULL; - } - -- dn = backend_build_dn("cn", grp->gr_name, container_sdn); -+ dn = format_build_dn("cn", grp->gr_name, container_sdn); - if (dn == NULL) { - slapi_log_error(SLAPI_LOG_FATAL, - cbdata->state->plugin_desc->spd_id, -diff --git a/src/format.c b/src/format.c -index ee6b8f3..ae4824c 100644 ---- a/src/format.c -+++ b/src/format.c -@@ -4825,3 +4825,44 @@ format_escape_for_filter(const char *unescaped) - } - return ret; - } -+ -+char * -+format_build_dn(const char *attribute, const char *value, -+ const char *container_sdn) -+{ -+ Slapi_RDN *rdn; -+ Slapi_DN *sdn; -+ char *val, *dn = NULL; -+ const char *ndn, *hexchars = "0123456789ABCDEF"; -+ int i; -+ -+ val = malloc(strlen(value) * 3 + 1); -+ if (val == NULL) { -+ return NULL; -+ } -+ rdn = slapi_rdn_new(); -+ if (rdn == NULL) { -+ free(val); -+ return NULL; -+ } -+ for (i = 0; value[i] != '\0'; i++) { -+ val[i * 3] = '\\'; -+ val[i * 3 + 1] = hexchars[(value[i] & 0xf0) >> 4]; -+ val[i * 3 + 2] = hexchars[value[i] & 0xf]; -+ } -+ val[i * 3] = '\0'; -+ if (slapi_rdn_add(rdn, attribute, val) == 1) { -+ sdn = slapi_sdn_new_dn_byval(container_sdn); -+ if (sdn != NULL) { -+ sdn = slapi_sdn_add_rdn(sdn, rdn); -+ ndn = slapi_sdn_get_ndn(sdn); -+ if (ndn != NULL) { -+ dn = slapi_ch_strdup(ndn); -+ } -+ slapi_sdn_free(&sdn); -+ } -+ } -+ free(val); -+ slapi_rdn_free(&rdn); -+ return dn; -+} -diff --git a/src/format.h b/src/format.h -index 4cde2dc..626d4a9 100644 ---- a/src/format.h -+++ b/src/format.h -@@ -83,4 +83,6 @@ char **format_get_data_set(struct plugin_state *state, - unsigned int **data_lengths); - - char *format_escape_for_filter(const char *unescaped); -+char *format_build_dn(const char *attribute, const char *value, -+ const char *container_sdn); - #endif --- -2.13.6 - diff --git a/SOURCES/slapi-0012-Add-dummy-handler-for-a-related-add-delete-modify-to.patch b/SOURCES/slapi-0012-Add-dummy-handler-for-a-related-add-delete-modify-to.patch deleted file mode 100644 index e5f1a30..0000000 --- a/SOURCES/slapi-0012-Add-dummy-handler-for-a-related-add-delete-modify-to.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 79ddc12c93920840e9fbdf5c8ea25db1c4166af5 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 12 Sep 2017 14:52:21 +0300 -Subject: [PATCH 12/17] Add dummy handler for a related add/delete/modify to - NIS plugin - -NIS doesn't need to handle ID overrides, it has to always skip related entries ---- - src/back-nis.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/src/back-nis.c b/src/back-nis.c -index 7fb191d..244beba 100644 ---- a/src/back-nis.c -+++ b/src/back-nis.c -@@ -1014,6 +1014,34 @@ backend_check_empty(struct plugin_state *state, - } - } - -+bool_t -+backend_entry_is_add_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return FALSE; -+} -+ -+bool_t -+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e_pre, -+ Slapi_Entry *e_post) -+{ -+ return FALSE; -+} -+ -+bool_t -+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return FALSE; -+} -+ - /* Scan for the list of configured domains and maps. */ - void - backend_startup(Slapi_PBlock *pb, struct plugin_state *state) --- -2.13.6 - diff --git a/SOURCES/slapi-0013-track-changes-to-ID-overrides-and-evict-map-cache-en.patch b/SOURCES/slapi-0013-track-changes-to-ID-overrides-and-evict-map-cache-en.patch deleted file mode 100644 index 49465ec..0000000 --- a/SOURCES/slapi-0013-track-changes-to-ID-overrides-and-evict-map-cache-en.patch +++ /dev/null @@ -1,340 +0,0 @@ -From bcdcb8e762c6a8824ff1dd67f7e068ef519b3952 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 11 Sep 2017 15:33:24 +0300 -Subject: [PATCH 13/17] track changes to ID overrides and evict map cache - entries - -Plug into a processing of LDAP add/delete/modify to see if an ID override entry -was added/deleted/updated. ID overrides aren't directly used to produce -map cache entries but when AD user or group is resolved, SSSD on IPA -master amends that information with ID Override from a Default Trust -View. Since nothing else would remove AD user or group entry from the map cache -on ID override change, handle their removal here. - -Check if we have any nssswitch-generated entry in a map cache that -corresponds to this entry. Such entries would be evicted from the map -cache to allow their refresh. - -Allow backends to inspect entries related to a map set - -Entries may be related to a map set content but not used directly to -generate it. An example would be ID overrides in FreeIPA. An addition, -removal or change of an ID override in the Default Trust View should be -reflected by evicting an entry from the corresponding seti. - -Let backends to handle exact logic. NIS backend does not support -exposing AD users so it provides set of dummy callbacks that always -return FALSE (entry is not related). Schema Compat backend, on other -hand, does track ID overrides in a Default Trust View in FreeIPA. ---- - src/back-sch.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/back-shr.c | 55 ++++++++++++++---- - src/backend.h | 20 +++++++ - 3 files changed, 239 insertions(+), 12 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index e15988f..f98b0b4 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -33,6 +33,7 @@ - #ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H - #include - #include -+#include - #include - #include - #else -@@ -2099,6 +2100,181 @@ backend_write_cb(Slapi_PBlock *pb, struct plugin_state *state) - return ret; - } - -+#ifdef USE_IPA_IDVIEWS -+/* Check if ID override applies to an entry in our map cache -+ * and remove the entry in case it does. */ -+ -+static bool_t -+backend__get_original_uid_and_ndn(Slapi_Entry *e, -+ char **original_uid, -+ const char **original_anchor) -+{ -+ char **elem = NULL; -+ char *v = NULL; -+ char *ndn = NULL; -+ char *view = NULL; -+ int n_elem = 0; -+ int i = 0; -+ -+ if (e == NULL) { -+ return FALSE; -+ } -+ -+ elem = slapi_entry_attr_get_charray_ext(e, "objectClass", &n_elem); -+ if (elem == NULL) { -+ /* weird, objectClass should be existing */ -+ return FALSE; -+ } -+ -+ for (i=0; i < n_elem; i++) { -+ if (strncasecmp(elem[i], "ipaOverrideAnchor", 17) == 0) { -+ break; -+ } -+ } -+ -+ slapi_ch_array_free(elem); -+ if (i == n_elem) { -+ /* This is not an override, bail out */ -+ return FALSE; -+ } -+ -+ ndn = slapi_entry_get_ndn(e); -+ if (ndn == NULL) { -+ return FALSE; -+ } -+ -+ view = PL_strcasestr(ndn, "cn=Default Trust View,"); -+ if (view == NULL || view == ndn) { -+ return FALSE; -+ } -+ -+ /* This is an ID override, we need to search for a referenced ipaOriginalUid or cn in our maps */ -+ v = slapi_entry_attr_get_charptr(e, "ipaOriginalUid"); -+ if (v == NULL) { -+ v = slapi_entry_attr_get_charptr(e, "cn"); -+ if (v == NULL) { -+ return FALSE; -+ } -+ } -+ -+ *original_uid = v; -+ *original_anchor = ndn; -+ return TRUE; -+} -+ -+bool_t -+backend_entry_evict_if_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ struct backend_set_data *set_data; -+ struct plugin_state *state = NULL; -+ char *id = NULL; -+ char *original_uid = NULL; -+ const char *original_anchor = NULL; -+ const char *rdn_attribute[] = {NULL, "uid=%s,%s,%s", "cn=%s,%s,%s"}; -+ bool_t result = FALSE; -+ -+ set_data = shared_set_data; -+ -+ /* We only interested in NSSWITCH-capable maps */ -+ if (set_data->check_nsswitch == SCH_NSSWITCH_NONE) { -+ return FALSE; -+ } -+ -+ /* See if the entry pre modification had original UID */ -+ if (!backend__get_original_uid_and_ndn(e, -+ &original_uid, -+ &original_anchor)) { -+ return FALSE; -+ } -+ -+ id = slapi_ch_smprintf(rdn_attribute[set_data->check_nsswitch], -+ original_uid, set, group); -+ -+ if (id == NULL) { -+ slapi_ch_free_string(&original_uid); -+ return FALSE; -+ } -+ -+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); -+ result = map_data_check_entry(state, group, set, id); -+ if (result) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "evicted entry %s due to changed content of ID override %s\n", -+ id, original_anchor); -+ -+ /* An entry corresponding to our target is found, evict it */ -+ map_data_unset_entry(state, group, set, id); -+ } -+ -+ slapi_ch_free_string(&id); -+ slapi_ch_free_string(&original_uid); -+ return result; -+} -+ -+bool_t -+backend_entry_is_add_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e); -+} -+ -+ -+bool_t -+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e_pre, -+ Slapi_Entry *e_post) -+{ -+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e_pre); -+} -+ -+bool_t -+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e); -+} -+ -+#else -+ -+bool_t -+backend_entry_is_add_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return FALSE; -+} -+ -+bool_t -+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e_pre, -+ Slapi_Entry *e_post) -+{ -+ return FALSE; -+} -+ -+bool_t -+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e) -+{ -+ return FALSE; -+} -+ -+#endif -+ - static int - backend_pre_write_cb(Slapi_PBlock *pb) - { -diff --git a/src/back-shr.c b/src/back-shr.c -index 7842e05..a7ea92f 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -1856,11 +1856,21 @@ backend_shr_add_entry_cb(const char *group, const char *set, bool_t secure, - - /* If the entry doesn't match the set, skip it. */ - if (!backend_shr_entry_matches_set(set_data, cbdata->pb, cbdata->e)) { -- slapi_log_error(SLAPI_LOG_PLUGIN, -- cbdata->state->plugin_desc->spd_id, -- "entry \"%s\" does not belong in " -- "\"%s\"/\"%s\"\n", -- cbdata->ndn, group, set); -+ /* Give backend a chance to perform other operations on the add op. -+ * For example, ID override addition in FreeIPA need to be noted to -+ * evict AD user/group entries from a map cache while ID overrides -+ * themselves aren't present in any map. -+ * Note that we could do this as a part of backend_shr_entry_matches_set() -+ * but it is better to isolate this operation in a separate call. */ -+ if (!backend_entry_is_add_related(group, set, secure, -+ set_data, cbdata->pb, -+ cbdata->e)) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, -+ cbdata->state->plugin_desc->spd_id, -+ "entry \"%s\" does not belong in " -+ "\"%s\"/\"%s\"\n", -+ cbdata->ndn, group, set); -+ } - return TRUE; - } - -@@ -2010,13 +2020,24 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag, - cbdata->e_post) && - !backend_shr_entry_matches_set(set_data, cbdata->pb, - cbdata->e_pre)) { -- slapi_log_error(SLAPI_LOG_PLUGIN, -- cbdata->state->plugin_desc->spd_id, -- "\"%s\" not in \"%s\"/\"%s\", " -- "before or after modify\n", -- cbdata->ndn, -- set_data->group, -- set_data->set); -+ /* Give backend a chance to perform other operations on the modify op. -+ * For example, ID override updates in FreeIPA need to be noted to -+ * evict AD user/group entries from a map cache while ID overrides -+ * themselves aren't present in any map. -+ * Note that we could do this as a part of backend_shr_entry_matches_set() -+ * but it is better to isolate this operation in a separate call. */ -+ if (!backend_entry_is_modify_related(group, set, flag, -+ set_data, cbdata->pb, -+ cbdata->e_pre, -+ cbdata->e_post)) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, -+ cbdata->state->plugin_desc->spd_id, -+ "\"%s\" not in \"%s\"/\"%s\", " -+ "before or after modify\n", -+ cbdata->ndn, -+ set_data->group, -+ set_data->set); -+ } - return TRUE; - } - if (set_data->skip_uninteresting_updates && -@@ -2631,6 +2652,16 @@ backend_shr_delete_entry_cb(const char *group, const char *set, bool_t flag, - group, set, set_data->group, set_data->set, - cbdata->ndn); - map_data_unset_entry(cbdata->state, group, set, cbdata->ndn); -+ } else { -+ /* Give backend a chance to perform other operations on the delete op. -+ * For example, ID override removal in FreeIPA need to be noted to -+ * evict AD user/group entries from a map cache while ID overrides -+ * themselves aren't present in any map. -+ * Note that we could do this as a part of backend_shr_entry_matches_set() -+ * but it is better to isolate this operation in a separate call. */ -+ (void) backend_entry_is_delete_related(group, set, flag, -+ set_data, cbdata->pb, -+ cbdata->e); - } - return TRUE; - } -diff --git a/src/backend.h b/src/backend.h -index 4608d2d..f0a5bbb 100644 ---- a/src/backend.h -+++ b/src/backend.h -@@ -115,4 +115,24 @@ void backend_update_params(Slapi_PBlock *pb, struct plugin_state *state); - bool_t backend_shr_is_caller(struct plugin_state *state, - struct slapi_pblock *pb); - -+/* Check if an operation is performed on an entry that is related to -+ * any entry in the set. This allows to catch changes of the entries that -+ * aren't directly included in the map set but should affect the set. */ -+bool_t -+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e_pre, -+ Slapi_Entry *e_post); -+bool_t -+backend_entry_is_add_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e); -+bool_t -+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag, -+ void *shared_set_data, -+ Slapi_PBlock *pb, -+ Slapi_Entry *e); -+ - #endif --- -2.13.6 - diff --git a/SOURCES/slapi-0015-configure.ac-detect-extended-NSS-API-provided-by-SSS.patch b/SOURCES/slapi-0015-configure.ac-detect-extended-NSS-API-provided-by-SSS.patch deleted file mode 100644 index 76c6a0b..0000000 --- a/SOURCES/slapi-0015-configure.ac-detect-extended-NSS-API-provided-by-SSS.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 6c4e8869ba6121ddbc6e1eca880c39b0af3391e0 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 25 Oct 2017 11:38:55 +0300 -Subject: [PATCH 15/17] configure.ac: detect extended NSS API provided by SSSD - -SSSD exposes an extended NSS API via libsss_nss_idmap. This API allows -to query getpwnam()/getgrnam()/getgruid()/getpwuid()/getgrouplist() -information with a timeout per request. As result, an application has -possibility to cancel too long request. - -This API also allows to ignore SSSD cache or invalidate it when -requesting certain information. slapi-nis needs this functionality when -invalidating own entries as result of changes done by other LDAP clients -in the areas which slapi-nis doesn't track directly. - -For example, an update of ID override in the Default Trust View should -invalidate user or group entry for that AD object. Since retrieval of -the user/group information relies on SSSD, SSSD needs to be notified -that there is a change in ID override and evict the entry from its cache -as well. ---- - configure.ac | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/configure.ac b/configure.ac -index f82a47e..a958607 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -361,8 +361,13 @@ if test "x$use_nsswitch" != xno ; then - SSS_NSS_IDMAP_LIBS= - fi - fi -+ - AC_SUBST(SSS_NSS_IDMAP_CFLAGS) - AC_SUBST(SSS_NSS_IDMAP_LIBS) -+ AC_CHECK_LIB(sss_nss_idmap,sss_nss_getpwnam_timeout) -+ if test "x$ac_cv_lib_sss_nss_idmap_sss_nss_getpwnam_timeout" = xyes ; then -+ AC_DEFINE(USE_SSS_NSS_TIMEOUT,1,[Use extended NSS API provided by SSSD]) -+ fi - - if test "x$use_pam" != xno ; then - AC_CHECK_HEADERS(security/pam_appl.h) -@@ -384,6 +389,7 @@ if test "x$use_nsswitch" != xno ; then - fi - AC_DEFINE(USE_NSSWITCH,1,[Use nsswitch API to lookup users and groups not found in the LDAP tree]) - fi -+AM_CONDITIONAL([USE_SSS_NSS_TIMEOUT], [test "x$ac_cv_lib_sss_nss_idmap_sss_nss_getpwnam_timeout" = xyes]) - - use_idviews=true - AC_ARG_WITH(idviews, --- -2.13.6 - diff --git a/SOURCES/slapi-0016-schema-compat-add-support-for-timeout-based-NSS-quer.patch b/SOURCES/slapi-0016-schema-compat-add-support-for-timeout-based-NSS-quer.patch deleted file mode 100644 index 972b735..0000000 --- a/SOURCES/slapi-0016-schema-compat-add-support-for-timeout-based-NSS-quer.patch +++ /dev/null @@ -1,933 +0,0 @@ -From 6fbf5891e9169142fc0ea37eb8f897a645b82d6f Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 1 Nov 2017 10:29:41 +0200 -Subject: [PATCH 16/17] schema-compat: add support for timeout-based NSS - queries with libsss_nss_idmap - -In case libsss_nss_idmap provides timeout-enabled NSS API, use it. -This solves a problem of too long queries to an NSS backend with -traditional POSIX NSS API. In case SSSD takes too long to respond -to a query, corresponding 389-ds thread running schema-compat plugin -would stuck waiting that response. It can lead to an exhaustion of -389-ds threads. - -A refactored interface to NSS backends is introduced with this commit. -A backend API looks like an API an NSS plugin has to implement in glibc -but also allows to handle timeout-based requests internally. - -If backend implements timeout-enabled calls, then -backend_nss_set_timeout() function can be used to modify a per-context -state. There is no need for a caller to know whether backend supports -timeout-enabled calls because either way these calls are synchronous -and backend choice is done at compile-time. - -schema-compat plugin uses 10 seconds as its default timeout. One can -change it via 'slapi-nss-timeout' attribute in the plugin config entry. ---- - src/Makefile.am | 11 ++- - src/back-sch-nss.c | 187 +++++------------------------------- - src/back-sch-nss.h | 70 ++++++++++++++ - src/back-sch-nss_sss.c | 231 +++++++++++++++++++++++++++++++++++++++++++++ - src/back-sch-sss_idmap.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++ - src/back-sch.h | 9 +- - src/plug-sch.c | 7 ++ - 7 files changed, 588 insertions(+), 166 deletions(-) - create mode 100644 src/back-sch-nss.h - create mode 100644 src/back-sch-nss_sss.c - create mode 100644 src/back-sch-sss_idmap.c - -diff --git a/src/Makefile.am b/src/Makefile.am -index 6f4926e..cd1efc2 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -68,8 +68,17 @@ schemacompat_plugin_la_LIBADD = $(LDAP_LIBS) $(RUNTIME_LIBS) $(LIBPTHREAD) $(CON - - if USE_NSSWITCH - schemacompat_plugin_la_CFLAGS += $(SSS_NSS_IDMAP_CFLAGS) --schemacompat_plugin_la_SOURCES += back-sch-nss.c -+schemacompat_plugin_la_SOURCES += back-sch-nss.c back-sch-nss.h - schemacompat_plugin_la_LIBADD += $(SSS_NSS_IDMAP_LIBS) -+# We have two backends for nss operations: -+# (1) directly loading nss_sss.so.2 -+# (2) using timeout-enabled API from libsss_nss_idmap -+# We prefer (2) if available -+if USE_SSS_NSS_TIMEOUT -+schemacompat_plugin_la_SOURCES += back-sch-sss_idmap.c -+else -+schemacompat_plugin_la_SOURCES += back-sch-nss_sss.c -+endif - endif - - if USE_PAM -diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c -index e4d027e..e5f91b2 100644 ---- a/src/back-sch-nss.c -+++ b/src/back-sch-nss.c -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -52,6 +51,7 @@ - #include "map.h" - #include "back-sch.h" - #include "format.h" -+#include "back-sch-nss.h" - - static int - bvstrprefix(const struct berval *bval, const char *s) -@@ -294,143 +294,6 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, - return entry; - } - --/* Possible results of lookup using a nss_* function. -- * Note: don't include nss.h as its path gets overriden by NSS library */ --enum nss_status --{ -- NSS_STATUS_TRYAGAIN = -2, -- NSS_STATUS_UNAVAIL, -- NSS_STATUS_NOTFOUND, -- NSS_STATUS_SUCCESS, -- NSS_STATUS_RETURN --}; -- --struct nss_ops_ctx { -- void *dl_handle; -- -- enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*setpwent)(void); -- enum nss_status (*getpwent_r)(struct passwd *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*endpwent)(void); -- -- enum nss_status (*getgrnam_r)(const char *name, struct group *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*setgrent)(void); -- enum nss_status (*getgrent_r)(struct group *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*endgrent)(void); -- -- enum nss_status (*initgroups_dyn)(const char *user, gid_t group, -- long int *start, long int *size, -- gid_t **groups, long int limit, -- int *errnop); --}; -- --void backend_nss_init_context(struct nss_ops_ctx **nss_context) --{ -- struct nss_ops_ctx *ctx = NULL; -- -- if (nss_context == NULL) { -- return; -- } -- -- ctx = calloc(1, sizeof(struct nss_ops_ctx)); -- -- *nss_context = ctx; -- if (ctx == NULL) { -- return; -- } -- -- ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); -- if (ctx->dl_handle == NULL) { -- goto fail; -- } -- -- ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r"); -- if (ctx->getpwnam_r == NULL) { -- goto fail; -- } -- -- ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r"); -- if (ctx->getpwuid_r == NULL) { -- goto fail; -- } -- -- ctx->setpwent = dlsym(ctx->dl_handle, "_nss_sss_setpwent"); -- if (ctx->setpwent == NULL) { -- goto fail; -- } -- -- ctx->getpwent_r = dlsym(ctx->dl_handle, "_nss_sss_getpwent_r"); -- if (ctx->getpwent_r == NULL) { -- goto fail; -- } -- -- ctx->endpwent = dlsym(ctx->dl_handle, "_nss_sss_endpwent"); -- if (ctx->endpwent == NULL) { -- goto fail; -- } -- -- ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r"); -- if (ctx->getgrnam_r == NULL) { -- goto fail; -- } -- -- ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r"); -- if (ctx->getgrgid_r == NULL) { -- goto fail; -- } -- -- ctx->setgrent = dlsym(ctx->dl_handle, "_nss_sss_setgrent"); -- if (ctx->setgrent == NULL) { -- goto fail; -- } -- -- ctx->getgrent_r = dlsym(ctx->dl_handle, "_nss_sss_getgrent_r"); -- if (ctx->getgrent_r == NULL) { -- goto fail; -- } -- -- ctx->endgrent = dlsym(ctx->dl_handle, "_nss_sss_endgrent"); -- if (ctx->endgrent == NULL) { -- goto fail; -- } -- -- ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn"); -- if (ctx->initgroups_dyn == NULL) { -- goto fail; -- } -- -- return; -- --fail: -- backend_nss_free_context(nss_context); -- -- return; --} -- --void --backend_nss_free_context(struct nss_ops_ctx **nss_context) --{ -- if (nss_context == NULL) { -- return; -- } -- -- if ((*nss_context)->dl_handle != NULL) { -- dlclose((*nss_context)->dl_handle); -- } -- -- free((*nss_context)); -- *nss_context = NULL; --} -- -- - - static Slapi_Entry ** - backend_retrieve_user_entry_from_nsswitch(char *user_name, bool_t is_uid, -@@ -456,13 +319,13 @@ repeat: - } - - if (is_uid) { -- rc = ctx->getpwuid_r((uid_t) atoll(user_name), &pwd, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getpwuid(ctx, (uid_t) atoll(user_name), &pwd, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &result, &lerrno); - } else { -- rc = ctx->getpwnam_r(user_name, &pwd, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getpwnam(ctx, user_name, &pwd, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &result, &lerrno); - } - - if ((rc != NSS_STATUS_SUCCESS)) { -@@ -591,13 +454,13 @@ repeat: - } - - if (is_gid) { -- rc = ctx->getgrgid_r((gid_t) atoll(group_name), &grp, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getgrgid(ctx, (gid_t) atoll(group_name), &grp, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &result, &lerrno); - } else { -- rc = ctx->getgrnam_r(group_name, &grp, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getgrnam(ctx, group_name, &grp, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &result, &lerrno); - } - if ((rc != NSS_STATUS_SUCCESS)) { - if (lerrno == ERANGE) { -@@ -651,9 +514,9 @@ repeat: - return NULL; - } - -- rc = ctx->getgrgid_r(gid, &grp, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getgrgid(ctx, gid, &grp, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &result, &lerrno); - - if ((rc != NSS_STATUS_SUCCESS)) { - if (lerrno == ERANGE) { -@@ -689,7 +552,7 @@ backend_retrieve_group_list_from_nsswitch(char *user_name, char *container_sdn, - int i, idx; - struct nss_ops_ctx *ctx = NULL; - int lerrno = 0; -- long int ngroups = 0; -+ int ngroups = 0; - long int start = 0; - enum nss_status rc; - -@@ -702,9 +565,9 @@ repeat: - return NULL; - } - -- rc = ctx->getpwnam_r(user_name, &pwd, -- cbdata->nsswitch_buffer, -- cbdata->nsswitch_buffer_len, &lerrno); -+ rc = backend_nss_getpwnam(ctx, user_name, &pwd, -+ cbdata->nsswitch_buffer, -+ cbdata->nsswitch_buffer_len, &pwd_result, &lerrno); - - if ((rc != NSS_STATUS_SUCCESS)) { - if (lerrno == ERANGE) { -@@ -723,19 +586,15 @@ repeat: - } - - ngroups = 32; -- start = 0; - grouplist = malloc(sizeof(gid_t) * ngroups); - if (grouplist == NULL) { - return NULL; - } - -- grouplist[0] = pwd.pw_gid; -- start++; -- - do { -- rc = ctx->initgroups_dyn(user_name, pwd.pw_gid, -- &start, &ngroups, &grouplist, -- -1, &lerrno); -+ rc = backend_nss_getgrouplist(ctx, user_name, pwd.pw_gid, -+ grouplist, &ngroups, -+ &lerrno); - if ((rc != NSS_STATUS_SUCCESS)) { - tmp_list = realloc(grouplist, ngroups * sizeof(gid_t)); - if (tmp_list == NULL) { -diff --git a/src/back-sch-nss.h b/src/back-sch-nss.h -new file mode 100644 -index 0000000..54a3c07 ---- /dev/null -+++ b/src/back-sch-nss.h -@@ -0,0 +1,70 @@ -+/* -+ * Copyright 2017 Red Hat, Inc. -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This Program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this Program; if not, write to the -+ * -+ * Free Software Foundation, Inc. -+ * 59 Temple Place, Suite 330 -+ * Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifndef back_sch_nss_h -+#define back_sch_nss_h -+#include -+#include -+#include -+ -+/* Possible results of lookup using a nss_* function. -+ * Note: don't include nss.h as its path gets overriden by NSS library */ -+enum nss_status -+{ -+ NSS_STATUS_TRYAGAIN = -2, -+ NSS_STATUS_UNAVAIL, -+ NSS_STATUS_NOTFOUND, -+ NSS_STATUS_SUCCESS, -+ NSS_STATUS_RETURN -+}; -+ -+struct nss_ops_ctx; -+ -+enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno); -+ -+enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -+ uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno); -+ -+enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno); -+ -+enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -+ gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno); -+ -+enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, -+ const char *name, gid_t group, -+ gid_t *groups, int *ngroups, -+ int *lerrno); -+ -+#endif /* back_sch_nss_h */ -diff --git a/src/back-sch-nss_sss.c b/src/back-sch-nss_sss.c -new file mode 100644 -index 0000000..e3e6628 ---- /dev/null -+++ b/src/back-sch-nss_sss.c -@@ -0,0 +1,231 @@ -+/* -+ * Copyright 2013-2017 Red Hat, Inc. -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This Program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this Program; if not, write to the -+ * -+ * Free Software Foundation, Inc. -+ * 59 Temple Place, Suite 330 -+ * Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "back-sch-nss.h" -+ -+struct nss_ops_ctx { -+ void *dl_handle; -+ long int initgroups_start; -+ -+ enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getgrnam_r)(const char *name, struct group *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*initgroups_dyn)(const char *user, gid_t group, -+ long int *start, long int *size, -+ gid_t **groups, long int limit, -+ int *errnop); -+}; -+ -+void backend_nss_init_context(struct nss_ops_ctx **nss_context) -+{ -+ struct nss_ops_ctx *ctx = NULL; -+ -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ ctx = calloc(1, sizeof(struct nss_ops_ctx)); -+ -+ *nss_context = ctx; -+ if (ctx == NULL) { -+ return; -+ } -+ -+ ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); -+ if (ctx->dl_handle == NULL) { -+ goto fail; -+ } -+ -+ ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r"); -+ if (ctx->getpwnam_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r"); -+ if (ctx->getpwuid_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r"); -+ if (ctx->getgrnam_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r"); -+ if (ctx->getgrgid_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn"); -+ if (ctx->initgroups_dyn == NULL) { -+ goto fail; -+ } -+ -+ return; -+ -+fail: -+ backend_nss_free_context(nss_context); -+ -+ return; -+} -+ -+void -+backend_nss_free_context(struct nss_ops_ctx **nss_context) -+{ -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ if ((*nss_context)->dl_handle != NULL) { -+ dlclose((*nss_context)->dl_handle); -+ } -+ -+ free((*nss_context)); -+ *nss_context = NULL; -+} -+ -+ -+/* Following three functions cannot be implemented with nss_sss.so.2 -+ * As result, we simply do nothing here */ -+ -+void backend_nss_set_timeout(struct nss_ops_ctx **nss_context, -+ unsigned int timeout) { -+ /* no operation */ -+} -+ -+void backend_nss_evict_user(struct nss_ops_ctx **nss_context, -+ const char *name) { -+ /* no operation */ -+} -+ -+void backend_nss_evict_group(struct nss_ops_ctx **nss_context, -+ const char *name) { -+ /* no operation */ -+} -+ -+enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ return (enum nss_status) -+ nss_context->getpwnam_r(name, pwd, -+ buffer, buflen, -+ result, lerrno); -+} -+ -+enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -+ uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ return (enum nss_status) -+ nss_context->getpwuid_r(uid, pwd, -+ buffer, buflen, -+ result, lerrno); -+} -+ -+enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ return (enum nss_status) -+ nss_context->getgrnam_r(name, grp, -+ buffer, buflen, -+ result, lerrno); -+} -+ -+enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -+ gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ return (enum nss_status) -+ nss_context->getgrgid_r(gid, grp, -+ buffer, buflen, -+ result, lerrno); -+} -+ -+enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, -+ const char *name, gid_t group, -+ gid_t *groups, int *ngroups, -+ int *lerrno) { -+ enum nss_status ret = NSS_STATUS_UNAVAIL; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ if (nss_context->initgroups_start == 0) { -+ groups[0] = group; -+ nss_context->initgroups_start++; -+ } -+ -+ ret = nss_context->initgroups_dyn(name, group, -+ &nss_context->initgroups_start, -+ &ngroups, &groups, -+ -1, &lerrno); -+ if (ret == NSS_STATUS_SUCCESS) { -+ nss_context->initgroups_start = 0; -+ } -+ -+ return ret; -+} -+ -diff --git a/src/back-sch-sss_idmap.c b/src/back-sch-sss_idmap.c -new file mode 100644 -index 0000000..6a31267 ---- /dev/null -+++ b/src/back-sch-sss_idmap.c -@@ -0,0 +1,239 @@ -+/* -+ * Copyright 2013-2017 Red Hat, Inc. -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This Program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this Program; if not, write to the -+ * -+ * Free Software Foundation, Inc. -+ * 59 Temple Place, Suite 330 -+ * Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "back-sch-nss.h" -+ -+/* SSSD only exposes *_timeout() variants if the following symbol is defined */ -+#define IPA_389DS_PLUGIN_HELPER_CALLS -+#include -+ -+struct nss_ops_ctx { -+ unsigned int timeout; -+}; -+ -+static enum nss_status __convert_sss_nss2nss_status(int errcode) { -+ enum nss_status ret = NSS_STATUS_UNAVAIL; -+ -+ if (errcode == 0) { -+ ret = NSS_STATUS_SUCCESS; -+ } else if (errcode == ENOENT) { -+ ret = NSS_STATUS_NOTFOUND; -+ } else if(errcode == ERANGE) { -+ ret = NSS_STATUS_TRYAGAIN; -+ } else if(errcode == ETIMEDOUT) { -+ ret = NSS_STATUS_UNAVAIL; -+ } else if(errcode == ETIME) { -+ ret = NSS_STATUS_TRYAGAIN; -+ }; -+ -+ return ret; -+} -+ -+void backend_nss_init_context(struct nss_ops_ctx **nss_context) -+{ -+ struct nss_ops_ctx *ctx = NULL; -+ -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ ctx = calloc(1, sizeof(struct nss_ops_ctx)); -+ -+ *nss_context = ctx; -+} -+ -+void backend_nss_free_context(struct nss_ops_ctx **nss_context) -+{ -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ free((*nss_context)); -+ *nss_context = NULL; -+} -+ -+ -+void backend_nss_set_timeout(struct nss_ops_ctx *nss_context, -+ unsigned int timeout) { -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ nss_context->timeout = timeout; -+} -+ -+/* TODO: handle buffers and memory allocation in this function */ -+void backend_nss_evict_user(struct nss_ops_ctx *nss_context, -+ const char *name) { -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ (void) sss_nss_getpwnam_timeout(name, NULL, -+ NULL, 0, -+ NULL, -+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -+ nss_context->timeout); -+} -+ -+/* TODO: handle buffers and memory allocation in this function */ -+void backend_nss_evict_group(struct nss_ops_ctx *nss_context, -+ const char *name) { -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ (void) sss_nss_getgrnam_timeout(name, NULL, -+ NULL, 0, -+ NULL, -+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -+ nss_context->timeout); -+} -+ -+enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getpwnam_timeout(name, pwd, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ if (ret != 0 && lerrno != NULL) { -+ /* SSSD translates errno into return code */ -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); -+} -+ -+enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -+ uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getpwuid_timeout(uid, pwd, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ if (ret != 0 && lerrno != NULL) { -+ /* SSSD translates errno into return code */ -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); -+} -+ -+enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -+ const char *name, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrnam_timeout(name, grp, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ if (ret != 0 && lerrno != NULL) { -+ /* SSSD translates errno into return code */ -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); -+} -+ -+enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -+ gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrgid_timeout(gid, grp, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ if (ret != 0 && lerrno != NULL) { -+ /* SSSD translates errno into return code */ -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); -+} -+ -+enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, -+ const char *name, gid_t group, -+ gid_t *groups, int *ngroups, -+ int *lerrno) { -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrouplist_timeout(name, group, -+ groups, ngroups, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ if (ret != 0 && lerrno != NULL) { -+ /* SSSD translates errno into return code */ -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); -+} -+ -diff --git a/src/back-sch.h b/src/back-sch.h -index 9a9abc7..a400419 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -152,10 +152,17 @@ typedef struct backend_extop_handlers { - - int backend_analyze_search_filter(Slapi_Filter *filter, struct backend_search_filter_config *config); - --/* Operations against nsswitch API */ -+/* NSS backend operations implemented using either nss_sss.so.2 or libsss_nss_idmap API */ - struct nss_ops_ctx; -+ - void backend_nss_init_context(struct nss_ops_ctx **nss_context); - void backend_nss_free_context(struct nss_ops_ctx **nss_context); -+void backend_nss_set_timeout(struct nss_ops_ctx **nss_context, -+ unsigned int timeout); -+void backend_nss_evict_user(struct nss_ops_ctx **nss_context, -+ const char *name); -+void backend_nss_evict_group(struct nss_ops_ctx **nss_context, -+ const char *name); - - void backend_search_nsswitch(struct backend_set_data *set_data, - struct backend_search_cbdata *cbdata); -diff --git a/src/plug-sch.c b/src/plug-sch.c -index 00e7041..6ee4042 100644 ---- a/src/plug-sch.c -+++ b/src/plug-sch.c -@@ -104,6 +104,7 @@ plugin_startup(Slapi_PBlock *pb) - struct plugin_state *state; - Slapi_Entry *plugin_entry = NULL; - Slapi_DN *pluginsdn = NULL; -+ unsigned int nss_timeout = 10000; - - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); - slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn); -@@ -130,7 +131,13 @@ plugin_startup(Slapi_PBlock *pb) - state->use_entry_cache = backend_shr_get_vattr_boolean(state, plugin_entry, - "slapi-entry-cache", - 1); -+ nss_timeout = backend_shr_get_vattr_uint(state, plugin_entry, -+ "slapi-nss-timeout", -+ 10000); -+ - } -+ backend_nss_set_timeout(state->nss_context, nss_timeout); -+ - state->cached_entries_lock = wrap_new_rwlock(); - wrap_rwlock_wrlock(state->cached_entries_lock); - state->cached_entries = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, 0, 0); --- -2.13.6 - diff --git a/SOURCES/slapi-0017-Fix-nss_sss-callers.patch b/SOURCES/slapi-0017-Fix-nss_sss-callers.patch deleted file mode 100644 index d90305d..0000000 --- a/SOURCES/slapi-0017-Fix-nss_sss-callers.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 53f7f75ebf2a5086d63989bdf1da0d42983d6448 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Fri, 3 Nov 2017 23:49:19 +0200 -Subject: [PATCH 17/18] Fix nss_sss callers - ---- - src/back-sch-nss_sss.c | 82 +++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 57 insertions(+), 25 deletions(-) - -diff --git a/src/back-sch-nss_sss.c b/src/back-sch-nss_sss.c -index e3e6628..2b1b8b0 100644 ---- a/src/back-sch-nss_sss.c -+++ b/src/back-sch-nss_sss.c -@@ -52,6 +52,20 @@ struct nss_ops_ctx { - int *errnop); - }; - -+void backend_nss_free_context(struct nss_ops_ctx **nss_context) -+{ -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ if ((*nss_context)->dl_handle != NULL) { -+ dlclose((*nss_context)->dl_handle); -+ } -+ -+ free((*nss_context)); -+ *nss_context = NULL; -+} -+ - void backend_nss_init_context(struct nss_ops_ctx **nss_context) - { - struct nss_ops_ctx *ctx = NULL; -@@ -105,21 +119,6 @@ fail: - return; - } - --void --backend_nss_free_context(struct nss_ops_ctx **nss_context) --{ -- if (nss_context == NULL) { -- return; -- } -- -- if ((*nss_context)->dl_handle != NULL) { -- dlclose((*nss_context)->dl_handle); -- } -- -- free((*nss_context)); -- *nss_context = NULL; --} -- - - /* Following three functions cannot be implemented with nss_sss.so.2 - * As result, we simply do nothing here */ -@@ -144,15 +143,22 @@ enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, - char *buffer, size_t buflen, - struct passwd **result, - int *lerrno) { -+ enum nss_status ret; - - if (nss_context == NULL) { - return NSS_STATUS_UNAVAIL; - } - -- return (enum nss_status) -+ ret = (enum nss_status) - nss_context->getpwnam_r(name, pwd, - buffer, buflen, -- result, lerrno); -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = pwd; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -@@ -160,15 +166,22 @@ enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, - char *buffer, size_t buflen, - struct passwd **result, - int *lerrno) { -+ enum nss_status ret; - - if (nss_context == NULL) { - return NSS_STATUS_UNAVAIL; - } - -- return (enum nss_status) -+ ret = (enum nss_status) - nss_context->getpwuid_r(uid, pwd, - buffer, buflen, -- result, lerrno); -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = pwd; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -@@ -176,15 +189,22 @@ enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, - char *buffer, size_t buflen, - struct group **result, - int *lerrno) { -+ enum nss_status ret; - - if (nss_context == NULL) { - return NSS_STATUS_UNAVAIL; - } - -- return (enum nss_status) -+ ret = (enum nss_status) - nss_context->getgrnam_r(name, grp, - buffer, buflen, -- result, lerrno); -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = grp; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -@@ -193,21 +213,31 @@ enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, - struct group **result, - int *lerrno) { - -+ enum nss_status ret; -+ - if (nss_context == NULL) { - return NSS_STATUS_UNAVAIL; - } - -- return (enum nss_status) -+ ret = (enum nss_status) - nss_context->getgrgid_r(gid, grp, - buffer, buflen, -- result, lerrno); -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = grp; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, - const char *name, gid_t group, - gid_t *groups, int *ngroups, - int *lerrno) { -+ - enum nss_status ret = NSS_STATUS_UNAVAIL; -+ long int size = 0; - - if (nss_context == NULL) { - return NSS_STATUS_UNAVAIL; -@@ -220,12 +250,14 @@ enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, - - ret = nss_context->initgroups_dyn(name, group, - &nss_context->initgroups_start, -- &ngroups, &groups, -- -1, &lerrno); -+ &size, &groups, -+ -1, lerrno); - if (ret == NSS_STATUS_SUCCESS) { - nss_context->initgroups_start = 0; - } - -+ *ngroups = (int) size; -+ - return ret; - } - --- -2.13.6 - diff --git a/SOURCES/slapi-0017-back-sch-cancel-memberof-retrieval-in-case-of-a-dirs.patch b/SOURCES/slapi-0017-back-sch-cancel-memberof-retrieval-in-case-of-a-dirs.patch deleted file mode 100644 index 7c5dd7f..0000000 --- a/SOURCES/slapi-0017-back-sch-cancel-memberof-retrieval-in-case-of-a-dirs.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 46649808918c027865dfaf78869aeeaddf97f47c Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 2 Nov 2017 17:14:14 +0200 -Subject: [PATCH 17/17] back-sch: cancel memberof retrieval in case of a dirsrv - shutdown - -Do not wait for SSSD to become online if directory server is going -for shutdown. Since it is guaranteed that SSSD will not be able to -function with 389-ds offline, it makes no sense to continue a loop. ---- - src/back-sch.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index f98b0b4..1998765 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -507,7 +507,7 @@ backend_set_process_external_members(Slapi_PBlock *pb, - /* This group must exist because it exists in the original tree - * but as dirsrv was restarted, SSSD might still consider its domain offline. */ - is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata); -- if (!is_group_exists) { -+ if (!is_group_exists && !slapi_is_shutting_down()) { - slapi_log_error(SLAPI_LOG_FATAL, plugin_id, - "group \"%s\" does not exist because SSSD is offline.\n", - staged.name); --- -2.13.6 - diff --git a/SOURCES/slapi-0018-Clean-up-unused-code.patch b/SOURCES/slapi-0018-Clean-up-unused-code.patch deleted file mode 100644 index 8fab1e3..0000000 --- a/SOURCES/slapi-0018-Clean-up-unused-code.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 9f8158841cc5ee3017de8f718203707d27ae87e1 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 4 Nov 2017 07:35:22 +0200 -Subject: [PATCH 18/18] Clean up unused code - ---- - src/back-sch-idview.c | 2 +- - src/back-sch-nss.c | 4 +--- - src/back-sch.h | 1 - - 3 files changed, 2 insertions(+), 5 deletions(-) - -diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c -index 8842906..e83fb1d 100644 ---- a/src/back-sch-idview.c -+++ b/src/back-sch-idview.c -@@ -121,7 +121,7 @@ idview_process_overrides(struct backend_search_cbdata *cbdata, - "createtimestamp", "modifytimestamp", "parentid", - "entryusn", "entryid", "entrydn", "ipaoriginaluid", - "ipaanchoruuid", "nsuniqueid", "ipasshpubkey", NULL }; -- char *new_dn = NULL, *new_key = NULL, *sep = NULL, *new_val = NULL; -+ char *new_dn = NULL, *sep = NULL, *new_val = NULL; - char *override_type = NULL; - Slapi_Entry *override_entry = NULL; - Slapi_Attr *anchor = NULL, *id_attr = NULL; -diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c -index e5f91b2..df04a96 100644 ---- a/src/back-sch-nss.c -+++ b/src/back-sch-nss.c -@@ -57,7 +57,6 @@ static int - bvstrprefix(const struct berval *bval, const char *s) - { - size_t len; -- int c; - - len = strlen(s); - if (len < bval->bv_len) { -@@ -553,7 +552,6 @@ backend_retrieve_group_list_from_nsswitch(char *user_name, char *container_sdn, - struct nss_ops_ctx *ctx = NULL; - int lerrno = 0; - int ngroups = 0; -- long int start = 0; - enum nss_status rc; - - ctx = cbdata->state->nss_context; -@@ -674,7 +672,7 @@ void - backend_search_nsswitch(struct backend_set_data *set_data, - struct backend_search_cbdata *cbdata) - { -- int result, rc; -+ int result; - struct backend_search_filter_config config = - {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, NULL}; - struct backend_staged_search *staged = NULL; -diff --git a/src/back-sch.h b/src/back-sch.h -index a400419..483e288 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -137,7 +137,6 @@ struct backend_search_filter_config { - #define LDAP_EXTOP_PASSMOD_TAG_NEWPWD 0x82U - - typedef int (*IFP)(); --static int backend_passwdmod_extop(Slapi_PBlock *pb); - typedef struct backend_extop_handlers { - char *oid; - IFP extop_fct; --- -2.13.6 - diff --git a/SOURCES/slapi-0019-Synchronize-nsswitch-backend-code-with-freeIPA.patch b/SOURCES/slapi-0019-Synchronize-nsswitch-backend-code-with-freeIPA.patch deleted file mode 100644 index d7daa01..0000000 --- a/SOURCES/slapi-0019-Synchronize-nsswitch-backend-code-with-freeIPA.patch +++ /dev/null @@ -1,905 +0,0 @@ -From 1229089c4023757ae15ff1866e4d89069325d2f0 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 7 Dec 2017 12:33:24 +0200 -Subject: [PATCH] Synchronize nsswitch backend code with freeIPA - -FreeIPA ipa-extdom-extop plugin uses the same logic as slapi-nis -schema-compat plugin to handle requests to SSSD. Thus, we keep the -code synchronized across both code bases. Since both plugins are loaded -into the same address space we currently rename functions to allow them -to co-exist. In future we'd move some of common code to a shared -library. ---- - src/back-sch-nss_sss.c | 365 ++++++++++++++++++++++++----------------------- - src/back-sch-sss_idmap.c | 335 +++++++++++++++++++++++-------------------- - src/back-sch.h | 8 +- - src/plug-sch.c | 32 +++-- - 4 files changed, 390 insertions(+), 350 deletions(-) - -diff --git a/src/back-sch-nss_sss.c b/src/back-sch-nss_sss.c -index 2b1b8b0..5ee911e 100644 ---- a/src/back-sch-nss_sss.c -+++ b/src/back-sch-nss_sss.c -@@ -32,232 +32,245 @@ - #include - #include - #include -+#include - #include "back-sch-nss.h" - - struct nss_ops_ctx { -- void *dl_handle; -- long int initgroups_start; -- -- enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*getgrnam_r)(const char *name, struct group *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, -- char *buffer, size_t buflen, int *errnop); -- enum nss_status (*initgroups_dyn)(const char *user, gid_t group, -- long int *start, long int *size, -- gid_t **groups, long int limit, -- int *errnop); -+ void *dl_handle; -+ long int initgroups_start; -+ -+ enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getgrnam_r)(const char *name, struct group *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, -+ char *buffer, size_t buflen, int *errnop); -+ enum nss_status (*initgroups_dyn)(const char *user, gid_t group, -+ long int *start, long int *size, -+ gid_t **groups, long int limit, -+ int *errnop); - }; - - void backend_nss_free_context(struct nss_ops_ctx **nss_context) - { -- if (nss_context == NULL) { -- return; -- } -+ if ((nss_context == NULL) || (*nss_context == NULL)) { -+ return; -+ } - -- if ((*nss_context)->dl_handle != NULL) { -- dlclose((*nss_context)->dl_handle); -- } -+ if ((*nss_context)->dl_handle != NULL) { -+ dlclose((*nss_context)->dl_handle); -+ } - -- free((*nss_context)); -- *nss_context = NULL; -+ free((*nss_context)); -+ *nss_context = NULL; - } - --void backend_nss_init_context(struct nss_ops_ctx **nss_context) -+int backend_nss_init_context(struct nss_ops_ctx **nss_context) - { -- struct nss_ops_ctx *ctx = NULL; -- -- if (nss_context == NULL) { -- return; -- } -- -- ctx = calloc(1, sizeof(struct nss_ops_ctx)); -- -- *nss_context = ctx; -- if (ctx == NULL) { -- return; -- } -- -- ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); -- if (ctx->dl_handle == NULL) { -- goto fail; -- } -- -- ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r"); -- if (ctx->getpwnam_r == NULL) { -- goto fail; -- } -- -- ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r"); -- if (ctx->getpwuid_r == NULL) { -- goto fail; -- } -- -- ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r"); -- if (ctx->getgrnam_r == NULL) { -- goto fail; -- } -- -- ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r"); -- if (ctx->getgrgid_r == NULL) { -- goto fail; -- } -- -- ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn"); -- if (ctx->initgroups_dyn == NULL) { -- goto fail; -- } -- -- return; -+ struct nss_ops_ctx *ctx = NULL; -+ -+ if (nss_context == NULL) { -+ return EINVAL; -+ } -+ -+ ctx = calloc(1, sizeof(struct nss_ops_ctx)); -+ if (ctx == NULL) { -+ return ENOMEM; -+ } -+ *nss_context = ctx; -+ -+ ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); -+ if (ctx->dl_handle == NULL) { -+ goto fail; -+ } -+ -+ ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r"); -+ if (ctx->getpwnam_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r"); -+ if (ctx->getpwuid_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r"); -+ if (ctx->getgrnam_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r"); -+ if (ctx->getgrgid_r == NULL) { -+ goto fail; -+ } -+ -+ ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn"); -+ if (ctx->initgroups_dyn == NULL) { -+ goto fail; -+ } -+ -+ return 0; - - fail: -- backend_nss_free_context(nss_context); -+ backend_nss_free_context(nss_context); - -- return; -+ return EINVAL; - } - - - /* Following three functions cannot be implemented with nss_sss.so.2 - * As result, we simply do nothing here */ - --void backend_nss_set_timeout(struct nss_ops_ctx **nss_context, -- unsigned int timeout) { -- /* no operation */ -+void backend_nss_set_timeout(struct nss_ops_ctx *nss_context, -+ unsigned int timeout) { -+ /* no operation */ - } - --void backend_nss_evict_user(struct nss_ops_ctx **nss_context, -- const char *name) { -- /* no operation */ -+void backend_nss_evict_user(struct nss_ops_ctx *nss_context, -+ const char *name) { -+ /* no operation */ - } - --void backend_nss_evict_group(struct nss_ops_ctx **nss_context, -- const char *name) { -- /* no operation */ -+void backend_nss_evict_group(struct nss_ops_ctx *nss_context, -+ const char *name) { -+ /* no operation */ - } - - enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, -- const char *name, struct passwd *pwd, -- char *buffer, size_t buflen, -- struct passwd **result, -- int *lerrno) { -- enum nss_status ret; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = (enum nss_status) -- nss_context->getpwnam_r(name, pwd, -- buffer, buflen, -- lerrno); -- -- if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -- *result = pwd; -- } -- -- return ret; -+ const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ enum nss_status ret; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = nss_context->getpwnam_r(name, pwd, -+ buffer, buflen, -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = pwd; -+ *lerrno = 0; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -- uid_t uid, struct passwd *pwd, -- char *buffer, size_t buflen, -- struct passwd **result, -- int *lerrno) { -- enum nss_status ret; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = (enum nss_status) -- nss_context->getpwuid_r(uid, pwd, -- buffer, buflen, -- lerrno); -- -- if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -- *result = pwd; -- } -- -- return ret; -+ uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ enum nss_status ret; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = nss_context->getpwuid_r(uid, pwd, -+ buffer, buflen, -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = pwd; -+ *lerrno = 0; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -- const char *name, struct group *grp, -- char *buffer, size_t buflen, -- struct group **result, -- int *lerrno) { -- enum nss_status ret; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = (enum nss_status) -- nss_context->getgrnam_r(name, grp, -- buffer, buflen, -- lerrno); -- -- if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -- *result = grp; -- } -- -- return ret; -+ const char *name, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ enum nss_status ret; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = nss_context->getgrnam_r(name, grp, -+ buffer, buflen, -+ lerrno); -+ -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = grp; -+ *lerrno = 0; -+ } -+ -+ return ret; - } - - enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -- gid_t gid, struct group *grp, -- char *buffer, size_t buflen, -- struct group **result, -- int *lerrno) { -+ gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { - -- enum nss_status ret; -+ enum nss_status ret; - -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } - -- ret = (enum nss_status) -- nss_context->getgrgid_r(gid, grp, -- buffer, buflen, -- lerrno); -+ ret = nss_context->getgrgid_r(gid, grp, -+ buffer, buflen, -+ lerrno); - -- if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -- *result = grp; -- } -+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) { -+ *result = grp; -+ *lerrno = 0; -+ } - -- return ret; -+ return ret; - } - - enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, -- const char *name, gid_t group, -- gid_t *groups, int *ngroups, -- int *lerrno) { -+ const char *name, gid_t group, -+ gid_t *groups, int *ngroups, -+ int *lerrno) { -+ -+ enum nss_status ret = NSS_STATUS_UNAVAIL; -+ long int tsize = MAX (1, *ngroups); -+ gid_t *newgroups = NULL; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ newgroups = (gid_t *) calloc (tsize, sizeof (gid_t)); -+ if (newgroups == NULL) { -+ *lerrno = ENOMEM; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ newgroups[0] = group; -+ nss_context->initgroups_start = 1; - -- enum nss_status ret = NSS_STATUS_UNAVAIL; -- long int size = 0; -+ ret = nss_context->initgroups_dyn(name, group, -+ &nss_context->initgroups_start, -+ &tsize, &newgroups, -+ -1, lerrno); - -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -+ (void) memcpy(groups, newgroups, -+ MIN(*ngroups, nss_context->initgroups_start) * sizeof(gid_t)); -+ free(newgroups); - -- if (nss_context->initgroups_start == 0) { -- groups[0] = group; -- nss_context->initgroups_start++; -- } -+ if (*ngroups < nss_context->initgroups_start) { -+ ret = NSS_STATUS_TRYAGAIN; -+ *lerrno = ERANGE; -+ } - -- ret = nss_context->initgroups_dyn(name, group, -- &nss_context->initgroups_start, -- &size, &groups, -- -1, lerrno); -- if (ret == NSS_STATUS_SUCCESS) { -- nss_context->initgroups_start = 0; -- } -+ *ngroups = (int) nss_context->initgroups_start; - -- *ngroups = (int) size; -+ nss_context->initgroups_start = 0; - -- return ret; -+ return ret; - } - -diff --git a/src/back-sch-sss_idmap.c b/src/back-sch-sss_idmap.c -index 6a31267..452ff4f 100644 ---- a/src/back-sch-sss_idmap.c -+++ b/src/back-sch-sss_idmap.c -@@ -38,202 +38,223 @@ - #include - - struct nss_ops_ctx { -- unsigned int timeout; -+ unsigned int timeout; - }; - - static enum nss_status __convert_sss_nss2nss_status(int errcode) { -- enum nss_status ret = NSS_STATUS_UNAVAIL; -- -- if (errcode == 0) { -- ret = NSS_STATUS_SUCCESS; -- } else if (errcode == ENOENT) { -- ret = NSS_STATUS_NOTFOUND; -- } else if(errcode == ERANGE) { -- ret = NSS_STATUS_TRYAGAIN; -- } else if(errcode == ETIMEDOUT) { -- ret = NSS_STATUS_UNAVAIL; -- } else if(errcode == ETIME) { -- ret = NSS_STATUS_TRYAGAIN; -- }; -- -- return ret; -+ switch(errcode) { -+ case 0: -+ return NSS_STATUS_SUCCESS; -+ case ENOENT: -+ return NSS_STATUS_NOTFOUND; -+ case ETIME: -+ /* fall-through */ -+ case ERANGE: -+ return NSS_STATUS_TRYAGAIN; -+ case ETIMEDOUT: -+ /* fall-through */ -+ default: -+ return NSS_STATUS_UNAVAIL; -+ } -+ return NSS_STATUS_UNAVAIL; - } - --void backend_nss_init_context(struct nss_ops_ctx **nss_context) -+int backend_nss_init_context(struct nss_ops_ctx **nss_context) - { -- struct nss_ops_ctx *ctx = NULL; -+ struct nss_ops_ctx *ctx = NULL; - -- if (nss_context == NULL) { -- return; -- } -+ if (nss_context == NULL) { -+ return EINVAL; -+ } - -- ctx = calloc(1, sizeof(struct nss_ops_ctx)); -+ ctx = calloc(1, sizeof(struct nss_ops_ctx)); - -- *nss_context = ctx; -+ if (ctx == NULL) { -+ return ENOMEM; -+ } -+ *nss_context = ctx; -+ return 0; - } - - void backend_nss_free_context(struct nss_ops_ctx **nss_context) - { -- if (nss_context == NULL) { -- return; -- } -+ if ((nss_context == NULL) || (*nss_context == NULL)) { -+ return; -+ } - -- free((*nss_context)); -- *nss_context = NULL; -+ free((*nss_context)); -+ *nss_context = NULL; - } - - - void backend_nss_set_timeout(struct nss_ops_ctx *nss_context, -- unsigned int timeout) { -- if (nss_context == NULL) { -- return; -- } -+ unsigned int timeout) { -+ if (nss_context == NULL) { -+ return; -+ } - -- nss_context->timeout = timeout; -+ nss_context->timeout = timeout; - } - --/* TODO: handle buffers and memory allocation in this function */ - void backend_nss_evict_user(struct nss_ops_ctx *nss_context, -- const char *name) { -- if (nss_context == NULL) { -- return; -- } -- -- (void) sss_nss_getpwnam_timeout(name, NULL, -- NULL, 0, -- NULL, -- SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -- nss_context->timeout); -+ const char *name) { -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ (void) sss_nss_getpwnam_timeout(name, NULL, -+ NULL, 0, -+ NULL, -+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -+ nss_context->timeout); - } - --/* TODO: handle buffers and memory allocation in this function */ - void backend_nss_evict_group(struct nss_ops_ctx *nss_context, -- const char *name) { -- if (nss_context == NULL) { -- return; -- } -- -- (void) sss_nss_getgrnam_timeout(name, NULL, -- NULL, 0, -- NULL, -- SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -- nss_context->timeout); -+ const char *name) { -+ if (nss_context == NULL) { -+ return; -+ } -+ -+ (void) sss_nss_getgrnam_timeout(name, NULL, -+ NULL, 0, -+ NULL, -+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE, -+ nss_context->timeout); - } - - enum nss_status backend_nss_getpwnam(struct nss_ops_ctx *nss_context, -- const char *name, struct passwd *pwd, -- char *buffer, size_t buflen, -- struct passwd **result, -- int *lerrno) { -- int ret = 0; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = sss_nss_getpwnam_timeout(name, pwd, -- buffer, buflen, -- result, -- SSS_NSS_EX_FLAG_NO_FLAGS, -- nss_context->timeout); -- -- if (ret != 0 && lerrno != NULL) { -- /* SSSD translates errno into return code */ -- *lerrno = ret; -- } -- return __convert_sss_nss2nss_status(ret); -+ const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getpwnam_timeout(name, pwd, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls -+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper -+ * but writes down errno into return code so we propagate it in case -+ * of error and translate the return code */ -+ if (lerrno != NULL) { -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); - } - - enum nss_status backend_nss_getpwuid(struct nss_ops_ctx *nss_context, -- uid_t uid, struct passwd *pwd, -- char *buffer, size_t buflen, -- struct passwd **result, -- int *lerrno) { -- -- int ret = 0; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = sss_nss_getpwuid_timeout(uid, pwd, -- buffer, buflen, -- result, -- SSS_NSS_EX_FLAG_NO_FLAGS, -- nss_context->timeout); -- if (ret != 0 && lerrno != NULL) { -- /* SSSD translates errno into return code */ -- *lerrno = ret; -- } -- return __convert_sss_nss2nss_status(ret); -+ uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, -+ struct passwd **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getpwuid_timeout(uid, pwd, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls -+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper -+ * but writes down errno into return code so we propagate it in case -+ * of error and translate the return code */ -+ if (lerrno != NULL) { -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); - } - - enum nss_status backend_nss_getgrnam(struct nss_ops_ctx *nss_context, -- const char *name, struct group *grp, -- char *buffer, size_t buflen, -- struct group **result, -- int *lerrno) { -- -- int ret = 0; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = sss_nss_getgrnam_timeout(name, grp, -- buffer, buflen, -- result, -- SSS_NSS_EX_FLAG_NO_FLAGS, -- nss_context->timeout); -- if (ret != 0 && lerrno != NULL) { -- /* SSSD translates errno into return code */ -- *lerrno = ret; -- } -- return __convert_sss_nss2nss_status(ret); -+ const char *name, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrnam_timeout(name, grp, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls -+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper -+ * but writes down errno into return code so we propagate it in case -+ * of error and translate the return code */ -+ if (lerrno != NULL) { -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); - } - - enum nss_status backend_nss_getgrgid(struct nss_ops_ctx *nss_context, -- gid_t gid, struct group *grp, -- char *buffer, size_t buflen, -- struct group **result, -- int *lerrno) { -- -- int ret = 0; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = sss_nss_getgrgid_timeout(gid, grp, -- buffer, buflen, -- result, -- SSS_NSS_EX_FLAG_NO_FLAGS, -- nss_context->timeout); -- if (ret != 0 && lerrno != NULL) { -- /* SSSD translates errno into return code */ -- *lerrno = ret; -- } -- return __convert_sss_nss2nss_status(ret); -+ gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, -+ struct group **result, -+ int *lerrno) { -+ -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrgid_timeout(gid, grp, -+ buffer, buflen, -+ result, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls -+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper -+ * but writes down errno into return code so we propagate it in case -+ * of error and translate the return code */ -+ if (lerrno != NULL) { -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); - } - - enum nss_status backend_nss_getgrouplist(struct nss_ops_ctx *nss_context, -- const char *name, gid_t group, -- gid_t *groups, int *ngroups, -- int *lerrno) { -- int ret = 0; -- -- if (nss_context == NULL) { -- return NSS_STATUS_UNAVAIL; -- } -- -- ret = sss_nss_getgrouplist_timeout(name, group, -- groups, ngroups, -- SSS_NSS_EX_FLAG_NO_FLAGS, -- nss_context->timeout); -- if (ret != 0 && lerrno != NULL) { -- /* SSSD translates errno into return code */ -- *lerrno = ret; -- } -- return __convert_sss_nss2nss_status(ret); -+ const char *name, gid_t group, -+ gid_t *groups, int *ngroups, -+ int *lerrno) { -+ int ret = 0; -+ -+ if (nss_context == NULL) { -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ret = sss_nss_getgrouplist_timeout(name, group, -+ groups, ngroups, -+ SSS_NSS_EX_FLAG_NO_FLAGS, -+ nss_context->timeout); -+ -+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls -+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper -+ * but writes down errno into return code so we propagate it in case -+ * of error and translate the return code */ -+ if (lerrno != NULL) { -+ *lerrno = ret; -+ } -+ return __convert_sss_nss2nss_status(ret); - } - -diff --git a/src/back-sch.h b/src/back-sch.h -index 483e288..2d73f34 100644 ---- a/src/back-sch.h -+++ b/src/back-sch.h -@@ -154,13 +154,13 @@ int backend_analyze_search_filter(Slapi_Filter *filter, struct backend_search_fi - /* NSS backend operations implemented using either nss_sss.so.2 or libsss_nss_idmap API */ - struct nss_ops_ctx; - --void backend_nss_init_context(struct nss_ops_ctx **nss_context); -+int backend_nss_init_context(struct nss_ops_ctx **nss_context); - void backend_nss_free_context(struct nss_ops_ctx **nss_context); --void backend_nss_set_timeout(struct nss_ops_ctx **nss_context, -+void backend_nss_set_timeout(struct nss_ops_ctx *nss_context, - unsigned int timeout); --void backend_nss_evict_user(struct nss_ops_ctx **nss_context, -+void backend_nss_evict_user(struct nss_ops_ctx *nss_context, - const char *name); --void backend_nss_evict_group(struct nss_ops_ctx **nss_context, -+void backend_nss_evict_group(struct nss_ops_ctx *nss_context, - const char *name); - - void backend_search_nsswitch(struct backend_set_data *set_data, -diff --git a/src/plug-sch.c b/src/plug-sch.c -index 6ee4042..0c20a07 100644 ---- a/src/plug-sch.c -+++ b/src/plug-sch.c -@@ -105,27 +105,33 @@ plugin_startup(Slapi_PBlock *pb) - Slapi_Entry *plugin_entry = NULL; - Slapi_DN *pluginsdn = NULL; - unsigned int nss_timeout = 10000; -+ int ret = 0; - - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); - slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn); - /* plugin base need to be duplicated because it will be destroyed - * when pblock is destroyed but we need to use it in a separate thread */ - if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) { -- slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id, -- "scheman compat plugin_startup: unable to retrieve plugin DN\n"); -- return -1; -- -- } else { -- state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn)); -- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -- "configuration entry is %s%s%s\n", -- state->plugin_base ? "\"" : "", -- state->plugin_base ? state->plugin_base : "NULL", -- state->plugin_base ? "\"" : ""); -- } -+ slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id, -+ "scheman compat plugin_startup: unable to retrieve plugin DN\n"); -+ return -1; -+ } else { -+ state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn)); -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "configuration entry is %s%s%s\n", -+ state->plugin_base ? "\"" : "", -+ state->plugin_base ? state->plugin_base : "NULL", -+ state->plugin_base ? "\"" : ""); -+ } - - state->pam_lock = wrap_new_rwlock(); -- backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context); -+ ret = backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context); -+ if (ret != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "failed to intiialize nsswitch backend: [%d]!\n", -+ ret); -+ return -1; -+ } - if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && - (plugin_entry != NULL)) { - state->use_entry_cache = backend_shr_get_vattr_boolean(state, plugin_entry, --- -2.14.3 - diff --git a/SOURCES/slapi-0020-Use-extended-SSSD-API-to-signal-that-an-entry-should.patch b/SOURCES/slapi-0020-Use-extended-SSSD-API-to-signal-that-an-entry-should.patch deleted file mode 100644 index f91c79d..0000000 --- a/SOURCES/slapi-0020-Use-extended-SSSD-API-to-signal-that-an-entry-should.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 4cd8ef26ceb3f28d103d9b8381b025d9d3f087e5 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 7 Dec 2017 12:41:15 +0200 -Subject: [PATCH] Use extended SSSD API to signal that an entry should not be - cached anymore - -When ID override is changed, we remove affected entry from the schema -compat subtrees. However, we should also signal to SSSD that ID override -did change and thus SSSD should stop caching the entry. As result, next -look up of the affected entry should cause a refresh of the data in -SSSD. - -This is important for cases when group membership changes for AD users. ---- - src/back-sch.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 1998765..4612051 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2207,6 +2207,18 @@ backend_entry_evict_if_related(const char *group, const char *set, bool_t flag, - - /* An entry corresponding to our target is found, evict it */ - map_data_unset_entry(state, group, set, id); -+ -+ /* Signal to SSSD that this entry is not cached anymore */ -+ switch(set_data->check_nsswitch) { -+ case SCH_NSSWITCH_USER: -+ backend_nss_evict_user(state->nss_context, original_uid); -+ break; -+ case SCH_NSSWITCH_GROUP: -+ backend_nss_evict_group(state->nss_context, original_uid); -+ break; -+ default: -+ break; -+ } - } - - slapi_ch_free_string(&id); --- -2.14.3 - diff --git a/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch b/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch deleted file mode 100644 index b441a46..0000000 --- a/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch +++ /dev/null @@ -1,2242 +0,0 @@ -From 8b10ea485f7964ea53fb9ab1bd71105a2da96f84 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Wed, 13 Sep 2017 12:39:08 +0200 -Subject: [PATCH 01/13] Bug 1435663: deadlock between write and search - operation in schema-compat plugin - -Problem description: - Schema compat is a betxn pre/post op plugin managing maps. - The maps are protected by a RW lock. - A typical deadlock scenario is when a read thread (SRCH) holding - the map lock needs a ressource (DB page) acquired by an - write thread (MOD/ADD/DEL..) and that write thread needs to update - the map and so acquire the map lock. - - So far we have been able to reduce the frequency of those scenarios - (but not eliminate them) by restricting the scope of operations - that need to acquire the lock. - - But scoping is not systematically possible like described in - https://bugzilla.redhat.com/show_bug.cgi?id=1435663#c16 - -Fix description: - The fix implements a plugin RW reentrant lock 'plugin_lock'. - To do this it uses a thread private variables (thread_plugin_lock_status and - thread_plugin_lock_count to remember the current status of the lock - (free, read_acquired, write_acquired). - - Then for write operations (even if it is out of the scope of SC), the lock is acquired in write - in the BE_preop operation (note not in BETXN_preop) and only released - in the BE_postop (postop/bepostop). - So a write operation acquires (exclusive) the maps lock before acquiring DB pages. - So read and write operation will acquire locks in the same order. - - Design is https://www.freeipa.org/page/V4_slapi_nis_locking - -Signed-off-by: Thierry Bordaz ---- - src/back-sch.c | 221 ++++++++++++++++++++++++++++++++++++++++ - src/back-shr.c | 94 +++++++++++++++++ - src/back-shr.h | 16 +++ - src/map.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++-- - src/map.h | 3 + - src/plug-sch.c | 52 ++++++++++ - 6 files changed, 651 insertions(+), 6 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 4612051..9313cd5 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2304,6 +2304,157 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb) - return state->use_be_txns ? backend_write_cb(pb, state) : 0; - } - -+static int -+backend_be_pre_write_cb(Slapi_PBlock *pb) { -+ int ret; -+ int lock_status; -+ int lock_count; -+ struct plugin_state *state; -+ -+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); -+ -+ if (wrap_get_call_level() > 0) { -+ return 0; -+ } -+ if (state->ready_to_serve == 0) { -+ /* No data to serve yet */ -+ return 0; -+ } -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ return 0; -+ } -+ -+ -+ wrap_inc_call_level(); -+ -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ return 0; -+ } -+ -+ if (lock_status == MAP_RWLOCK_FREE) { -+ set_plugin_monitor_count(1); -+ -+ if (plugin_wrlock() == 0) { -+ ret = 0; -+ } else { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "backend_be_pre_write_cb: unable to acquire write lock\n"); -+ ret = -1; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+#endif -+ } else { -+ set_plugin_monitor_count(lock_count + 1); -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_pre_write_cb: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", -+ lock_count + 1); -+#endif -+ ret = 0; -+ if (lock_status == MAP_RLOCK_HELD) { -+ /* lock is already acquired in read */ -+ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map backend_be_pre_write_cb: weird situation map lock is held in read and now required in write mode\n"); -+#endif -+ /* First free the lock held in read */ -+ ret = plugin_unlock(); -+ if (ret) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_pre_write_cb: fail to unlock plugin lock (%d)\n", ret); -+ } -+ -+ /* Second acquire it in write */ -+ ret = plugin_wrlock(); -+ if (ret) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_pre_write_cb: fail to write lock plugin lock (%d)\n", ret); -+ } -+ } -+ } -+ -+ set_plugin_monitor_status(MAP_WLOCK_HELD); -+ wrap_dec_call_level(); -+ -+ return ret; -+} -+ -+static int -+backend_be_post_write_cb(Slapi_PBlock *pb) -+{ -+ int ret; -+ int lock_status; -+ int lock_count; -+ struct plugin_state *state; -+ -+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); -+ -+ if (wrap_get_call_level() > 0) { -+ return 0; -+ } -+ if (state->ready_to_serve == 0) { -+ /* No data to serve yet */ -+ return 0; -+ } -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ return 0; -+ } -+ -+ wrap_inc_call_level(); -+ -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ return 0; -+ } -+ -+ if (lock_count == 1) { -+ set_plugin_monitor_status(MAP_RWLOCK_FREE); -+ if (plugin_unlock() == 0) { -+ ret = 0; -+ } else { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "backend_be_post_write_cb: unable to release write lock\n"); -+ ret = -1; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ 0); -+#endif -+ } -+ if (lock_count >= 1) { -+ set_plugin_monitor_count(lock_count - 1); -+#if DEBUG_MAP_LOCK -+ if (lock_count > 1) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) keep %s : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } else { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) is now %s : count=%d\n", -+ PR_GetCurrentThread(), -+ "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } -+#endif -+ } -+ wrap_dec_call_level(); -+ -+ return ret; -+} -+ - #ifdef USE_PAM - static int - backend_bind_cb_pam(Slapi_PBlock *pb, const char *username, char *ndn) -@@ -2814,6 +2965,42 @@ backend_init_betxn_preop(Slapi_PBlock *pb, struct plugin_state *state) - return 0; - } - -+int -+backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state) -+{ -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "hooking up bet preoperation callbacks\n"); -+ /* Intercept write requests and return an insufficient-access error for -+ * attempts to write to anything we're managing. */ -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN, -+ backend_be_pre_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn pre add callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN, -+ backend_be_pre_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn pre modify callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN, -+ backend_be_pre_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn pre modrdn callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN, -+ backend_be_pre_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn pre delete callback\n"); -+ return -1; -+ } -+ /* We don't hook abandonment requests. */ -+ /* We don't hook unbind requests. */ -+ return 0; -+} -+ - int - backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state) - { -@@ -2821,6 +3008,40 @@ backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state) - "hooking up betxn postoperation callbacks\n"); - return backend_shr_betxn_postop_init(pb, state); - } -+ -+ -+int -+backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state) -+{ -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN, -+ backend_be_post_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn post add callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN, -+ backend_be_post_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn post modify " -+ "callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN, -+ backend_be_post_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn post modrdn " -+ "callback\n"); -+ return -1; -+ } -+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN, -+ backend_be_post_write_cb) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error hooking up betxn post delete " -+ "callback\n"); -+ return -1; -+ } -+ return 0; -+} - #endif - - int -diff --git a/src/back-shr.c b/src/back-shr.c -index a7ea92f..a227b0a 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -2866,3 +2866,97 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state) - } - return 0; - } -+ -+static unsigned int thread_dummy; -+static unsigned int thread_plugin_lock_status; -+static int thread_plugin_lock_count; -+ -+void -+init_map_lock(void) -+{ -+ /* The plugin lock is initialized as free */ -+ slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock", -+ "thread_id = %p\n", PR_GetCurrentThread()); -+ -+ PR_NewThreadPrivateIndex (&thread_dummy, NULL); -+ PR_NewThreadPrivateIndex(&thread_plugin_lock_status, NULL); -+ PR_NewThreadPrivateIndex(&thread_plugin_lock_count, NULL); -+ -+ slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock", -+ "thread_plugin_lock_status = %d\n", thread_plugin_lock_status); -+ slapi_log_error(SLAPI_LOG_FATAL, "init_map_lock", -+ "thread_plugin_lock_count = %d\n", thread_plugin_lock_count); -+} -+ -+int -+rw_monitor_enabled(void) -+{ -+ if (thread_plugin_lock_status) -+ return (int) MAP_MONITOR_ENABLED; -+ else -+ return (int) MAP_MONITOR_DISABLED; -+} -+ -+int -+get_plugin_monitor_status(void) -+{ -+ int ret; -+ -+ if (thread_plugin_lock_status) -+ ret = (int) PR_GetThreadPrivate(thread_plugin_lock_status); -+ else -+ ret = (int) MAP_RWLOCK_UNINIT; -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status", -+ "lock_status = %d (%p)\n", ret, PR_GetCurrentThread()); -+#endif -+ return ret; -+} -+ -+void -+set_plugin_monitor_status(int lock_status) -+{ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status", -+ "lock_status = %d --> %d (%p)\n", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread()); -+#endif -+ -+ if (thread_plugin_lock_status) -+ PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status); -+ else -+ PR_SetThreadPrivate(thread_plugin_lock_status, (void *) MAP_RWLOCK_UNINIT); -+ -+ -+} -+ -+int -+get_plugin_monitor_count(void) -+{ -+ int ret; -+ -+ if (thread_plugin_lock_count) -+ ret = (int) PR_GetThreadPrivate(thread_plugin_lock_count); -+ else -+ ret = (int) MAP_RWLOCK_UNINIT; -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count", -+ "lock_count = %d (%p)\n", ret, PR_GetCurrentThread()); -+#endif -+ return ret; -+} -+ -+void -+set_plugin_monitor_count(int lock_count) -+{ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count", -+ "lock_count = %d --> %d (%p)\n", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread()); -+#endif -+ -+ if (thread_plugin_lock_count) -+ PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count); -+ else -+ PR_SetThreadPrivate(thread_plugin_lock_count, (void *) MAP_RWLOCK_UNINIT); -+ -+ -+} -diff --git a/src/back-shr.h b/src/back-shr.h -index 2caea5d..8c68b4f 100644 ---- a/src/back-shr.h -+++ b/src/back-shr.h -@@ -22,6 +22,22 @@ - #ifndef back_shr_h - #define back_shr_h - -+#define DEBUG_MAP_LOCK 0 -+#define MAP_MONITOR_DISABLED 0 -+#define MAP_MONITOR_ENABLED 1 -+ -+#define MAP_RWLOCK_UNINIT 3 -+#define MAP_WLOCK_HELD 2 -+#define MAP_RLOCK_HELD 1 -+#define MAP_RWLOCK_FREE 0 -+int rw_monitor_enabled(void); -+int get_plugin_monitor_status(void); -+void set_plugin_monitor_status(int lock_status); -+int get_plugin_monitor_count(void); -+void set_plugin_monitor_count(int lock_count); -+void init_map_lock(void); -+ -+ - struct plugin_state; - - void backend_shr_free_server_name(struct plugin_state *state, char *master); -diff --git a/src/map.c b/src/map.c -index ff18fcf..db9e093 100644 ---- a/src/map.c -+++ b/src/map.c -@@ -45,6 +45,7 @@ - #include "map.h" - #include "portmap.h" - #include "wrap.h" -+#include "back-shr.h" - - /* The singleton for the cache. */ - static struct { -@@ -91,6 +92,7 @@ static struct { - } *domains; - int n_domains; - struct wrapped_rwlock *lock; -+ struct wrapped_rwlock *plugin_lock; - } map_data; - - static void * -@@ -1155,6 +1157,10 @@ map_init(struct slapi_pblock *pb, struct plugin_state *state) - if (map_data.lock == NULL) { - return -1; - } -+ map_data.plugin_lock = wrap_new_rwlock(); -+ if (map_data.plugin_lock == NULL) { -+ return -1; -+ } - return 0; - } - -@@ -1193,6 +1199,8 @@ map_done(struct plugin_state *state) - } - wrap_free_rwlock(map_data.lock); - map_data.lock = NULL; -+ wrap_free_rwlock(map_data.plugin_lock); -+ map_data.plugin_lock = NULL; - } - - int -@@ -1219,19 +1227,270 @@ map_data_get_map_size(struct plugin_state *state, - } - - int --map_rdlock(void) -+plugin_rdlock(void) - { -- return wrap_rwlock_rdlock(map_data.lock); -+ return wrap_rwlock_rdlock(map_data.plugin_lock); - } - - int --map_wrlock(void) -+plugin_wrlock(void) - { -- return wrap_rwlock_wrlock(map_data.lock); -+ return wrap_rwlock_wrlock(map_data.plugin_lock); - } - - int --map_unlock(void) -+plugin_unlock(void) - { -- return wrap_rwlock_unlock(map_data.lock); -+ return wrap_rwlock_unlock(map_data.plugin_lock); - } -+ -+int -+map_rdlock(void) -+{ -+ int lock_status; -+ int lock_count; -+ int rc = 0; -+ -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: old way MAP_MONITOR_DISABLED\n"); -+ return wrap_rwlock_rdlock(map_data.lock); -+ } -+ -+ -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock", -+ "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+#endif -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: old way lock_status == MAP_RWLOCK_UNINIT\n"); -+ return wrap_rwlock_rdlock(map_data.lock); -+ } -+ -+ if (lock_status == MAP_RWLOCK_FREE) { -+ /* The plugin lock is free, acquire it */ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: current lock_status == MAP_RWLOCK_FREE\n"); -+#endif -+ set_plugin_monitor_status(MAP_RLOCK_HELD); -+ set_plugin_monitor_count(1); -+#if DEBUG_MAP_LOCK -+ if (lock_count != 0) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) ALERT !!! count was %d -> 1\n", PR_GetCurrentThread(), lock_count); -+ } -+#endif -+ -+ /* Acquire the slapi plugin in read */ -+ rc = plugin_rdlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ return rc; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+#endif -+ rc = wrap_rwlock_rdlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "Fail to acquire map lock in read (%d)\n", rc); -+ plugin_unlock(); -+ return rc; -+ } -+ return 0; -+ } -+ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", -+ lock_count, lock_count + 1); -+#endif -+ set_plugin_monitor_count(lock_count + 1); -+ return 0; -+ } -+ -+int -+map_wrlock(void) -+{ -+ int lock_status; -+ int lock_count; -+ int rc = 0; -+ -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: old way MAP_MONITOR_DISABLED\n"); -+ return wrap_rwlock_wrlock(map_data.lock); -+ } -+ -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "map wrlock", -+ "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+#endif -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: old way lock_status == MAP_LOCK_UNINIT\n"); -+ -+ return wrap_rwlock_wrlock(map_data.lock); -+ } -+ -+ if (lock_status == MAP_RWLOCK_FREE) { -+ /* The lock is free, acquire it */ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: current lock_status == MAP_LOCK_FREE\n"); -+#endif -+ -+ set_plugin_monitor_count(1); -+#if DEBUG_MAP_LOCK -+ if (lock_count != 0) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) ALERT !!! count was %d --> 1\n", PR_GetCurrentThread(), lock_count); -+ } -+#endif -+ /* Acquire the slapi plugin in write */ -+ rc = plugin_wrlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ return rc; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+#endif -+ -+ rc = wrap_rwlock_wrlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc); -+ plugin_unlock(); -+ goto common; -+ } -+ } else { -+ set_plugin_monitor_count(lock_count + 1); -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", -+ lock_count + 1); -+#endif -+ -+ if (lock_status == MAP_RLOCK_HELD) { -+ /* lock is already acquired in read */ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: weird situation map lock is held in read and now required in write mode\n"); -+#endif -+ /* First free the lock held in read */ -+ rc = plugin_unlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: fail to unlock plugin lock (%d)\n", rc); -+ goto common; -+ } -+ -+ /* Second acquire it in write */ -+ rc = plugin_wrlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: fail to write lock plugin lock (%d)\n", rc); -+ goto common; -+ } -+ } -+ } -+ -+common: -+ set_plugin_monitor_status(MAP_WLOCK_HELD); -+ return rc; -+ } -+ -+int -+map_unlock(void) -+ { -+ int lock_status; -+ int lock_count; -+ int rc = 0; -+ -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: old way MAP_MONITOR_DISABLED\n"); -+ return wrap_rwlock_unlock(map_data.lock); -+ } -+ -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "map_unlock", -+ "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+#endif -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ /* This is not initialized used the old way */ -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: old way lock_status == MAP_RWLOCK_UNINIT\n"); -+ -+ return wrap_rwlock_unlock(map_data.lock); -+ } -+ -+ if (lock_count == 1) { -+ set_plugin_monitor_status(MAP_RWLOCK_FREE); -+ rc = plugin_unlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map unlock: fail to unlock plugin lock (%d)\n", rc); -+ goto common; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ 0); -+#endif -+ rc = wrap_rwlock_unlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: fail to unlock map lock (%d)\n", rc); -+ goto common; -+ } -+ } -+ if (lock_count >= 1) { -+ set_plugin_monitor_count(lock_count - 1); -+#if DEBUG_MAP_LOCK -+ if (lock_count > 1) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) keep %s : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } else { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) is now %s : count=%d\n", -+ PR_GetCurrentThread(), -+ "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } -+#endif -+ } -+ -+common: -+ return rc; -+ } -diff --git a/src/map.h b/src/map.h -index f5b0405..4d7cb8c 100644 ---- a/src/map.h -+++ b/src/map.h -@@ -115,6 +115,9 @@ int map_data_get_domain_size(struct plugin_state *state, - const char *domain_name); - int map_data_get_map_size(struct plugin_state *state, - const char *domain_name, const char *map_name); -+int plugin_rdlock(void); -+int plugin_wrlock(void); -+int plugin_unlock(void); - int map_rdlock(void); - int map_wrlock(void); - int map_unlock(void); -diff --git a/src/plug-sch.c b/src/plug-sch.c -index 0c20a07..2d9c75b 100644 ---- a/src/plug-sch.c -+++ b/src/plug-sch.c -@@ -62,6 +62,8 @@ - #define PLUGIN_ID "schema-compat-plugin" - #define PLUGIN_PREOP_ID PLUGIN_ID "-preop" - #define PLUGIN_BETXN_PREOP_ID PLUGIN_ID "-betxn_preop" -+#define PLUGIN_BE_POSTOP_ID PLUGIN_ID "-be_postop" -+#define PLUGIN_BE_PREOP_ID PLUGIN_ID "-be_preop" - #define PLUGIN_BETXN_POSTOP_ID PLUGIN_ID "-betxn_postop" - #define PLUGIN_POSTOP_ID PLUGIN_ID "-postop" - #define PLUGIN_INTERNAL_POSTOP_ID PLUGIN_ID "-internal-postop" -@@ -258,6 +260,35 @@ schema_compat_plugin_init_betxn_postop(Slapi_PBlock *pb) - } - return 0; - } -+static int -+schema_compat_plugin_init_bepreop(Slapi_PBlock *pb) -+{ -+ slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03); -+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description); -+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state); -+ if (backend_init_be_preop(pb, global_plugin_state) == -1) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, -+ global_plugin_state->plugin_desc->spd_id, -+ "error registering be preoperation hooks\n"); -+ return -1; -+ } -+ return 0; -+} -+static int -+schema_compat_plugin_init_bepostop(Slapi_PBlock *pb) -+{ -+ slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03); -+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description); -+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state); -+ if (backend_init_be_postop(pb, global_plugin_state) == -1) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, -+ global_plugin_state->plugin_desc->spd_id, -+ "error registering be postoperation " -+ "hooks\n"); -+ return -1; -+ } -+ return 0; -+} - #endif - static int - schema_compat_plugin_init_postop(Slapi_PBlock *pb) -@@ -300,6 +331,9 @@ schema_compat_plugin_init(Slapi_PBlock *pb) - "error setting up plugin\n"); - return -1; - } -+ -+ init_map_lock(); -+ - /* Read global configuration. */ - if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, - &plugin_entry) == 0) && -@@ -341,6 +375,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb) - "error registering betxn preoperation plugin\n"); - return -1; - } -+ if (slapi_register_plugin("bepreoperation", TRUE, -+ "schema_compat_plugin_init_bepreop", -+ schema_compat_plugin_init_bepreop, -+ PLUGIN_BE_PREOP_ID, NULL, -+ state->plugin_identity) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error registering betxn preoperation plugin\n"); -+ return -1; -+ } - #endif - if (slapi_register_plugin("postoperation", TRUE, - "schema_compat_plugin_init_postop", -@@ -370,6 +413,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb) - "error registering betxn postoperation plugin\n"); - return -1; - } -+ if (slapi_register_plugin("bepostoperation", TRUE, -+ "schema_compat_plugin_init_bepostop", -+ schema_compat_plugin_init_bepostop, -+ PLUGIN_BE_POSTOP_ID, NULL, -+ state->plugin_identity) != 0) { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "error registering betxn postoperation plugin\n"); -+ return -1; -+ } - #endif - if (slapi_register_plugin("preextendedop", TRUE, - "schema_compat_plugin_init_extop", --- -2.21.0 - - -From 1ccbfe23576ac78f81d85bcce246e4d72cfc4db8 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Wed, 3 Apr 2019 10:55:38 +0200 -Subject: [PATCH 07/13] Bug 1694263: Fix thread private variable initialization - -Fix description: - The initialization of the thread private variable was buggy. - The private variable required an allocated struct (per thread). - The struct is allocated on demand (during get/set) when the - retrieved (PR_GetThreadPrivate) struct is NULL. - -Signed-off-by: Thierry Bordaz ---- - src/back-sch.c | 85 ++++++++--------- - src/back-shr.c | 138 ++++++++++++++++++++++------ - src/map.c | 244 ++++++++++++++++++++++++------------------------- - 3 files changed, 274 insertions(+), 193 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 9313cd5..2d0bad0 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2306,7 +2306,7 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb) - - static int - backend_be_pre_write_cb(Slapi_PBlock *pb) { -- int ret; -+ int ret = 0; - int lock_status; - int lock_count; - struct plugin_state *state; -@@ -2334,6 +2334,7 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) { - } - - if (lock_status == MAP_RWLOCK_FREE) { -+ /* This thread does not hold the map lock */ - set_plugin_monitor_count(1); - - if (plugin_wrlock() == 0) { -@@ -2389,12 +2390,12 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) { - static int - backend_be_post_write_cb(Slapi_PBlock *pb) - { -- int ret; -- int lock_status; -- int lock_count; -- struct plugin_state *state; -+ int ret = 0; -+ int lock_status; -+ int lock_count; -+ struct plugin_state *state; - -- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); -+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); - - if (wrap_get_call_level() > 0) { - return 0; -@@ -2409,47 +2410,47 @@ backend_be_post_write_cb(Slapi_PBlock *pb) - - wrap_inc_call_level(); - -- lock_status = get_plugin_monitor_status(); -- lock_count = get_plugin_monitor_count(); -- if (lock_status == MAP_RWLOCK_UNINIT) { -- return 0; -- } -+ lock_status = get_plugin_monitor_status(); -+ lock_count = get_plugin_monitor_count(); -+ if (lock_status == MAP_RWLOCK_UNINIT) { -+ return 0; -+ } - -- if (lock_count == 1) { -- set_plugin_monitor_status(MAP_RWLOCK_FREE); -- if (plugin_unlock() == 0) { -- ret = 0; -- } else { -- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -- "backend_be_post_write_cb: unable to release write lock\n"); -- ret = -1; -- } --#if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "backend_be_post_write_cb: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -- 0); --#endif -+ if (lock_count == 1) { -+ set_plugin_monitor_status(MAP_RWLOCK_FREE); -+ if (plugin_unlock() == 0) { -+ ret = 0; -+ } else { -+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, -+ "backend_be_post_write_cb: unable to release write lock\n"); -+ ret = -1; - } -- if (lock_count >= 1) { -- set_plugin_monitor_count(lock_count - 1); - #if DEBUG_MAP_LOCK -- if (lock_count > 1) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "backend_be_post_write_cb: (%p) keep %s : count=%d\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -- lock_count - 1); -- } else { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "backend_be_post_write_cb: (%p) is now %s : count=%d\n", -- PR_GetCurrentThread(), -- "MAP_RWLOCK_FREE", -- lock_count - 1); -- } -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ 0); - #endif -+ } -+ if (lock_count >= 1) { -+ set_plugin_monitor_count(lock_count - 1); -+#if DEBUG_MAP_LOCK -+ if (lock_count > 1) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) keep %s : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } else { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "backend_be_post_write_cb: (%p) is now %s : count=%d\n", -+ PR_GetCurrentThread(), -+ "MAP_RWLOCK_FREE", -+ lock_count - 1); - } -+#endif -+ } - wrap_dec_call_level(); - - return ret; -diff --git a/src/back-shr.c b/src/back-shr.c -index a227b0a..920c135 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -37,6 +37,7 @@ - #endif - - #include -+#include - #include "../yp/yp.h" - - #ifdef HAVE_TCPD_H -@@ -2867,31 +2868,61 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state) - return 0; - } - --static unsigned int thread_dummy; -+PRBool use_lock_status = PR_FALSE; - static unsigned int thread_plugin_lock_status; --static int thread_plugin_lock_count; -+PRBool use_lock_count = PR_FALSE; -+static unsigned int thread_plugin_lock_count; -+/* -+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_NewThreadPrivateIndex -+ * It is called each time: -+ * - PR_SetThreadPrivate is call with a not NULL private value -+ * - on thread exit -+ */ -+static void -+lock_status_free(void *ptr) -+{ -+ int *lock_status = ptr; -+ if (lock_status) { -+ slapi_ch_free((void **)&lock_status); -+ } -+} -+static void -+lock_count_free(void *ptr) -+{ -+ int *lock_count = ptr; -+ if (lock_count) { -+ slapi_ch_free((void **)&lock_count); -+ } -+} - - void - init_map_lock(void) - { -+#if DEBUG_MAP_LOCK - /* The plugin lock is initialized as free */ - slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock", - "thread_id = %p\n", PR_GetCurrentThread()); -+#endif - -- PR_NewThreadPrivateIndex (&thread_dummy, NULL); -- PR_NewThreadPrivateIndex(&thread_plugin_lock_status, NULL); -- PR_NewThreadPrivateIndex(&thread_plugin_lock_count, NULL); -+ if (PR_NewThreadPrivateIndex(&thread_plugin_lock_status, lock_status_free) == PR_SUCCESS) { -+ use_lock_status = PR_TRUE; -+ } -+ if (PR_NewThreadPrivateIndex(&thread_plugin_lock_count, lock_count_free) == PR_SUCCESS) { -+ use_lock_count = PR_TRUE; -+ } - -+#if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock", - "thread_plugin_lock_status = %d\n", thread_plugin_lock_status); - slapi_log_error(SLAPI_LOG_FATAL, "init_map_lock", - "thread_plugin_lock_count = %d\n", thread_plugin_lock_count); -+#endif - } - - int - rw_monitor_enabled(void) - { -- if (thread_plugin_lock_status) -+ if (use_lock_status) - return (int) MAP_MONITOR_ENABLED; - else - return (int) MAP_MONITOR_DISABLED; -@@ -2902,13 +2933,27 @@ get_plugin_monitor_status(void) - { - int ret; - -- if (thread_plugin_lock_status) -- ret = (int) PR_GetThreadPrivate(thread_plugin_lock_status); -- else -+ if (use_lock_status) { -+ int *lock_status_p; -+ lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status); -+ if (lock_status_p == NULL) { -+ /* if it was not initialized then allocates a structure -+ * that will be private to that thread. -+ * Later when the structure is retrieved (PR_GetThreadPrivate), the -+ * content of the structure can be read/write without allocating -+ * this private structure PR_SetThreadPrivate. -+ * So this branch is processed one time per each thread -+ */ -+ lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int)); -+ PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p); -+ *lock_status_p = MAP_RWLOCK_FREE; -+ } -+ ret = *lock_status_p; -+ } else - ret = (int) MAP_RWLOCK_UNINIT; - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status", -- "lock_status = %d (%p)\n", ret, PR_GetCurrentThread()); -+ "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, PR_GetCurrentThread()); - #endif - return ret; - } -@@ -2918,15 +2963,26 @@ set_plugin_monitor_status(int lock_status) - { - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status", -- "lock_status = %d --> %d (%p)\n", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread()); -+ "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread()); - #endif - -- if (thread_plugin_lock_status) -- PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status); -- else -- PR_SetThreadPrivate(thread_plugin_lock_status, (void *) MAP_RWLOCK_UNINIT); -- -- -+ if (use_lock_status) { -+ int *lock_status_p; -+ -+ lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status); -+ if (lock_status_p == NULL) { -+ /* if it was not initialized then allocates a structure -+ * that will be private to that thread. -+ * Later when the structure is retrieved (PR_GetThreadPrivate), the -+ * content of the structure can be read/write without allocating -+ * this private structure PR_SetThreadPrivate. -+ * So this branch is processed one time per each thread -+ */ -+ lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int)); -+ PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p); -+ } -+ *lock_status_p = lock_status; -+ } - } - - int -@@ -2934,13 +2990,27 @@ get_plugin_monitor_count(void) - { - int ret; - -- if (thread_plugin_lock_count) -- ret = (int) PR_GetThreadPrivate(thread_plugin_lock_count); -- else -+ if (use_lock_count) { -+ int *lock_count; -+ lock_count = (int *) PR_GetThreadPrivate(thread_plugin_lock_count); -+ if (lock_count == NULL) { -+ /* if it was not initialized then allocates a structure -+ * that will be private to that thread. -+ * Later when the structure is retrieved (PR_GetThreadPrivate), the -+ * content of the structure can be read/write without allocating -+ * this private structure PR_SetThreadPrivate. -+ * So this branch is processed one time per each thread -+ */ -+ lock_count = (int *) slapi_ch_calloc(1, sizeof (int)); -+ PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count); -+ *lock_count = 0; -+ } -+ ret = *lock_count; -+ } else - ret = (int) MAP_RWLOCK_UNINIT; - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count", -- "lock_count = %d (%p)\n", ret, PR_GetCurrentThread()); -+ "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, PR_GetCurrentThread()); - #endif - return ret; - } -@@ -2950,13 +3020,23 @@ set_plugin_monitor_count(int lock_count) - { - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count", -- "lock_count = %d --> %d (%p)\n", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread()); -+ "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread()); - #endif -- -- if (thread_plugin_lock_count) -- PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count); -- else -- PR_SetThreadPrivate(thread_plugin_lock_count, (void *) MAP_RWLOCK_UNINIT); -- -- -+ if (use_lock_count) { -+ int *lock_count_p; -+ -+ lock_count_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_count); -+ if (lock_count_p == NULL) { -+ /* if it was not initialized then allocates a structure -+ * that will be private to that thread. -+ * Later when the structure is retrieved (PR_GetThreadPrivate), the -+ * content of the structure can be read/write without allocating -+ * this private structure PR_SetThreadPrivate. -+ * So this branch is processed one time per each thread -+ */ -+ lock_count_p = (int *) slapi_ch_calloc(1, sizeof (int)); -+ PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count_p); -+ } -+ *lock_count_p = lock_count; -+ } - } -diff --git a/src/map.c b/src/map.c -index db9e093..e953925 100644 ---- a/src/map.c -+++ b/src/map.c -@@ -1248,7 +1248,7 @@ int - map_rdlock(void) - { - int lock_status; -- int lock_count; -+ int lock_count; - int rc = 0; - - if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -@@ -1260,7 +1260,7 @@ map_rdlock(void) - - - lock_status = get_plugin_monitor_status(); -- lock_count = get_plugin_monitor_count(); -+ lock_count = get_plugin_monitor_count(); - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock", -@@ -1271,52 +1271,52 @@ map_rdlock(void) - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", - "map rdlock: old way lock_status == MAP_RWLOCK_UNINIT\n"); - return wrap_rwlock_rdlock(map_data.lock); -- } -+ } - -- if (lock_status == MAP_RWLOCK_FREE) { -- /* The plugin lock is free, acquire it */ -+ if (lock_status == MAP_RWLOCK_FREE) { -+ /* The plugin lock is free, acquire it */ - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: current lock_status == MAP_RWLOCK_FREE\n"); -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: current lock_status == MAP_RWLOCK_FREE\n"); - #endif -- set_plugin_monitor_status(MAP_RLOCK_HELD); -- set_plugin_monitor_count(1); -+ set_plugin_monitor_status(MAP_RLOCK_HELD); -+ set_plugin_monitor_count(1); - #if DEBUG_MAP_LOCK -- if (lock_count != 0) { -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) ALERT !!! count was %d -> 1\n", PR_GetCurrentThread(), lock_count); -- } -+ if (lock_count != 0) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) ALERT !!! count was %d -> 1\n", PR_GetCurrentThread(), lock_count); -+ } - #endif - -- /* Acquire the slapi plugin in read */ -- rc = plugin_rdlock(); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -- return rc; -- } -+ /* Acquire the slapi plugin in read */ -+ rc = plugin_rdlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ return rc; -+ } - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); - #endif -- rc = wrap_rwlock_rdlock(map_data.lock); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "Fail to acquire map lock in read (%d)\n", rc); -- plugin_unlock(); -- return rc; -- } -- return 0; -- } -+ rc = wrap_rwlock_rdlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "Fail to acquire map lock in read (%d)\n", rc); -+ plugin_unlock(); -+ return rc; -+ } -+ return 0; -+ } - - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", -- lock_count, lock_count + 1); -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", -+ lock_count, lock_count + 1); - #endif -- set_plugin_monitor_count(lock_count + 1); -+ set_plugin_monitor_count(lock_count + 1); - return 0; - } - -@@ -1324,7 +1324,7 @@ int - map_wrlock(void) - { - int lock_status; -- int lock_count; -+ int lock_count; - int rc = 0; - - if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -@@ -1335,7 +1335,7 @@ map_wrlock(void) - } - - lock_status = get_plugin_monitor_status(); -- lock_count = get_plugin_monitor_count(); -+ lock_count = get_plugin_monitor_count(); - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map wrlock", -@@ -1356,65 +1356,65 @@ map_wrlock(void) - "map wrlock: current lock_status == MAP_LOCK_FREE\n"); - #endif - -- set_plugin_monitor_count(1); -+ set_plugin_monitor_count(1); - #if DEBUG_MAP_LOCK -- if (lock_count != 0) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) ALERT !!! count was %d --> 1\n", PR_GetCurrentThread(), lock_count); -- } -+ if (lock_count != 0) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) ALERT !!! count was %d --> 1\n", PR_GetCurrentThread(), lock_count); -+ } - #endif -- /* Acquire the slapi plugin in write */ -- rc = plugin_wrlock(); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -- return rc; -- } -+ /* Acquire the slapi plugin in write */ -+ rc = plugin_wrlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ return rc; -+ } - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); - #endif - -- rc = wrap_rwlock_wrlock(map_data.lock); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc); -- plugin_unlock(); -- goto common; -- } -- } else { -- set_plugin_monitor_count(lock_count + 1); -+ rc = wrap_rwlock_wrlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc); -+ plugin_unlock(); -+ goto common; -+ } -+ } else { -+ set_plugin_monitor_count(lock_count + 1); - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", -- lock_count + 1); -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", -+ lock_count + 1); - #endif - -- if (lock_status == MAP_RLOCK_HELD) { -- /* lock is already acquired in read */ -+ if (lock_status == MAP_RLOCK_HELD) { -+ /* lock is already acquired in read */ - #if DEBUG_MAP_LOCK -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: weird situation map lock is held in read and now required in write mode\n"); -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: weird situation map lock is held in read and now required in write mode\n"); - #endif -- /* First free the lock held in read */ -- rc = plugin_unlock(); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: fail to unlock plugin lock (%d)\n", rc); -- goto common; -- } -+ /* First free the lock held in read */ -+ rc = plugin_unlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: fail to unlock plugin lock (%d)\n", rc); -+ goto common; -+ } - -- /* Second acquire it in write */ -- rc = plugin_wrlock(); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: fail to write lock plugin lock (%d)\n", rc); -- goto common; -- } -+ /* Second acquire it in write */ -+ rc = plugin_wrlock(); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map wrlock: fail to write lock plugin lock (%d)\n", rc); -+ goto common; - } - } -+ } - - common: - set_plugin_monitor_status(MAP_WLOCK_HELD); -@@ -1425,7 +1425,7 @@ int - map_unlock(void) - { - int lock_status; -- int lock_count; -+ int lock_count; - int rc = 0; - - if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -@@ -1436,7 +1436,7 @@ map_unlock(void) - } - - lock_status = get_plugin_monitor_status(); -- lock_count = get_plugin_monitor_count(); -+ lock_count = get_plugin_monitor_count(); - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map_unlock", -@@ -1448,48 +1448,48 @@ map_unlock(void) - "map_unlock: old way lock_status == MAP_RWLOCK_UNINIT\n"); - - return wrap_rwlock_unlock(map_data.lock); -- } -+ } - -- if (lock_count == 1) { -- set_plugin_monitor_status(MAP_RWLOCK_FREE); -- rc = plugin_unlock(); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map unlock: fail to unlock plugin lock (%d)\n", rc); -- goto common; -- } --#if DEBUG_MAP_LOCK -+ if (lock_count == 1) { -+ set_plugin_monitor_status(MAP_RWLOCK_FREE); -+ rc = plugin_unlock(); -+ if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map_unlock: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -- 0); -+ "map unlock: fail to unlock plugin lock (%d)\n", rc); -+ goto common; -+ } -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ 0); - #endif -- rc = wrap_rwlock_unlock(map_data.lock); -- if (rc) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ rc = wrap_rwlock_unlock(map_data.lock); -+ if (rc) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "map_unlock: fail to unlock map lock (%d)\n", rc); -- goto common; -- } -+ goto common; - } -- if (lock_count >= 1) { -- set_plugin_monitor_count(lock_count - 1); -+ } -+ if (lock_count >= 1) { -+ set_plugin_monitor_count(lock_count - 1); - #if DEBUG_MAP_LOCK -- if (lock_count > 1) { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map_unlock: (%p) keep %s : count=%d\n", -- PR_GetCurrentThread(), -- (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -- lock_count - 1); -- } else { -- slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map_unlock: (%p) is now %s : count=%d\n", -- PR_GetCurrentThread(), -- "MAP_RWLOCK_FREE", -- lock_count - 1); -- } --#endif -+ if (lock_count > 1) { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) keep %s : count=%d\n", -+ PR_GetCurrentThread(), -+ (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", -+ lock_count - 1); -+ } else { -+ slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -+ "map_unlock: (%p) is now %s : count=%d\n", -+ PR_GetCurrentThread(), -+ "MAP_RWLOCK_FREE", -+ lock_count - 1); - } -+#endif -+ } - - common: - return rc; --- -2.21.0 - - -From 5e6953c1d4e776f5e084ea69a4f6e6b485362b3d Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Wed, 10 Apr 2019 15:54:16 +0200 -Subject: [PATCH 08/13] Bug 1694263: improve debug msg to match pstack threadId - -Description: - - A pstack is showing threadId that differs from the - the thread pointer. To match logs with pstack - better to display the threadId - -https://bugzilla.redhat.com/show_bug.cgi?id=1694263 -Signed-off-by: Thierry Bordaz ---- - src/back-sch.c | 10 +++++----- - src/back-shr.c | 15 +++++++++++---- - src/back-shr.h | 1 + - src/map.c | 30 +++++++++++++++--------------- - 4 files changed, 32 insertions(+), 24 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 2d0bad0..4cacb28 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2346,14 +2346,14 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) { - } - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+ "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD : count=%d\n", (void *) PR_MyThreadId(), 1); - #endif - } else { - set_plugin_monitor_count(lock_count + 1); - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "backend_be_pre_write_cb: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD", - lock_count + 1); - #endif -@@ -2428,7 +2428,7 @@ backend_be_post_write_cb(Slapi_PBlock *pb) - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "backend_be_post_write_cb: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", - 0); - #endif -@@ -2439,13 +2439,13 @@ backend_be_post_write_cb(Slapi_PBlock *pb) - if (lock_count > 1) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "backend_be_post_write_cb: (%p) keep %s : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", - lock_count - 1); - } else { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "backend_be_post_write_cb: (%p) is now %s : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - "MAP_RWLOCK_FREE", - lock_count - 1); - } -diff --git a/src/back-shr.c b/src/back-shr.c -index 920c135..2bfdf52 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -2868,6 +2868,13 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state) - return 0; - } - -+static int -+PR_MyThreadId(void) -+{ -+ PRThread *thr = PR_GetCurrentThread(); -+ PRUint32 myself = PR_GetThreadID(thr); -+ return myself; -+} - PRBool use_lock_status = PR_FALSE; - static unsigned int thread_plugin_lock_status; - PRBool use_lock_count = PR_FALSE; -@@ -2953,7 +2960,7 @@ get_plugin_monitor_status(void) - ret = (int) MAP_RWLOCK_UNINIT; - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status", -- "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, PR_GetCurrentThread()); -+ "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId()); - #endif - return ret; - } -@@ -2963,7 +2970,7 @@ set_plugin_monitor_status(int lock_status) - { - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status", -- "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread()); -+ "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, (void *) PR_MyThreadId()); - #endif - - if (use_lock_status) { -@@ -3010,7 +3017,7 @@ get_plugin_monitor_count(void) - ret = (int) MAP_RWLOCK_UNINIT; - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count", -- "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, PR_GetCurrentThread()); -+ "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId()); - #endif - return ret; - } -@@ -3020,7 +3027,7 @@ set_plugin_monitor_count(int lock_count) - { - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count", -- "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread()); -+ "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, (void *) PR_MyThreadId()); - #endif - if (use_lock_count) { - int *lock_count_p; -diff --git a/src/back-shr.h b/src/back-shr.h -index 8c68b4f..5d72ad9 100644 ---- a/src/back-shr.h -+++ b/src/back-shr.h -@@ -30,6 +30,7 @@ - #define MAP_WLOCK_HELD 2 - #define MAP_RLOCK_HELD 1 - #define MAP_RWLOCK_FREE 0 -+static int PR_MyThreadId(void); - int rw_monitor_enabled(void); - int get_plugin_monitor_status(void); - void set_plugin_monitor_status(int lock_status); -diff --git a/src/map.c b/src/map.c -index e953925..f80f465 100644 ---- a/src/map.c -+++ b/src/map.c -@@ -1264,7 +1264,7 @@ map_rdlock(void) - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock", -- "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+ "thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level()); - #endif - if (lock_status == MAP_RWLOCK_UNINIT) { - /* This is not initialized used the old way */ -@@ -1284,7 +1284,7 @@ map_rdlock(void) - #if DEBUG_MAP_LOCK - if (lock_count != 0) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) ALERT !!! count was %d -> 1\n", PR_GetCurrentThread(), lock_count); -+ "map rdlock: (%p) ALERT !!! count was %d -> 1\n", (void *) PR_MyThreadId(), lock_count); - } - #endif - -@@ -1292,12 +1292,12 @@ map_rdlock(void) - rc = plugin_rdlock(); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc); - return rc; - } - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+ "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", (void *) PR_MyThreadId(), 1); - #endif - rc = wrap_rwlock_rdlock(map_data.lock); - if (rc) { -@@ -1312,7 +1312,7 @@ map_rdlock(void) - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", - "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", - lock_count, lock_count + 1); - #endif -@@ -1339,7 +1339,7 @@ map_wrlock(void) - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map wrlock", -- "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+ "thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level()); - #endif - if (lock_status == MAP_RWLOCK_UNINIT) { - /* This is not initialized used the old way */ -@@ -1360,25 +1360,25 @@ map_wrlock(void) - #if DEBUG_MAP_LOCK - if (lock_count != 0) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) ALERT !!! count was %d --> 1\n", PR_GetCurrentThread(), lock_count); -+ "map wrlock: (%p) ALERT !!! count was %d --> 1\n", (void *) PR_MyThreadId(), lock_count); - } - #endif - /* Acquire the slapi plugin in write */ - rc = plugin_wrlock(); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc); -+ "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc); - return rc; - } - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", PR_GetCurrentThread(), 1); -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", (void *) PR_MyThreadId(), 1); - #endif - - rc = wrap_rwlock_wrlock(map_data.lock); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc); -+ "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", (void *) PR_MyThreadId(), rc); - plugin_unlock(); - goto common; - } -@@ -1387,7 +1387,7 @@ map_wrlock(void) - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "map wrlock: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", - lock_count + 1); - #endif -@@ -1440,7 +1440,7 @@ map_unlock(void) - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map_unlock", -- "thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level()); -+ "thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level()); - #endif - if (lock_status == MAP_RWLOCK_UNINIT) { - /* This is not initialized used the old way */ -@@ -1461,7 +1461,7 @@ map_unlock(void) - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "map_unlock: (%p) %s --> MAP_RWLOCK_FREE : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", - 0); - #endif -@@ -1478,13 +1478,13 @@ map_unlock(void) - if (lock_count > 1) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "map_unlock: (%p) keep %s : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE", - lock_count - 1); - } else { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", - "map_unlock: (%p) is now %s : count=%d\n", -- PR_GetCurrentThread(), -+ (void *) PR_MyThreadId(), - "MAP_RWLOCK_FREE", - lock_count - 1); - } --- -2.21.0 - - -From 52fd1595699ea9859c2f4c41ae7ff425d65ae3cf Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Wed, 10 Apr 2019 18:40:02 +0200 -Subject: [PATCH 09/13] Bug 1694263: On some 'cn=config' updates bepost_op are - not called that leads to lock leak - -Description: - The true cause of the hang was that some updates on 'cn=config' - can skip the BEPOST phase. (in this bug it was the maxbersize setting). - The consequence is that the slapi-nis map lock was acquired but not released. - The fix consist to ignore (not lock slapi-nis map) write operation done - on 'cn=config' and 'cn=schema' - -https://bugzilla.redhat.com/show_bug.cgi?id=1694263 -Signed-off-by: Thierry Bordaz ---- - src/back-sch.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- - src/back-shr.c | 22 ++++++++++++++++++++-- - src/back-shr.h | 3 ++- - src/plug-sch.c | 7 +++++++ - 4 files changed, 74 insertions(+), 6 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 4cacb28..9201c2e 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -2303,6 +2303,33 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb) - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); - return state->use_be_txns ? backend_write_cb(pb, state) : 0; - } -+static PRBool -+backend_be_write_ignore(Slapi_PBlock *pb) -+{ -+ char *dn = NULL; -+ Slapi_DN *target_sdn = NULL; -+ int check; -+ int i = 0; -+ PRBool ignore = PR_FALSE; -+ -+ /* Check if the target DN is a subordinates of -+ * on of the ignored containers -+ */ -+ slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn); -+ target_sdn = slapi_sdn_new_dn_byval(dn); -+ -+ for (i = 0; ignored_containers_sdn[i]; i++) { -+ check = slapi_sdn_issuffix(target_sdn, ignored_containers_sdn[i]); -+ if (check != 0) { -+ /* This entry is an ignored container */ -+ ignore = PR_TRUE; -+ break; -+ } -+ } -+ slapi_sdn_free(&target_sdn); -+ return ignore; -+} -+ - - static int - backend_be_pre_write_cb(Slapi_PBlock *pb) { -@@ -2323,6 +2350,14 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) { - if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { - return 0; - } -+ if (backend_be_write_ignore(pb)) { -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "backend_be_pre_write_cb: (%p) operation is not impacting schema compat\n", PR_MyThreadId(), 1); -+#endif -+ return 0; -+ } -+ - - - wrap_inc_call_level(); -@@ -2404,9 +2439,16 @@ backend_be_post_write_cb(Slapi_PBlock *pb) - /* No data to serve yet */ - return 0; - } -- if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -- return 0; -- } -+ if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) { -+ return 0; -+ } -+ if (backend_be_write_ignore(pb)) { -+#if DEBUG_MAP_LOCK -+ slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -+ "backend_be_post_write_cb: (%p) operation was not impacting schema compat\n", PR_MyThreadId(), 1); -+#endif -+ return 0; -+ } - - wrap_inc_call_level(); - -diff --git a/src/back-shr.c b/src/back-shr.c -index 2bfdf52..b348869 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -2868,7 +2868,7 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state) - return 0; - } - --static int -+int - PR_MyThreadId(void) - { - PRThread *thr = PR_GetCurrentThread(); -@@ -2902,14 +2902,32 @@ lock_count_free(void *ptr) - } - } - -+/* This is used to ignore some write operations -+ * if they target subordinates entry of ignored containers -+ */ -+Slapi_DN **ignored_containers_sdn = NULL; - void - init_map_lock(void) - { - #if DEBUG_MAP_LOCK - /* The plugin lock is initialized as free */ - slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock", -- "thread_id = %p\n", PR_GetCurrentThread()); -+ "thread_id = %p\n", PR_MyThreadId()); - #endif -+ if (ignored_containers_sdn == NULL) { -+ /* allocates ignored_containers_sdn of Slapi_DN* only once -+ * It will be used later in be_pre/post_write_cb -+ */ -+ int cnt; -+ char *ignored_containers[3] = { "cn=config", "cn=schema", NULL}; -+ -+ for (cnt = 0; ignored_containers[cnt]; cnt++); -+ ignored_containers_sdn = (Slapi_DN **) slapi_ch_calloc(cnt + 1, sizeof(Slapi_DN *)); -+ -+ for (cnt = 0; ignored_containers[cnt]; cnt++) { -+ ignored_containers_sdn[cnt] = slapi_sdn_new_dn_byval(ignored_containers[cnt]); -+ } -+ } - - if (PR_NewThreadPrivateIndex(&thread_plugin_lock_status, lock_status_free) == PR_SUCCESS) { - use_lock_status = PR_TRUE; -diff --git a/src/back-shr.h b/src/back-shr.h -index 5d72ad9..d01b999 100644 ---- a/src/back-shr.h -+++ b/src/back-shr.h -@@ -30,13 +30,14 @@ - #define MAP_WLOCK_HELD 2 - #define MAP_RLOCK_HELD 1 - #define MAP_RWLOCK_FREE 0 --static int PR_MyThreadId(void); -+int PR_MyThreadId(void); - int rw_monitor_enabled(void); - int get_plugin_monitor_status(void); - void set_plugin_monitor_status(int lock_status); - int get_plugin_monitor_count(void); - void set_plugin_monitor_count(int lock_count); - void init_map_lock(void); -+Slapi_DN **ignored_containers_sdn; - - - struct plugin_state; -diff --git a/src/plug-sch.c b/src/plug-sch.c -index 2d9c75b..913abe2 100644 ---- a/src/plug-sch.c -+++ b/src/plug-sch.c -@@ -197,6 +197,13 @@ plugin_shutdown(Slapi_PBlock *pb) - if (state->plugin_base != NULL) { - slapi_ch_free((void **)&state->plugin_base); - } -+ if (ignored_containers_sdn) { -+ int i; -+ for (i = 0; ignored_containers_sdn[i]; i++) { -+ slapi_sdn_free(&ignored_containers_sdn[i]); -+ } -+ slapi_ch_free((void **)&ignored_containers_sdn); -+ } - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "plugin shutdown completed\n"); - return 0; --- -2.21.0 - - -From c44f9ca81afa6cbf817159d37b0695d6462866eb Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 23 Apr 2019 09:39:08 +0300 -Subject: [PATCH 10/13] Cast callbacks passed to xdrrec_create to a right type - -With newer compilers there are stricter checks on callback type -validation. As result, we need to cast the callback signatures even -though it makes no practical difference in our test case. ---- - tests/clients/yp.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/tests/clients/yp.c b/tests/clients/yp.c -index 200d591..bc2da1f 100644 ---- a/tests/clients/yp.c -+++ b/tests/clients/yp.c -@@ -34,6 +34,8 @@ - #include - #include "../../yp/yp.h" - -+typedef int (*xdrrec_proc_t)(void *, void *, int); -+ - static struct sockaddr_in server; - static int connected; - -@@ -189,7 +191,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv) - } - - memset(&s, 0, sizeof(s)); -- xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk); -+ xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk); - s.x_op = XDR_ENCODE; - - memset(&req, 0, sizeof(req)); -@@ -218,7 +220,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv) - xdr_destroy(&s); - - memset(&s, 0, sizeof(s)); -- xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk); -+ xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk); - s.x_op = XDR_DECODE; - xdrrec_skiprecord(&s); - --- -2.21.0 - - -From a4f645e09d92a8b8f7a80f939091689075d53de1 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 23 Apr 2019 09:40:59 +0300 -Subject: [PATCH 11/13] Define send_ldap_result as an external function - prototype - -389-ds does not expose send_ldap_result() as a public API. However, -we depend on it because slapi_send_ldap_result() is not usable for -the specific use case of the schema compatibility plugin. ---- - src/back-sch.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 9201c2e..f6211bc 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -55,6 +55,12 @@ - #include "map.h" - #include "back-sch.h" - -+/* -+ * This is not a public function in 389-ds but we need to use it in backend_search_cb(), -+ * see a comment there on the difference between slapi_send_ldap_result() and send_ldap_result(). -+ */ -+extern void send_ldap_result(Slapi_PBlock *pb, int err, char *matched, char *text, int nentries, struct berval **urls); -+ - static int backend_passwdmod_extop(Slapi_PBlock *pb); - backend_extop_handlers_t extop_handlers[] = {{EXTOP_PASSWD_OID, (IFP) backend_passwdmod_extop}, - {NULL, NULL}}; --- -2.21.0 - - -From dc3c95cf5b5a2c2d5e7f81ed02f2d9bf3c9acb9f Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 23 Apr 2019 09:42:41 +0300 -Subject: [PATCH 12/13] Declare transaction-aware callbacks for schema compat - plugin - -Schema compatibility plugin provides two transaction-aware -callbacks. The functions need to be declared as they are defined and -used in different compilation units. ---- - src/backend.h | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/backend.h b/src/backend.h -index f0a5bbb..4034704 100644 ---- a/src/backend.h -+++ b/src/backend.h -@@ -68,6 +68,11 @@ int backend_init_postop(struct slapi_pblock *pb, struct plugin_state *state); - int backend_init_internal_postop(struct slapi_pblock *pb, - struct plugin_state *state); - -+/* Only used for schema compatibility plugin*/ -+int backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state); -+int backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state); -+ -+ - /* Read the server's name. */ - int backend_read_master_name(struct plugin_state *state, - struct slapi_pblock *pb, --- -2.21.0 - - -From 1d9e79557df660f4556edb59bedead00eda9b757 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 23 Apr 2019 09:44:48 +0300 -Subject: [PATCH 13/13] Use portable definitions for printing PRUint32 values - -Also include proper headers for NSPR thread-local variable handling. -Fixes covscan warnings. ---- - src/back-shr.c | 4 +++- - src/map.c | 28 ++++++++++++++++------------ - 2 files changed, 19 insertions(+), 13 deletions(-) - -diff --git a/src/back-shr.c b/src/back-shr.c -index b348869..472846a 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -37,7 +37,9 @@ - #endif - - #include --#include -+#include -+/* NSPR private API for thread-local variables */ -+#include - #include "../yp/yp.h" - - #ifdef HAVE_TCPD_H -diff --git a/src/map.c b/src/map.c -index f80f465..3be60b4 100644 ---- a/src/map.c -+++ b/src/map.c -@@ -23,6 +23,7 @@ - #include "config.h" - #endif - -+#include - #include - #include - #include -@@ -40,6 +41,9 @@ - - #include - -+/* NSPR private API for thread-local variables */ -+#include -+ - #include "backend.h" - #include "disp-nis.h" - #include "map.h" -@@ -1264,7 +1268,7 @@ map_rdlock(void) - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock", -- "thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level()); -+ "thread_id = %"PRIx32" (call level = %d)\n", PR_MyThreadId(), wrap_get_call_level()); - #endif - if (lock_status == MAP_RWLOCK_UNINIT) { - /* This is not initialized used the old way */ -@@ -1284,7 +1288,7 @@ map_rdlock(void) - #if DEBUG_MAP_LOCK - if (lock_count != 0) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) ALERT !!! count was %d -> 1\n", (void *) PR_MyThreadId(), lock_count); -+ "map rdlock: (%"PRIx32") ALERT !!! count was %d -> 1\n", PR_MyThreadId(), lock_count); - } - #endif - -@@ -1292,12 +1296,12 @@ map_rdlock(void) - rc = plugin_rdlock(); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc); -+ "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc); - return rc; - } - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", (void *) PR_MyThreadId(), 1); -+ "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD : count=%d\n", PR_MyThreadId(), 1); - #endif - rc = wrap_rwlock_rdlock(map_data.lock); - if (rc) { -@@ -1311,8 +1315,8 @@ map_rdlock(void) - - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n", -- (void *) PR_MyThreadId(), -+ "map rdlock: (%x"PRIx32") was already hold %s : count=%d > %d!!!\n", -+ PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", - lock_count, lock_count + 1); - #endif -@@ -1360,25 +1364,25 @@ map_wrlock(void) - #if DEBUG_MAP_LOCK - if (lock_count != 0) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) ALERT !!! count was %d --> 1\n", (void *) PR_MyThreadId(), lock_count); -+ "map wrlock: (%"PRIx32") ALERT !!! count was %d --> 1\n", PR_MyThreadId(), lock_count); - } - #endif - /* Acquire the slapi plugin in write */ - rc = plugin_wrlock(); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schemacompat", -- "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc); -+ "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc); - return rc; - } - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", (void *) PR_MyThreadId(), 1); -+ "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : count=%d\n", PR_MyThreadId(), 1); - #endif - - rc = wrap_rwlock_wrlock(map_data.lock); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", (void *) PR_MyThreadId(), rc); -+ "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_MyThreadId(), rc); - plugin_unlock(); - goto common; - } -@@ -1386,8 +1390,8 @@ map_wrlock(void) - set_plugin_monitor_count(lock_count + 1); - #if DEBUG_MAP_LOCK - slapi_log_error(SLAPI_LOG_FATAL, "schema-compat", -- "map wrlock: (%p) %s --> MAP_WLOCK_HELD : count=%d\n", -- (void *) PR_MyThreadId(), -+ "map wrlock: (%"PRIx32") %s --> MAP_WLOCK_HELD : count=%d\n", -+ PR_MyThreadId(), - (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD", - lock_count + 1); - #endif --- -2.21.0 - diff --git a/SOURCES/slapi-0101-Fix-some-of-compiler-warnings.patch b/SOURCES/slapi-0101-Fix-some-of-compiler-warnings.patch deleted file mode 100644 index 113f7b0..0000000 --- a/SOURCES/slapi-0101-Fix-some-of-compiler-warnings.patch +++ /dev/null @@ -1,224 +0,0 @@ -From a8881e4cbb006fd317ecf89f006747c4dd1c84a4 Mon Sep 17 00:00:00 2001 -From: Stanislav Levin -Date: Tue, 11 Jun 2019 16:54:01 +0300 -Subject: [PATCH 1/2] Fix some of compiler warnings - -Signed-off-by: Stanislav Levin ---- - src/back-nis.c | 2 ++ - src/back-sch-idview.c | 8 +++----- - src/back-sch.c | 9 ++------- - src/back-shr.c | 2 -- - src/nis.c | 4 ++-- - src/portmap.c | 15 ++++++++++++--- - src/wrap.c | 5 +++-- - tests/clients/Makefile.am | 2 +- - tests/clients/yp.c | 3 +-- - yp/Makefile.am | 2 +- - 10 files changed, 27 insertions(+), 25 deletions(-) - -diff --git a/src/back-nis.c b/src/back-nis.c -index 244beba..adf378e 100644 ---- a/src/back-nis.c -+++ b/src/back-nis.c -@@ -849,6 +849,8 @@ backend_update_params(Slapi_PBlock *pb, struct plugin_state *state) - request_set(state->request_info, RQ_DAEMON, - DEFAULT_TCPWRAP_NAME); - } -+#else -+ (void)tmp; - #endif - use_be_txns = backend_shr_get_vattr_boolean(state, our_entry, - "nsslapd-pluginbetxn", -diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c -index e83fb1d..6769e8d 100644 ---- a/src/back-sch-idview.c -+++ b/src/back-sch-idview.c -@@ -56,7 +56,7 @@ void - idview_get_overrides(struct backend_search_cbdata *cbdata) - { - char *dn = NULL; -- int ret = 0, result = 0; -+ int result = 0; - const Slapi_DN *suffix = NULL; - Slapi_PBlock *pb; - -@@ -76,7 +76,7 @@ idview_get_overrides(struct backend_search_cbdata *cbdata) - slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE, - "(objectclass=ipaOverrideAnchor)", NULL, 0, - NULL, NULL, cbdata->state->plugin_identity, 0); -- ret = slapi_search_internal_pb(pb); -+ slapi_search_internal_pb(pb); - slapi_ch_free_string(&dn); - slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); - -@@ -411,8 +411,6 @@ idview_replace_filter(struct backend_search_cbdata *cbdata) - { - struct backend_search_filter_config config = - {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, NULL}; -- int res = 0; -- - if (cbdata->idview == NULL) { - return; - } -@@ -421,7 +419,7 @@ idview_replace_filter(struct backend_search_cbdata *cbdata) - config.callback_data = cbdata; - - /* Ignore the return code as it will always be SLAPI_FILTER_SCAN_NO_MORE */ -- res = backend_analyze_search_filter(cbdata->filter, &config); -+ (void)backend_analyze_search_filter(cbdata->filter, &config); - - if (config.name != NULL) { - slapi_ch_free_string(&config.name); -diff --git a/src/back-sch.c b/src/back-sch.c -index f6211bc..3f7e30f 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -438,13 +438,8 @@ backend_set_operational_attributes(Slapi_Entry *e, - * plugin want to override the values using the configuration, they - * can. */ - if (gmtime_r(×tamp, ×tamp_tm) == ×tamp_tm) { -- sprintf(timestamp_str, "%04d%02d%02d%02d%02d%02dZ", -- timestamp_tm.tm_year + 1900, -- timestamp_tm.tm_mon + 1, -- timestamp_tm.tm_mday, -- timestamp_tm.tm_hour, -- timestamp_tm.tm_min, -- timestamp_tm.tm_sec); -+ strftime(timestamp_str, sizeof(timestamp_str), -+ "%Y%m%d%H%M%SZ", ×tamp_tm); - slapi_entry_add_string(e, "createTimestamp", timestamp_str); - slapi_entry_add_string(e, "modifyTimestamp", timestamp_str); - } -diff --git a/src/back-shr.c b/src/back-shr.c -index 472846a..0c29d1f 100644 ---- a/src/back-shr.c -+++ b/src/back-shr.c -@@ -780,8 +780,6 @@ static void - backend_shr_data_initialize_thread(time_t when, void *arg) - { - struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; -- PRThread *thread = NULL; -- - if (slapi_is_shutting_down()) { - return; - } -diff --git a/src/nis.c b/src/nis.c -index 82b4c63..845c9da 100644 ---- a/src/nis.c -+++ b/src/nis.c -@@ -967,7 +967,7 @@ nis_process_request(struct plugin_state *state, - AUTH *request_auth, *reply_auth; - char auth_buf[MAX_AUTH_BYTES]; - struct rpc_msg request, reply; -- int auth_flavor, auth_len; -+ int auth_flavor; - struct ypresp_val reply_val; - struct ypresp_key_val reply_key_val; - struct ypresp_all reply_all; -@@ -1057,7 +1057,7 @@ nis_process_request(struct plugin_state *state, - } - auth_marshall(reply_auth, &auth_xdrs); - auth_destroy(reply_auth); -- auth_len = xdr_getpos(&auth_xdrs); -+ (void)xdr_getpos(&auth_xdrs); - xdr_destroy(&auth_xdrs); - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "built reply authenticator\n"); -diff --git a/src/portmap.c b/src/portmap.c -index f2e009e..bf700d9 100644 ---- a/src/portmap.c -+++ b/src/portmap.c -@@ -77,7 +77,8 @@ slapi_log_error(int i, char *f, char *fmt, ...) - int - main(int argc, char **argv) - { -- int s, ret, port; -+ int s, port; -+ int ret __attribute__ ((unused)); - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) { - printf("error allocating socket\n"); -@@ -94,8 +95,16 @@ main(int argc, char **argv) - printf("error creating portmap/rpcbind client socket\n"); - return 1; - } -- setregid(2516, 2516); -- setreuid(2510, 2510); -+ if (setregid(2516, 2516) == -1) { -+ printf("error setting real and effective group id %s\n", -+ strerror(errno)); -+ return 1; -+ } -+ if (setreuid(2510, 2510) == -1) { -+ printf("error setting real and effective user id %s\n", -+ strerror(errno)); -+ return 1; -+ } - sleep(60); - portmap_unregister("portmap", &s, port, YPPROG, YPVERS, - AF_INET, IPPROTO_TCP, 0); -diff --git a/src/wrap.c b/src/wrap.c -index f8056a4..2905f84 100644 ---- a/src/wrap.c -+++ b/src/wrap.c -@@ -153,13 +153,14 @@ void * - wrap_stop_thread(struct wrapped_thread *t) - { - void *returned = NULL; -+ int ret __attribute__ ((unused)); - #ifdef USE_PTHREADS -- write(t->stopfd[1], "", 1); -+ ret = write(t->stopfd[1], "", 1); - close(t->stopfd[1]); - pthread_join(t->tid, &returned); - #endif - #ifdef USE_NSPR_THREADS -- write(t->stopfd[1], "", 1); -+ ret = write(t->stopfd[1], "", 1); - close(t->stopfd[1]); - PR_JoinThread(t->tid); - returned = t->args.result; -diff --git a/tests/clients/Makefile.am b/tests/clients/Makefile.am -index b5326da..6415d02 100644 ---- a/tests/clients/Makefile.am -+++ b/tests/clients/Makefile.am -@@ -12,7 +12,7 @@ yp.h: ../../yp/yp.x - $(RPCGEN) -h -o $@ $^ - yp_xdr.c: ../../yp/yp.x - $(RM) -f $@ -- $(RPCGEN) -c -o $@ $^ -+ $(RPCGEN) -c -i 0 -o $@ $^ - yp_clnt.c: ../../yp/yp.x - $(RM) -f $@ - $(RPCGEN) -l -o $@ $^ -diff --git a/tests/clients/yp.c b/tests/clients/yp.c -index bc2da1f..88d2b81 100644 ---- a/tests/clients/yp.c -+++ b/tests/clients/yp.c -@@ -164,8 +164,7 @@ writejunk(char *fd, char *data, int size) - static int - all(CLIENT *client, FILE *output, int argc, char **argv) - { -- ypresp_all *ret; -- int i, sock; -+ int sock; - ypreq_nokey nokey; - struct rpc_msg req, rep; - struct ypresp_all resp; -diff --git a/yp/Makefile.am b/yp/Makefile.am -index a75aa22..a4b4e4b 100644 ---- a/yp/Makefile.am -+++ b/yp/Makefile.am -@@ -7,7 +7,7 @@ yp.h: yp.x - $(RPCGEN) -h -o $@ $^ - yp_xdr.c: yp.x - $(RM) -f $@ -- $(RPCGEN) -c -o $@ $^ -+ $(RPCGEN) -c -i 0 -o $@ $^ - yp_clnt.c: yp.x - $(RM) -f $@ - $(RPCGEN) -l -o $@ $^ --- -2.21.0 - diff --git a/SOURCES/slapi-0102-Bug-1725845-slapi-nis-crashes-when-returning-an-entr.patch b/SOURCES/slapi-0102-Bug-1725845-slapi-nis-crashes-when-returning-an-entr.patch deleted file mode 100644 index c616f3d..0000000 --- a/SOURCES/slapi-0102-Bug-1725845-slapi-nis-crashes-when-returning-an-entr.patch +++ /dev/null @@ -1,44 +0,0 @@ -From e34a1220d740490a78185fb65bf575766906e419 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Thu, 1 Aug 2019 18:23:14 +0200 -Subject: [PATCH 2/2] Bug 1725845: slapi-nis crashes when returning an entry - with invalid DN - -Bug Description: - On a search on compat tree, slapi-nis prepared the set of entries to return. - It stores the entries into a hashtable, using the normalized DN as a key. - If the entry contains an invalid DN, the key is invalid and triggers - a crash while adding the entry in the hashtable - -https://bugzilla.redhat.com/show_bug.cgi?id=1725845 ---- - src/back-sch.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/back-sch.c b/src/back-sch.c -index 3f7e30f..87fa24c 100644 ---- a/src/back-sch.c -+++ b/src/back-sch.c -@@ -1525,16 +1525,17 @@ backend_entries_to_return_push(struct backend_search_cbdata *cbdata, Slapi_Entry - struct entries_to_send *e_to_send = NULL; - struct cached_entry *entry = NULL; - bool_t dont_cache = FALSE; -+ void *ndn_key = (void *) slapi_entry_get_ndn(e); - PLHashTable* ht = (PLHashTable*) cbdata->state->cached_entries; - -- if ((cbdata == NULL) || (e == NULL)) return; -+ if ((cbdata == NULL) || (e == NULL) || (ndn_key == NULL)) return; - - e_to_send = (struct entries_to_send *) slapi_ch_calloc(1, sizeof(struct entries_to_send)); - - dont_cache = cbdata->state->use_entry_cache ? FALSE : TRUE; - - if (!wrap_rwlock_wrlock(cbdata->state->cached_entries_lock)) { -- entry = PL_HashTableLookup(ht, slapi_entry_get_ndn(e)); -+ entry = PL_HashTableLookup(ht, ndn_key); - if (entry != NULL) { - /* There is an entry in the hash table but is it the same? */ - char *e_modifyTimestamp = slapi_entry_attr_get_charptr(e, "modifyTimestamp"); --- -2.21.0 - diff --git a/SOURCES/slapi-nis-0.56.0.tar.gz.sig b/SOURCES/slapi-nis-0.56.0.tar.gz.sig deleted file mode 100644 index f83fae6..0000000 Binary files a/SOURCES/slapi-nis-0.56.0.tar.gz.sig and /dev/null differ diff --git a/SOURCES/slapi-nis-0.56.5.tar.gz.asc b/SOURCES/slapi-nis-0.56.5.tar.gz.asc new file mode 100644 index 0000000..075609e --- /dev/null +++ b/SOURCES/slapi-nis-0.56.5.tar.gz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQEzBAABCgAdFiEEEb9A7wQ1zA7rMdssD2m7b4Oa3L0FAl6v1FsACgkQD2m7b4Oa +3L2MLwgAuQNbDTVFDLFBP2+tAXlPnvVL6q476BMffBDVA4U1L3F1OFABMmTRfOC8 +WM8m90YjkOwUIC1wvwn+Mbw2Y0YWJY3AwR2xM/3KTxd2YVqIN68nPOax0BAYMJfS +drVV8asb8Cg4uQ+xUdcrGg0mpiYbC5slTX8p8zdAMylYgXxTKRBnqZItCkQ8zgtj ++euh8gof7ORMaRVNhHFH2UsMGAHQf9JfCnnKIPWOU2NO1bKS/v7P9I5vb3dOB4gF +/88GxWAMbME8/Y7syYQ314ROCqbQybBM0T7f6xixvHFF/tgI+V36wHN6XdpadbcU +6TrOLdyrQUbSXltmFbF6N0Od5/VAXw== +=rpl9 +-----END PGP SIGNATURE----- diff --git a/SOURCES/slapi-nis-bz1832190.patch b/SOURCES/slapi-nis-bz1832190.patch new file mode 100644 index 0000000..570735b --- /dev/null +++ b/SOURCES/slapi-nis-bz1832190.patch @@ -0,0 +1,49 @@ +From e8c3ed416a442f5a431ca48f7ea384a6abc1fa53 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 6 May 2020 14:08:41 +0300 +Subject: [PATCH] Initialize map lock in NIS plugin as well + +Also if ignored_containers_sdn is NULL, we don't really need to check +whether a write could be ignored. It has to be processed, so bail out +early with FALSE. + +Resolves: rhbz#1832190 + +Signed-off-by: Alexander Bokovoy +--- + src/back-shr.c | 4 ++++ + src/plug-nis.c | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/src/back-shr.c b/src/back-shr.c +index e2b5dd3..c6a181e 100644 +--- a/src/back-shr.c ++++ b/src/back-shr.c +@@ -2960,6 +2960,10 @@ backend_shr_write_ignore(Slapi_PBlock *pb) + int i = 0; + PRBool ignore = PR_FALSE; + ++ if (ignored_containers_sdn == NULL) { ++ return ignore; ++ } ++ + /* Check if the target DN is a subordinates of + * on of the ignored containers + */ +diff --git a/src/plug-nis.c b/src/plug-nis.c +index ee90c37..0ce4ae6 100644 +--- a/src/plug-nis.c ++++ b/src/plug-nis.c +@@ -540,6 +540,9 @@ nis_plugin_init(Slapi_PBlock *pb) + "error setting up plugin\n"); + return -1; + } ++ ++ init_map_lock(); ++ + /* Read global configuration. */ + if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, + &plugin_entry) == 0) && +-- +2.25.4 + diff --git a/SPECS/slapi-nis.spec b/SPECS/slapi-nis.spec index cc82e12..df7b223 100644 --- a/SPECS/slapi-nis.spec +++ b/SPECS/slapi-nis.spec @@ -10,38 +10,20 @@ %endif Name: slapi-nis -Version: 0.56.0 -Release: 13%{?dist} +Version: 0.56.5 +Release: 2%{?dist} Summary: NIS Server and Schema Compatibility plugins for Directory Server Group: System Environment/Daemons License: GPLv2 URL: http://pagure.io/slapi-nis/ Source0: https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz -Source1: https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz.sig -Patch1: slapi-0001-Move-advance-definition-of-backend_passwdmod_extop-b.patch -Patch2: slapi-0002-Initialize-ret-before-use.patch -Patch3: slapi-0003-slapi-nis-resolve-IPA-groups-with-fully-qualified-su.patch -Patch4: slapi-0004-Declare-int-backend_init_extop-for-reuse-in-plug-sch.patch -Patch5: slapi-0005-Double-free-on-ldap-entry-during-priming.patch -Patch6: slapi-0006-back-sch-do-not-clobber-target-of-the-pblock-for-idv.patch -Patch7: slapi-0007-back-sch-nss-for-users-with-aliases-return-alias-as-.patch -Patch11: slapi-0011-Move-a-helper-to-build-DN-to-a-format.c.patch -Patch12: slapi-0012-Add-dummy-handler-for-a-related-add-delete-modify-to.patch -Patch13: slapi-0013-track-changes-to-ID-overrides-and-evict-map-cache-en.patch -Patch15: slapi-0015-configure.ac-detect-extended-NSS-API-provided-by-SSS.patch -Patch16: slapi-0016-schema-compat-add-support-for-timeout-based-NSS-quer.patch -Patch17: slapi-0017-back-sch-cancel-memberof-retrieval-in-case-of-a-dirs.patch -Patch18: slapi-0017-Fix-nss_sss-callers.patch -Patch19: slapi-0018-Clean-up-unused-code.patch -Patch20: slapi-0019-Synchronize-nsswitch-backend-code-with-freeIPA.patch -Patch21: slapi-0020-Use-extended-SSSD-API-to-signal-that-an-entry-should.patch -Patch22: slapi-0100-deadlok-between-write-and-search-operation.patch -Patch23: slapi-0101-Fix-some-of-compiler-warnings.patch -Patch24: slapi-0102-Bug-1725845-slapi-nis-crashes-when-returning-an-entr.patch +Source1: https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz.asc +Patch1: slapi-nis-bz1832190.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) - -BuildRequires: libtool, automake, autoconf +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool BuildRequires: 389-ds-base-devel >= 1.3.5.6, %{ldap_impl}-devel BuildRequires: nspr-devel, nss-devel, /usr/bin/rpcgen %if 0%{?fedora} > 18 || 0%{?rhel} > 6 @@ -83,25 +65,6 @@ for attributes from multiple entries in the tree. %prep %setup -q %patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 %build libtoolize -f -c @@ -137,6 +100,17 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/nisserver-plugin-defs %changelog +* Wed May 06 2020 Alexander Bokovoy - 0.56.5-2 +- Initialize map lock in NIS plugin +- Resolves: rhbz#1832190 + +* Mon May 04 2020 Alexander Bokovoy - 0.56.5-1 +- Upstream release 0.56.5 +- Resolves: rhbz#1820124 When sync-repl is enabled, slapi-nis can deadlock during retrochanglog trimming +- Resolves: rhbz#1820122 ERR - schemacompat - map rdlock: old way MAP_MONITOR_DISABLED +- Resolves: rhbz#1819018 ipa slapi-nis stack traces review request for LDAP server deadlock +- Resolves: rhbz#1830894 Memory leak during search of idview overrides + * Fri Aug 16 2019 Alexander Bokovoy - 0.56.0-13 - Fixed: #1725845 ns-slapd is crashing intermittently