Hello, Fix race condition in addrdataset() during SOA serial update.
https://fedorahosted.org/bind-dyndb-ldap/ticket/89 -- Petr^2 Spacek
From 5e8bc8f943345d8d92900474905288939958dcd8 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Fri, 7 Sep 2012 13:01:57 +0200 Subject: [PATCH] Fix race condition in addrdataset() during SOA serial update. https://fedorahosted.org/bind-dyndb-ldap/ticket/89 Signed-off-by: Petr Spacek <pspa...@redhat.com> --- src/ldap_driver.c | 44 ++++++++++++++++++++++++++++++++++---------- src/ldap_helper.c | 4 ++-- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/ldap_driver.c b/src/ldap_driver.c index 2cdde30cdad9544d530475f5cf4a0b8275a56f03..3a802238028145d35390f6a8d00f156bfdf8e7a1 100644 --- a/src/ldap_driver.c +++ b/src/ldap_driver.c @@ -936,6 +936,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatalist_t diff; isc_result_t result; isc_boolean_t rdatalist_exists = ISC_FALSE; + isc_boolean_t soa_simulated_write = ISC_FALSE; UNUSED(now); UNUSED(db); @@ -975,42 +976,65 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, rdatalist_removedups(found_rdlist, new_rdlist, ISC_FALSE, &diff); - if ((options & DNS_DBADD_MERGE) != 0) + if ((options & DNS_DBADD_MERGE) == 0 && + (rdatalist_length(&diff) != 0)) { + CLEANUP_WITH(DNS_R_NOTEXACT); + } else { free_rdatalist(ldapdb->common.mctx, &diff); - else if (rdatalist_length(&diff) != 0) { - free_rdatalist(ldapdb->common.mctx, &diff); - result = DNS_R_NOTEXACT; - goto cleanup; } } else { /* Replace existing rdataset */ free_rdatalist(ldapdb->common.mctx, found_rdlist); } } - CHECK(write_to_ldap(&ldapdbnode->owner, ldapdb->ldap_inst, new_rdlist)); + /* HACK: SOA addition will never fail with DNS_R_UNCHANGED. + * This prevents warning from BIND's diff_apply(), it has too strict + * checks for us. + * + * Reason: There is a race condition between SOA serial update + * from BIND's update_action() and our persistent search watcher, because + * they don't know about each other. + * BIND's update_action() changes data with first addrdataset() call and + * then changes serial with second addrdataset() call. + * It can lead to empty diff if persistent search watcher + * incremented serial in meanwhile. + */ + if (HEAD(new_rdlist->rdata) == NULL) { + if (rdlist->type == dns_rdatatype_soa) + soa_simulated_write = ISC_TRUE; + else + CLEANUP_WITH(DNS_R_UNCHANGED); + } else { + CHECK(write_to_ldap(&ldapdbnode->owner, ldapdb->ldap_inst, new_rdlist)); + } + if (addedrdataset != NULL) { - result = dns_rdatalist_tordataset(new_rdlist, addedrdataset); - /* Use strong condition here, returns only SUCCESS */ - INSIST(result == ISC_R_SUCCESS); + if (soa_simulated_write) { + dns_rdataset_clone(rdataset, addedrdataset); + } else { + result = dns_rdatalist_tordataset(new_rdlist, addedrdataset); + /* Use strong condition here, returns only SUCCESS */ + INSIST(result == ISC_R_SUCCESS); + } } if (rdatalist_exists) { ISC_LIST_APPENDLIST(found_rdlist->rdata, new_rdlist->rdata, link); SAFE_MEM_PUT_PTR(ldapdb->common.mctx, new_rdlist); } else APPEND(ldapdbnode->rdatalist, new_rdlist, link); - return ISC_R_SUCCESS; cleanup: if (new_rdlist != NULL) { free_rdatalist(ldapdb->common.mctx, new_rdlist); SAFE_MEM_PUT_PTR(ldapdb->common.mctx, new_rdlist); } + free_rdatalist(ldapdb->common.mctx, &diff); return result; } diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 3241ffe486205fa03a6fd1a0a14edf1245c5c4aa..e636a84b35d0bcdc8573c6e7146f38ee21a42076 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -2973,10 +2973,10 @@ soa_serial_increment(isc_mem_t *mctx, ldap_instance_t *inst, /* put the new SOA to inst->cache and compare old and new serials */ CHECK(ldap_get_zone_serial(inst, zone_name, &new_serial)); - INSIST(isc_serial_gt(new_serial, old_serial) == ISC_TRUE); cleanup: - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS || + isc_serial_gt(new_serial, old_serial) != ISC_TRUE) log_error("SOA serial number incrementation failed in zone '%s'", str_buf(zone_dn)); -- 1.7.11.4
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel