dlz_bind9: Fix the named crash on reloading named
authorAmitay Isaacs <amitay@gmail.com>
Wed, 23 May 2012 01:52:16 +0000 (11:52 +1000)
committerAmitay Isaacs <amitay@gmail.com>
Wed, 23 May 2012 23:42:24 +0000 (09:42 +1000)
When reloading zones, named first creates new zone instance and then shuts down
the old instance. Since ldb layer, keeps the same LDB open, talloc_free() on samdb
handle, causes talloc "access after use" error.

This patch keeps only single context (dlz_bind9_data) and uses reference counting
to decide when to actually free the context. Since samdb handle is reused, use
talloc_unlink() instead of talloc_free() on samdb handle.

source4/dns_server/dlz_bind9.c

index 224f242b879d0b5da7024e6247c87bdd1dabab4a..4be7aaea83eb4c61ef32699b376694f7358bfae3 100644 (file)
@@ -65,6 +65,8 @@ struct dlz_bind9_data {
        dns_dlz_writeablezone_t *writeable_zone;
 };
 
+static struct dlz_bind9_data *dlz_bind9_state = NULL;
+static int dlz_bind9_state_ref_count = 0;
 
 static const char *zone_prefixes[] = {
        "CN=MicrosoftDNS,DC=DomainDnsZones",
@@ -570,6 +572,12 @@ _PUBLIC_ isc_result_t dlz_create(const char *dlzname,
        struct ldb_dn *dn;
        NTSTATUS nt_status;
 
+       if (dlz_bind9_state != NULL) {
+               *dbdata = dlz_bind9_state;
+               dlz_bind9_state_ref_count++;
+               return ISC_R_SUCCESS;
+       }
+
        state = talloc_zero(NULL, struct dlz_bind9_data);
        if (state == NULL) {
                return ISC_R_NOMEMORY;
@@ -664,6 +672,8 @@ _PUBLIC_ isc_result_t dlz_create(const char *dlzname,
        state->auth_context->generate_session_info_pac = b9_generate_session_info_pac;
 
        *dbdata = state;
+       dlz_bind9_state = state;
+       dlz_bind9_state_ref_count++;
 
        return ISC_R_SUCCESS;
 
@@ -679,7 +689,13 @@ _PUBLIC_ void dlz_destroy(void *dbdata)
 {
        struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
        state->log(ISC_LOG_INFO, "samba_dlz: shutting down");
-       talloc_free(state);
+
+       dlz_bind9_state_ref_count--;
+       if (dlz_bind9_state_ref_count == 0) {
+               talloc_unlink(state, state->samdb);
+               talloc_free(state);
+               dlz_bind9_state = NULL;
+       }
 }