diff --git a/SOURCES/0083-Ticket-49410-opened-connection-can-remain-no-longer-.patch b/SOURCES/0083-Ticket-49410-opened-connection-can-remain-no-longer-.patch new file mode 100644 index 0000000..a94aa80 --- /dev/null +++ b/SOURCES/0083-Ticket-49410-opened-connection-can-remain-no-longer-.patch @@ -0,0 +1,58 @@ +From 72f541fd317321fbd0395dcaa77830aa8b5d35b6 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Wed, 15 Nov 2017 16:38:28 +0100 +Subject: [PATCH] Ticket 49410 - opened connection can remain no longer poll, + like hanging + +Bug Description: + Some opened connection are no longer poll. + Those connections has 'gettingber' toggle set although there is + no more worker thread reading it. + The reason they have gettingber set is that the last + operation had 'persistent search' flag. With such flag + gettingber is not reset. + persistent flag is set even when no persistent search/sync_repl + was received on the connection. + The problem is that the flag is tested on the wrong operation. + The tested operation can be + - the first operation when the connection entered in turbo mode + - the previous operation if several ops PDUs were read on the network + - accessing random memory + + In theory testing the flag can lead to sigsev even + if it never crash + +Fix Description: + The fix is to use the operation that is in the pblock + In such case pb_op is no longer used, so we can get rid of it. + In addition make pb_conn a local variable where it is used + +https://pagure.io/389-ds-base/issue/49410 + +Reviewed by: Ludwig Krispenz, Mark Reynolds + +Platforms tested: F26 + +Flag Day: no + +Doc impact: no +--- + ldap/servers/slapd/connection.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index 359b59a4d..c00c88578 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -1540,6 +1540,8 @@ connection_threadmain() + } + + if (!thread_turbo_flag && !more_data) { ++ Connection *pb_conn = NULL; ++ + /* If more data is left from the previous connection_read_operation, + we should finish the op now. Client might be thinking it's + done sending the request and wait for the response forever. +-- +2.13.6 + diff --git a/SOURCES/0084-Ticket-48118-backport-changelog-can-be-erronously-re.patch b/SOURCES/0084-Ticket-48118-backport-changelog-can-be-erronously-re.patch new file mode 100644 index 0000000..14787e1 --- /dev/null +++ b/SOURCES/0084-Ticket-48118-backport-changelog-can-be-erronously-re.patch @@ -0,0 +1,237 @@ +From b0d593b001d4ef1fb19348335fb39bd45b31764c Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Fri, 8 Dec 2017 14:26:06 +0100 +Subject: [PATCH] Ticket 48118 - backport - changelog can be erronously rebuilt + at startup + +--- + ldap/servers/plugins/replication/cl5_api.c | 39 ++++++++++++++++++++++ + ldap/servers/plugins/replication/repl5.h | 1 - + ldap/servers/plugins/replication/repl5_replica.c | 39 ++-------------------- + .../plugins/replication/repl5_replica_config.c | 2 -- + 4 files changed, 41 insertions(+), 40 deletions(-) + +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index 5c2233f82..1ce8d081f 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -304,6 +304,8 @@ static void _cl5ReadBerval (struct berval *bv, char** buff); + static void _cl5WriteBerval (struct berval *bv, char** buff); + static int _cl5ReadBervals (struct berval ***bv, char** buff, unsigned int size); + static int _cl5WriteBervals (struct berval **bv, char** buff, u_int32_t *size); ++static int32_t _cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv); ++static int32_t _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg); + + /* replay iteration */ + #ifdef FOR_DEBUGGING +@@ -2885,6 +2887,36 @@ static int _cl5WriteBervals (struct berval **bv, char** buff, u_int32_t *size) + return CL5_SUCCESS; + } + ++static int32_t ++_cl5CheckCSNinCL(const ruv_enum_data *element, void *arg) ++{ ++ CL5DBFile *file = (CL5DBFile *)arg; ++ int rc = 0; ++ ++ DBT key = {0}, data = {0}; ++ char csnStr[CSN_STRSIZE]; ++ ++ /* construct the key */ ++ key.data = csn_as_string(element->csn, PR_FALSE, csnStr); ++ key.size = CSN_STRSIZE; ++ ++ data.flags = DB_DBT_MALLOC; ++ ++ rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0); ++ ++ slapi_ch_free(&(data.data)); ++ return rc; ++} ++ ++static int32_t ++_cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv) ++{ ++ int rc = 0; ++ ++ rc = ruv_enumerate_elements(maxruv, _cl5CheckCSNinCL, (void *)file); ++ ++ return rc; ++} + /* upgrade from db33 to db41 + * 1. Run recovery on the database environment using the DB_ENV->open method + * 2. Remove any Berkeley DB environment using the DB_ENV->remove method +@@ -4248,6 +4280,13 @@ static int _cl5WriteRUV (CL5DBFile *file, PRBool purge) + rc = ruv_to_bervals(file->maxRUV, &vals); + } + ++ if (!purge && _cl5CheckMaxRUV(file, file->maxRUV)) { ++ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, ++ "_cl5WriteRUV - changelog maxRUV not found in changelog for file %s\n", ++ file->name); ++ return CL5_DB_ERROR; ++ } ++ + key.size = CSN_STRSIZE; + + rc = _cl5WriteBervals (vals, &buff, &data.size); +diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h +index 718f64ef1..9c4789f9e 100644 +--- a/ldap/servers/plugins/replication/repl5.h ++++ b/ldap/servers/plugins/replication/repl5.h +@@ -620,7 +620,6 @@ Object *replica_get_for_backend (const char *be_name); + void replica_set_purge_delay (Replica *r, PRUint32 purge_delay); + void replica_set_tombstone_reap_interval (Replica *r, long interval); + void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv); +-void replica_set_ruv_dirty (Replica *r); + Slapi_Entry *get_in_memory_ruv(Slapi_DN *suffix_sdn); + int replica_write_ruv (Replica *r); + char *replica_get_dn(Replica *r); +diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c +index 7927ac30a..3c7281a42 100644 +--- a/ldap/servers/plugins/replication/repl5_replica.c ++++ b/ldap/servers/plugins/replication/repl5_replica.c +@@ -46,7 +46,6 @@ struct replica { + char* legacy_purl; /* partial url of the legacy supplier */ + ReplicaId repl_rid; /* replicaID */ + Object *repl_ruv; /* replica update vector */ +- PRBool repl_ruv_dirty; /* Dirty flag for ruv */ + CSNPL *min_csn_pl; /* Pending list for minimal CSN */ + void *csn_pl_reg_id; /* registration assignment for csn callbacks */ + unsigned long repl_state_flags; /* state flags */ +@@ -855,7 +854,6 @@ replica_set_ruv (Replica *r, RUV *ruv) + } + + r->repl_ruv = object_new((void*)ruv, (FNFree)ruv_destroy); +- r->repl_ruv_dirty = PR_TRUE; + + replica_unlock(r->repl_lock); + } +@@ -941,11 +939,6 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + slapi_sdn_get_dn(r->repl_root), + csn_as_string(updated_csn, PR_FALSE, csn_str)); + } +- else +- { +- /* RUV updated - mark as dirty */ +- r->repl_ruv_dirty = PR_TRUE; +- } + } + else + { +@@ -1526,8 +1519,6 @@ replica_dump(Replica *r) + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\tupdate dn: %s\n", + updatedn_list? updatedn_list : "not configured"); + slapi_ch_free_string(&updatedn_list); +- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\truv: %s configured and is %sdirty\n", +- r->repl_ruv ? "" : "not", r->repl_ruv_dirty ? "" : "not "); + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\tCSN generator: %s configured\n", + r->repl_csngen ? "" : "not"); + /* JCMREPL - Dump Referrals */ +@@ -1877,7 +1868,6 @@ int replica_check_for_data_reload (Replica *r, void *arg) + + ruv_force_csn_update_from_ruv(upper_bound_ruv, r_ruv, + "Force update of database RUV (from CL RUV) -> ", SLAPI_LOG_NOTICE); +- replica_set_ruv_dirty(r); + } + + } else { +@@ -2994,12 +2984,6 @@ replica_write_ruv (Replica *r) + + replica_lock(r->repl_lock); + +- if (!r->repl_ruv_dirty) +- { +- replica_unlock(r->repl_lock); +- return rc; +- } +- + PR_ASSERT (r->repl_ruv); + + ruv_to_smod ((RUV*)object_get_data(r->repl_ruv), &smod); +@@ -3034,19 +3018,13 @@ replica_write_ruv (Replica *r) + /* ruv does not exist - create one */ + replica_lock(r->repl_lock); + +- if (rc == LDAP_SUCCESS) +- { +- r->repl_ruv_dirty = PR_FALSE; +- } +- else if (rc == LDAP_NO_SUCH_OBJECT) ++ if (rc == LDAP_NO_SUCH_OBJECT) + { + /* this includes an internal operation - but since this only happens + during server startup - its ok that we have lock around it */ + rc = _replica_configure_ruv (r, PR_TRUE); +- if (rc == 0) +- r->repl_ruv_dirty = PR_FALSE; + } +- else /* error */ ++ else if (rc != LDAP_SUCCESS) /* error */ + { + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, + "replica_write_ruv - Failed to update RUV tombstone for %s; " +@@ -3570,7 +3548,6 @@ replica_create_ruv_tombstone(Replica *r) + + if (ruv_init_new(csnstr, r->repl_rid, purl, &ruv) == RUV_SUCCESS){ + r->repl_ruv = object_new((void*)ruv, (FNFree)ruv_destroy); +- r->repl_ruv_dirty = PR_TRUE; + return_value = LDAP_SUCCESS; + } else { + slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_create_ruv_tombstone - " +@@ -3610,8 +3587,6 @@ replica_create_ruv_tombstone(Replica *r) + slapi_add_internal_pb(pb); + e = NULL; /* add consumes e, upon success or failure */ + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value); +- if (return_value == LDAP_SUCCESS) +- r->repl_ruv_dirty = PR_FALSE; + + done: + slapi_entry_free (e); +@@ -3930,7 +3905,6 @@ replica_strip_cleaned_rids(Replica *r) + ruv_get_cleaned_rids(ruv, rid); + while(rid[i] != 0){ + ruv_delete_replica(ruv, rid[i]); +- replica_set_ruv_dirty(r); + if (replica_write_ruv(r)) { + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, + "replica_strip_cleaned_rids - Failed to write RUV\n"); +@@ -4052,15 +4026,6 @@ replica_update_ruv_consumer(Replica *r, RUV *supplier_ruv) + } + } + +-void +-replica_set_ruv_dirty(Replica *r) +-{ +- PR_ASSERT(r); +- replica_lock(r->repl_lock); +- r->repl_ruv_dirty = PR_TRUE; +- replica_unlock(r->repl_lock); +-} +- + PRBool + replica_is_state_flag_set(Replica *r, PRInt32 flag) + { +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 814f1cac0..128c9423a 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -1034,7 +1034,6 @@ replica_config_change_type_and_id (Replica *r, const char *new_type, + replica_reset_csn_pl(r); + } + ruv_delete_replica(ruv, oldrid); +- replica_set_ruv_dirty(r); + cl5CleanRUV(oldrid); + replica_set_csn_assigned(r); + } +@@ -1454,7 +1453,6 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not + return LDAP_UNWILLING_TO_PERFORM; + } + rc = ruv_delete_replica(local_ruv, rid); +- replica_set_ruv_dirty(replica); + if (replica_write_ruv(replica)) { + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task - Could not write RUV\n"); + } +-- +2.13.6 + diff --git a/SOURCES/0085-Ticket-49495-Fix-memory-management-is-vattr.patch b/SOURCES/0085-Ticket-49495-Fix-memory-management-is-vattr.patch new file mode 100644 index 0000000..77f8311 --- /dev/null +++ b/SOURCES/0085-Ticket-49495-Fix-memory-management-is-vattr.patch @@ -0,0 +1,293 @@ +From d1236b0d3917b024a252b4d6acf823a975182d3b Mon Sep 17 00:00:00 2001 +From: William Brown +Date: Mon, 11 Dec 2017 15:48:24 +0100 +Subject: [PATCH] Ticket 49495 - Fix memory management is vattr. + +Bug Description: During the fix for +https://pagure.io/389-ds-base/issue/49436 a issue was exposed +in how registration of attributes to cos work. With the change +to handle -> attr link, this exposed that cos treats each attribute +and template pair as a new type for the handle. As aresult, this +caused the sp_list to create a long linked list of M*N entries +for each attr - template value. Obviously, this is extremely +slow to traverse during a search! + +Fix Description: Undo part of the SLL next change and convert +to reference counting. The issue remains that there is a defect +in how cos handles attribute registration, but this can not be +resolved without a significant rearchitecture of the code +related to virtual attributes. + +https://pagure.io/389-ds-base/issue/49495 + +Author: wibrown + +Review by: tbordaz, lkrispen (Thanks!) + +Note: includes backport of incr and decr for rc +--- + ldap/servers/plugins/cos/cos_cache.c | 28 ++++------ + ldap/servers/slapd/slapi-plugin.h | 21 ++++++++ + ldap/servers/slapd/slapi_counter.c | 30 +++++++++++ + ldap/servers/slapd/vattr.c | 100 +++++++++++++++++++++-------------- + 4 files changed, 122 insertions(+), 57 deletions(-) + +diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c +index 0e93183d2..74261af87 100644 +--- a/ldap/servers/plugins/cos/cos_cache.c ++++ b/ldap/servers/plugins/cos/cos_cache.c +@@ -275,7 +275,7 @@ static Slapi_Mutex *start_lock; + static Slapi_Mutex *stop_lock; + static Slapi_CondVar *something_changed = NULL; + static Slapi_CondVar *start_cond = NULL; +- ++static vattr_sp_handle *vattr_handle = NULL; + + /* + cos_cache_init +@@ -313,6 +313,15 @@ int cos_cache_init(void) + goto out; + } + ++ if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle, ++ cos_cache_vattr_get, ++ cos_cache_vattr_compare, ++ cos_cache_vattr_types) != 0) { ++ slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM, "cos_cache_init - Cannot register as service provider\n"); ++ ret = -1; ++ goto out; ++ } ++ + /* grab the views interface */ + if (slapi_apib_get_interface(Views_v1_0_GUID, &views_api)) { + /* lets be tolerant if views is disabled */ +@@ -872,22 +881,7 @@ cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) + dnVals[valIndex]->bv_val); + } + +- /* +- * Each SP_handle is associated to one and only one vattr. +- * We could consider making this a single function rather +- * than the double-call. +- */ +- +- vattr_sp_handle *vattr_handle = NULL; +- +- if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle, +- cos_cache_vattr_get, +- cos_cache_vattr_compare, +- cos_cache_vattr_types) != 0) { +- slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM, "cos_cache_init - Cannot register as service provider for %s\n", dnVals[valIndex]->bv_val); +- } else { +- slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL); +- } ++ slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL); + + } /* if(attrType is cosAttribute) */ + +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 4084945f4..16aa1b711 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -8063,6 +8063,27 @@ int slapi_is_special_rdn(const char *rdn, int flag); + */ + void DS_Sleep(PRIntervalTime ticks); + ++/** ++ * Increment a 64bitintegral atomicly ++ * ++ * \param ptr - pointer to integral to increment ++ * \param memorder - __ATOMIC_RELAXED, __ATOMIC_CONSUME, __ATOMIC_ACQUIRE, ++ * __ATOMIC_RELEASE, __ATOMIC_ACQ_REL, __ATOMIC_SEQ_CST ++ * \return - new value of ptr ++ */ ++uint64_t slapi_atomic_incr_64(uint64_t *ptr, int memorder); ++ ++/** ++ * Decrement a 64bitintegral atomicly ++ * ++ * \param ptr - pointer to integral to decrement ++ * \param memorder - __ATOMIC_RELAXED, __ATOMIC_CONSUME, __ATOMIC_ACQUIRE, ++ * __ATOMIC_RELEASE, __ATOMIC_ACQ_REL, __ATOMIC_SEQ_CST ++ * \return - new value of ptr ++ */ ++uint64_t slapi_atomic_decr_64(uint64_t *ptr, int memorder); ++ ++ + #ifdef __cplusplus + } + #endif +diff --git a/ldap/servers/slapd/slapi_counter.c b/ldap/servers/slapd/slapi_counter.c +index 9904fe964..59e5223ad 100644 +--- a/ldap/servers/slapd/slapi_counter.c ++++ b/ldap/servers/slapd/slapi_counter.c +@@ -269,3 +269,33 @@ uint64_t slapi_counter_get_value(Slapi_Counter *counter) + return value; + } + ++/* ++ * atomic increment functions (64bit) ++ */ ++uint64_t ++slapi_atomic_incr_64(uint64_t *ptr, int memorder) ++{ ++#ifdef ATOMIC_64BIT_OPERATIONS ++ return __atomic_add_fetch_8(ptr, 1, memorder); ++#else ++ PRInt32 *pr_ptr = (PRInt32 *)ptr; ++ return PR_AtomicIncrement(pr_ptr); ++#endif ++} ++ ++/* ++ * atomic decrement functions (64bit) ++ */ ++ ++uint64_t ++slapi_atomic_decr_64(uint64_t *ptr, int memorder) ++{ ++#ifdef ATOMIC_64BIT_OPERATIONS ++ return __atomic_sub_fetch_8(ptr, 1, memorder); ++#else ++ PRInt32 *pr_ptr = (PRInt32 *)ptr; ++ return PR_AtomicDecrement(pr_ptr); ++#endif ++} ++ ++ +diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c +index 84e01cd62..adf44b0b6 100644 +--- a/ldap/servers/slapd/vattr.c ++++ b/ldap/servers/slapd/vattr.c +@@ -1529,10 +1529,12 @@ struct _vattr_sp { + typedef struct _vattr_sp vattr_sp; + + /* Service provider handle */ +-struct _vattr_sp_handle { +- vattr_sp *sp; +- struct _vattr_sp_handle *next; /* So we can link them together in the map */ +- void *hint; /* Hint to the SP */ ++struct _vattr_sp_handle ++{ ++ vattr_sp *sp; ++ struct _vattr_sp_handle *next; /* So we can link them together in the map */ ++ void *hint; /* Hint to the SP */ ++ uint64_t rc; + }; + + /* Calls made by Service Providers */ +@@ -1758,7 +1760,7 @@ is a separate thing in the insterests of stability. + + */ + +-#define VARRT_MAP_HASHTABLE_SIZE 10 ++#define VARRT_MAP_HASHTABLE_SIZE 32 + + /* Attribute map oject */ + /* Needs to contain: a linked list of pointers to provider handles handles, +@@ -1849,7 +1851,10 @@ vattr_map_entry_free(vattr_map_entry *vae) + vattr_sp_handle *list_entry = vae->sp_list; + while (list_entry != NULL) { + vattr_sp_handle *next_entry = list_entry->next; +- slapi_ch_free((void **)&list_entry); ++ if (slapi_atomic_decr_64(&(list_entry->rc), __ATOMIC_RELAXED) == 0) { ++ /* Only free on RC 0 */ ++ slapi_ch_free((void **)&list_entry); ++ } + list_entry = next_entry; + } + slapi_ch_free_string(&(vae->type_name)); +@@ -2268,41 +2273,56 @@ to handle the calls on it, but return nothing */ + * + * Better idea, is that regattr should just take the fn pointers + * and callers never *see* the sp_handle structure at all. ++ * ++ * This leaves us with some quirks today. First: if you have plugin A ++ * and B, A registers attr 1 and B 1 and 2, it's possible that if you ++ * register A1 first, then B1, you have B->A in next. Then when you ++ * register B2, because we take 0==result from map_lookup, we add sp ++ * "as is" to the map. This means that B2 now has the same next to A1 ++ * handle. This won't add a bug, because A1 won't be able to service the ++ * attr, but it could cause some head scratching ... ++ * ++ * Again, to fix this, the whole vattr external interface needs a ++ * redesign ... :( + */ +- +-int vattr_map_sp_insert(char *type_to_add, vattr_sp_handle *sp, void *hint) +-{ +- int result = 0; +- vattr_map_entry *map_entry = NULL; +- /* Is this type already there ? */ +- result = vattr_map_lookup(type_to_add,&map_entry); +- /* If it is, add this SP to the list, safely even if readers are traversing the list at the same time */ +- if (0 == result) { +- int found = 0; +- vattr_sp_handle *list_entry = NULL; +- /* Walk the list checking that the daft SP isn't already here */ +- for (list_entry = map_entry->sp_list ; list_entry; list_entry = list_entry->next) { +- if (list_entry == sp) { +- found = 1; +- break; +- } +- } +- /* If it is, we do nothing */ +- if(found) { +- return 0; +- } +- /* We insert the SP handle into the linked list at the head */ +- sp->next = map_entry->sp_list; +- map_entry->sp_list = sp; +- } else { +- /* If not, add it */ +- map_entry = vattr_map_entry_new(type_to_add,sp,hint); +- if (NULL == map_entry) { +- return ENOMEM; +- } +- return vattr_map_insert(map_entry); +- } +- return 0; ++int ++vattr_map_sp_insert(char *type_to_add, vattr_sp_handle *sp, void *hint) ++{ ++ int result = 0; ++ vattr_map_entry *map_entry = NULL; ++ /* Is this type already there ? */ ++ result = vattr_map_lookup(type_to_add, &map_entry); ++ /* If it is, add this SP to the list, safely even if readers are traversing the list at the same time */ ++ if (0 == result) { ++ int found = 0; ++ vattr_sp_handle *list_entry = NULL; ++ /* Walk the list checking that the daft SP isn't already here */ ++ for (list_entry = map_entry->sp_list; list_entry; list_entry = list_entry->next) { ++ if (list_entry == sp) { ++ found = 1; ++ break; ++ } ++ } ++ /* If it is, we do nothing */ ++ if (found) { ++ return 0; ++ } ++ /* Increase the ref count of the sphandle */ ++ slapi_atomic_incr_64(&(sp->rc), __ATOMIC_RELAXED); ++ /* We insert the SP handle into the linked list at the head */ ++ sp->next = map_entry->sp_list; ++ map_entry->sp_list = sp; ++ } else { ++ /* If not, add it */ ++ /* Claim a reference on the sp ... */ ++ slapi_atomic_incr_64(&(sp->rc), __ATOMIC_RELAXED); ++ map_entry = vattr_map_entry_new(type_to_add, sp, hint); ++ if (NULL == map_entry) { ++ return ENOMEM; ++ } ++ return vattr_map_insert(map_entry); ++ } ++ return 0; + } + + /* +-- +2.13.6 + diff --git a/SOURCES/0086-CVE-2017-15134-389-ds-base-Remote-DoS-via-search-fil.patch b/SOURCES/0086-CVE-2017-15134-389-ds-base-Remote-DoS-via-search-fil.patch new file mode 100644 index 0000000..23d764e --- /dev/null +++ b/SOURCES/0086-CVE-2017-15134-389-ds-base-Remote-DoS-via-search-fil.patch @@ -0,0 +1,117 @@ +From 040c492b4beb0efcd34b8420f682187441767055 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 16 Jan 2018 09:46:49 -0500 +Subject: [PATCH] CVE-2017-15134 389-ds-base: Remote DoS via search filters in + slapi_filter_sprintf + +Description: Improper handling of a search filter in slapi_filter_sprintf + in slapd/util.c can lead to remote server crash and denial + of service. + +https://bugzilla.redhat.com/show_bug.cgi?id=1529117 +--- + ldap/servers/slapd/util.c | 36 +++++++++++++++++++++++++++++++----- + 1 file changed, 31 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c +index 4ff6d4141..ffeeff6f3 100644 +--- a/ldap/servers/slapd/util.c ++++ b/ldap/servers/slapd/util.c +@@ -224,9 +224,10 @@ escape_string_for_filename(const char *str, char buf[BUFSIZ]) + + struct filter_ctx { + char *buf; +- char attr[ATTRSIZE]; ++ char *attr; + int attr_position; + int attr_found; ++ size_t attr_size; + int buf_size; + int buf_len; + int next_arg_needs_esc_norm; +@@ -265,7 +266,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) + * Start collecting the attribute name so we can use the correct + * syntax normalization func. + */ +- if(ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)){ ++ if(ctx->attr_found == 0 && ctx->attr_position < (ctx->attr_size - 1)) { + if(ctx->attr[0] == '\0'){ + if(strstr(val,"=")){ + /* we have an attr we need to record */ +@@ -279,6 +280,14 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) + * attr with val. The next pass should be '=', otherwise we will + * reset it. + */ ++ if (slen > ctx->attr_size) { ++ if (ctx->attr_size == ATTRSIZE) { ++ ctx->attr = slapi_ch_calloc(sizeof(char), slen+1); ++ } else { ++ ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (slen+1)); ++ } ++ ctx->attr_size = slen+1; ++ } + memcpy(ctx->attr, val, slen); + ctx->attr_position = slen; + } +@@ -288,9 +297,20 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) + } else { + if(special_attr_char(val[0])){ + /* this is not an attribute, we should not be collecting this, reset everything */ +- memset(ctx->attr, '\0', ATTRSIZE); ++ memset(ctx->attr, '\0', ctx->attr_size); + ctx->attr_position = 0; + } else { ++ /* we can be adding char by char and overrun allocated size */ ++ if (ctx->attr_position >= ctx->attr_size) { ++ if (ctx->attr_size == ATTRSIZE) { ++ char *ctxattr = slapi_ch_calloc(sizeof(char), ctx->attr_size + ATTRSIZE); ++ memcpy(ctxattr, ctx->attr, ctx->attr_size); ++ ctx->attr = ctxattr; ++ } else { ++ ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (ctx->attr_size + ATTRSIZE)); ++ } ++ ctx->attr_size = ctx->attr_size + ATTRSIZE; ++ } + memcpy(ctx->attr + ctx->attr_position, val, 1); + ctx->attr_position++; + } +@@ -363,7 +383,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) + ctx->next_arg_needs_esc_norm = 0; + ctx->attr_found = 0; + ctx->attr_position = 0; +- memset(ctx->attr, '\0', ATTRSIZE); ++ memset(ctx->attr, '\0', ctx->attr_size); + slapi_ch_free_string(&buf); + + return filter_len; +@@ -402,13 +422,15 @@ slapi_filter_sprintf(const char *fmt, ...) + { + struct filter_ctx ctx = {0}; + va_list args; ++ char attr_static[ATTRSIZE] = {0}; + char *buf; + int rc; + + buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1); + ctx.buf = buf; +- memset(ctx.attr,'\0', ATTRSIZE); + ctx.attr_position = 0; ++ ctx.attr = attr_static; ++ ctx.attr_size = ATTRSIZE; + ctx.attr_found = 0; + ctx.buf_len = FILTER_BUF; + ctx.buf_size = 0; +@@ -424,6 +446,10 @@ slapi_filter_sprintf(const char *fmt, ...) + } + va_end(args); + ++ if (ctx.attr_size > ATTRSIZE) { ++ slapi_ch_free_string(&ctx.attr); ++ } ++ + return ctx.buf; + } + +-- +2.13.6 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index ed028d0..61d84f7 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -30,7 +30,7 @@ Summary: 389 Directory Server (base) Name: 389-ds-base Version: 1.3.6.1 -Release: %{?relprefix}24%{?prerel}%{?dist} +Release: %{?relprefix}26%{?prerel}%{?dist} License: GPLv3+ URL: https://www.port389.org/ Group: System Environment/Daemons @@ -216,6 +216,10 @@ Patch79: 0079-Ticket-49439-cleanallruv-is-not-logging-information.patch Patch80: 0080-Ticket-49436-double-free-in-COS-in-some-conditions.patch Patch81: 0081-Ticket-49441-Import-crashes-with-large-indexed-binar.patch Patch82: 0082-Ticket-49431-replicated-MODRDN-fails-breaking-replic.patch +Patch83: 0083-Ticket-49410-opened-connection-can-remain-no-longer-.patch +Patch84: 0084-Ticket-48118-backport-changelog-can-be-erronously-re.patch +Patch85: 0085-Ticket-49495-Fix-memory-management-is-vattr.patch +Patch86: 0086-CVE-2017-15134-389-ds-base-Remote-DoS-via-search-fil.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -368,6 +372,10 @@ cp %{SOURCE2} README.devel %patch80 -p1 %patch81 -p1 %patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 %build @@ -600,6 +608,16 @@ fi %{_sysconfdir}/%{pkgname}/dirsrvtests %changelog +* Tue Jan 16 2018 Mark Reynolds - 1.3.6.1-26 +- Bump version to 1.3.6.1-25 +- Resolves: Bug 1534430 - crash in slapi_filter_sprintf + +* Mon Dec 18 2017 Mark Reynolds - 1.3.6.1-25 +- Bump version to 1.3.6.1-25 +- Resolves: Bug 1526928 - search with CoS attribute is getting slower after modifying/adding CosTemplate +- Resolves: Bug 1523505 - opened connection are hanging, no longer poll +- Resolves: Bug 1523507 - IPA server replication broken, after DS stop-start, due to changelog reset + * Fri Nov 10 2017 Mark Reynolds - 1.3.6.1-24 - Bump version to 1.3.6.1-24 - Resolves: Bug 1508978 - replicated MODRDN fails breaking replication