diff options
author | Tobias Brunner <tobias@strongswan.org> | 2016-09-20 16:26:58 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2016-09-20 16:26:58 +0200 |
commit | f654324e5e317ad6b9290c73aec113fc4001b362 (patch) | |
tree | 9563d3259b054385a7fb7fa32c853e1290bde404 /src | |
parent | d344474b3d44d55b488140a2d9cd7f8f28ed514e (diff) | |
parent | 95f9fa82d5574f08dca873941115ce60c8f14341 (diff) | |
download | strongswan-f654324e5e317ad6b9290c73aec113fc4001b362.tar.bz2 strongswan-f654324e5e317ad6b9290c73aec113fc4001b362.tar.xz |
Merge branch 'testing-leak-detective'
Test scenarios now fail if any leaks are detected by the leak detective.
Several leaks found this way have been fixed.
Diffstat (limited to 'src')
-rw-r--r-- | src/charon-tkm/build_common.gpr | 3 | ||||
-rw-r--r-- | src/charon-tkm/src/charon-tkm.c | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/dnscert/dnscert_cred.c | 19 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_peap/eap_peap_server.c | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/ipseckey/ipseckey_cred.c | 28 | ||||
-rw-r--r-- | src/libstrongswan/library.c | 46 | ||||
-rw-r--r-- | src/libstrongswan/plugins/unbound/unbound_response.c | 3 | ||||
-rw-r--r-- | src/libstrongswan/plugins/unbound/unbound_rr.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 24 | ||||
-rw-r--r-- | src/pool/pool.c | 59 |
10 files changed, 132 insertions, 59 deletions
diff --git a/src/charon-tkm/build_common.gpr b/src/charon-tkm/build_common.gpr index 102f6b7a2..459519564 100644 --- a/src/charon-tkm/build_common.gpr +++ b/src/charon-tkm/build_common.gpr @@ -9,7 +9,8 @@ project Build_Common is C_Compiler_Switches := ("-W", "-Wall", - "-Wno-unused-parameter"); + "-Wno-unused-parameter", + "-g"); Ada_Compiler_Switches := ("-gnatwale", "-gnatygAdISuxo", "-gnata", diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 13352e55a..3136b8083 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -373,6 +373,7 @@ int main(int argc, char *argv[]) run(); unlink_pidfile(); + free(pidfile_name); status = 0; charon->bus->remove_listener(charon->bus, &listener->listener); listener->destroy(listener); @@ -382,7 +383,7 @@ int main(int argc, char *argv[]) deinit: destroy_dh_mapping(); libcharon_deinit(); - library_deinit(); tkm_deinit(); + library_deinit(); return status; } diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.c b/src/libcharon/plugins/dnscert/dnscert_cred.c index 790252682..d32794c99 100644 --- a/src/libcharon/plugins/dnscert/dnscert_cred.c +++ b/src/libcharon/plugins/dnscert/dnscert_cred.c @@ -70,6 +70,8 @@ typedef struct { enumerator_t *inner; /** response of the DNS resolver which contains the CERTs */ resolver_response_t *response; + /** most recently enumerated certificate */ + certificate_t *cert; } cert_enumerator_t; METHOD(enumerator_t, cert_enumerator_enumerate, bool, @@ -101,17 +103,17 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool, /* Try to parse PEM certificate container. Both x509 and PGP should * presumably come as PEM encoded certs. */ certificate = cur_crt->get_certificate(cur_crt); - *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY, - BUILD_BLOB_PEM, certificate, - BUILD_END); - if (*cert == NULL) + DESTROY_IF(this->cert); + this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY, + BUILD_BLOB_PEM, certificate, + BUILD_END); + cur_crt->destroy(cur_crt); + if (!this->cert) { - DBG1(DBG_CFG, " unable to parse certificate, skipping", - cur_crt->get_cert_type(cur_crt)); - cur_crt->destroy(cur_crt); + DBG1(DBG_CFG, " unable to parse certificate, skipping"); continue; } - cur_crt->destroy(cur_crt); + *cert = this->cert; return TRUE; } return FALSE; @@ -120,6 +122,7 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool, METHOD(enumerator_t, cert_enumerator_destroy, void, cert_enumerator_t *this) { + DESTROY_IF(this->cert); this->inner->destroy(this->inner); this->response->destroy(this->response); free(this); diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c index 7f8348e06..d51d0d090 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_server.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c @@ -211,7 +211,7 @@ METHOD(tls_application_t, process, status_t, { DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]", eap_code_short_names, code); - + in->destroy(in); /* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */ return (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) ? start_phase2_tnc(this) : FAILED; @@ -250,6 +250,7 @@ METHOD(tls_application_t, process, status_t, { DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_IDENTITY); + in->destroy(in); return FAILED; } } @@ -258,6 +259,7 @@ METHOD(tls_application_t, process, status_t, { DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_IDENTITY); + in->destroy(in); return FAILED; } diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c index 6c041ce26..ff50d8a17 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_cred.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c @@ -57,6 +57,8 @@ typedef struct { time_t notAfter; /* identity to which the IPSECKEY belongs */ identification_t *identity; + /** most recently enumerated certificate */ + certificate_t *cert; } cert_enumerator_t; METHOD(enumerator_t, cert_enumerator_enumerate, bool, @@ -91,28 +93,27 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool, public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_DNSKEY, key, BUILD_END); + cur_ipseckey->destroy(cur_ipseckey); if (!public) { DBG1(DBG_CFG, " failed to create public key from IPSECKEY"); - cur_ipseckey->destroy(cur_ipseckey); continue; } - - *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, - CERT_TRUSTED_PUBKEY, - BUILD_PUBLIC_KEY, public, - BUILD_SUBJECT, this->identity, - BUILD_NOT_BEFORE_TIME, this->notBefore, - BUILD_NOT_AFTER_TIME, this->notAfter, - BUILD_END); - if (*cert == NULL) + DESTROY_IF(this->cert); + this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_TRUSTED_PUBKEY, + BUILD_PUBLIC_KEY, public, + BUILD_SUBJECT, this->identity, + BUILD_NOT_BEFORE_TIME, this->notBefore, + BUILD_NOT_AFTER_TIME, this->notAfter, + BUILD_END); + public->destroy(public); + if (!this->cert) { DBG1(DBG_CFG, " failed to create certificate from IPSECKEY"); - cur_ipseckey->destroy(cur_ipseckey); - public->destroy(public); continue; } - cur_ipseckey->destroy(cur_ipseckey); + *cert = this->cert; return TRUE; } return FALSE; @@ -121,6 +122,7 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool, METHOD(enumerator_t, cert_enumerator_destroy, void, cert_enumerator_t *this) { + DESTROY_IF(this->cert); this->inner->destroy(this->inner); this->response->destroy(this->response); free(this); diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c index e130b93ee..f694509d1 100644 --- a/src/libstrongswan/library.c +++ b/src/libstrongswan/library.c @@ -55,6 +55,13 @@ struct private_library_t { */ bool integrity_failed; +#ifdef LEAK_DETECTIVE + /** + * Where to write leak detective output to + */ + FILE *ld_out; +#endif + /** * Number of times we have been initialized */ @@ -95,32 +102,34 @@ library_t *lib = NULL; /** * Default leak report callback */ -static void report_leaks(void *user, int count, size_t bytes, - backtrace_t *bt, bool detailed) +CALLBACK(report_leaks, void, + private_library_t *this, int count, size_t bytes, backtrace_t *bt, + bool detailed) { - fprintf(stderr, "%zu bytes total, %d allocations, %zu bytes average:\n", + fprintf(this->ld_out, "%zu bytes total, %d allocations, %zu bytes average:\n", bytes, count, bytes / count); - bt->log(bt, stderr, detailed); + bt->log(bt, this->ld_out, detailed); } /** * Default leak report summary callback */ -static void sum_leaks(void* user, int count, size_t bytes, int whitelisted) +CALLBACK(sum_leaks, void, + private_library_t *this, int count, size_t bytes, int whitelisted) { switch (count) { case 0: - fprintf(stderr, "No leaks detected"); + fprintf(this->ld_out, "No leaks detected"); break; case 1: - fprintf(stderr, "One leak detected"); + fprintf(this->ld_out, "One leak detected"); break; default: - fprintf(stderr, "%d leaks detected, %zu bytes", count, bytes); + fprintf(this->ld_out, "%d leaks detected, %zu bytes", count, bytes); break; } - fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted); + fprintf(this->ld_out, ", %d suppressed by whitelist\n", whitelisted); } #endif /* LEAK_DETECTIVE */ @@ -166,12 +175,18 @@ void library_deinit() this->public.integrity->destroy(this->public.integrity); } +#ifdef LEAK_DETECTIVE if (lib->leak_detective) { lib->leak_detective->report(lib->leak_detective, detailed); lib->leak_detective->destroy(lib->leak_detective); lib->leak_detective = NULL; } + if (this->ld_out && this->ld_out != stderr) + { + fclose(this->ld_out); + } +#endif /* LEAK_DETECTIVE */ backtrace_deinit(); arrays_deinit(); @@ -301,11 +316,22 @@ bool library_init(char *settings, const char *namespace) backtrace_init(); #ifdef LEAK_DETECTIVE + { + FILE *out = NULL; + char *log; + + log = getenv("LEAK_DETECTIVE_LOG"); + if (log) + { + out = fopen(log, "a"); + } + this->ld_out = out ?: stderr; + } lib->leak_detective = leak_detective_create(); if (lib->leak_detective) { lib->leak_detective->set_report_cb(lib->leak_detective, - report_leaks, sum_leaks, NULL); + report_leaks, sum_leaks, this); } #endif /* LEAK_DETECTIVE */ diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c index 6f6c25e89..950df344c 100644 --- a/src/libstrongswan/plugins/unbound/unbound_response.c +++ b/src/libstrongswan/plugins/unbound/unbound_response.c @@ -189,7 +189,7 @@ unbound_response_t *unbound_response_create_frm_libub_response( */ rr_list = linked_list_create(); - orig_rr_list = ldns_pkt_get_section_clone(dns_pkt, LDNS_SECTION_ANSWER); + orig_rr_list = ldns_pkt_answer(dns_pkt); orig_rr_count = ldns_rr_list_rr_count(orig_rr_list); for (i = 0; i < orig_rr_count; i++) @@ -253,7 +253,6 @@ unbound_response_t *unbound_response_create_frm_libub_response( this->rr_set = rr_set_create(rr_list, rrsig_list); ldns_pkt_free(dns_pkt); - ldns_rr_list_free(orig_rr_list); } return &this->public; } diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c index fc69eed00..91b5cdb33 100644 --- a/src/libstrongswan/plugins/unbound/unbound_rr.c +++ b/src/libstrongswan/plugins/unbound/unbound_rr.c @@ -154,11 +154,13 @@ unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr) if (status != LDNS_STATUS_OK) { DBG1(DBG_LIB, "failed to get the RDATA field of a DNS RR"); + ldns_buffer_free(buf); _destroy(this); return NULL; } this->rdata = ldns_buffer_export(buf); + ldns_buffer_free(buf); return &this->public; } diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index d0f646c31..ad67c0380 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -494,7 +494,7 @@ static bool register_hooks() * List of functions using static allocation buffers or should be suppressed * otherwise on leak report. */ -char *whitelist[] = { +static char *whitelist[] = { /* backtraces, including own */ "backtrace_create", "strerror_safe", @@ -551,6 +551,15 @@ char *whitelist[] = { "xmlInitParserCtxt", /* libcurl */ "Curl_client_write", + /* libsoup */ + "soup_message_headers_append", + "soup_message_headers_clear", + "soup_message_headers_get_list", + "soup_message_headers_get_one", + "soup_session_abort", + "soup_session_get_type", + /* libldap */ + "ldap_int_initialize", /* ClearSilver */ "nerr_init", /* libgcrypt */ @@ -575,17 +584,28 @@ char *whitelist[] = { /* libapr */ "apr_pool_create_ex", /* glib */ + "g_output_stream_write", + "g_resolver_lookup_by_name", + "g_signal_connect_data", + "g_socket_connection_factory_lookup_type", "g_type_init_with_debug_flags", "g_type_register_static", "g_type_class_ref", "g_type_create_instance", "g_type_add_interface_static", "g_type_interface_add_prerequisite", - "g_socket_connection_factory_lookup_type", + "g_private_set", + "g_queue_pop_tail", /* libgpg */ "gpg_err_init", /* gnutls */ "gnutls_global_init", + /* Ada runtime */ + "system__tasking__initialize", + "system__tasking__initialization__abort_defer", + "system__tasking__stages__create_task", + /* in case external threads call into our code */ + "thread_current_id", }; /** diff --git a/src/pool/pool.c b/src/pool/pool.c index 265974860..cd9fb6293 100644 --- a/src/pool/pool.c +++ b/src/pool/pool.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2011-2016 Tobias Brunner * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * 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 @@ -23,6 +24,7 @@ #include <utils/debug.h> #include <library.h> +#include <collections/array.h> #include <networking/host.h> #include <utils/identification.h> #include <attributes/attributes.h> @@ -586,11 +588,11 @@ static void resize(char *name, host_t *end) /** * create the lease query using the filter string */ -static enumerator_t *create_lease_query(char *filter) +static enumerator_t *create_lease_query(char *filter, array_t **to_free) { enumerator_t *query; - identification_t *id = NULL; - host_t *addr = NULL; + chunk_t id_chunk = chunk_empty, addr_chunk = chunk_empty; + id_type_t id_type = 0; u_int tstamp = 0; bool online = FALSE, valid = FALSE, expired = FALSE; char *value, *pos, *pool = NULL; @@ -635,18 +637,29 @@ static enumerator_t *create_lease_query(char *filter) case FIL_ID: if (value) { + identification_t *id; + id = identification_create_from_string(value); + id_type = id->get_type(id); + id_chunk = chunk_clone(id->get_encoding(id)); + array_insert_create(to_free, ARRAY_TAIL, id_chunk.ptr); + id->destroy(id); } break; case FIL_ADDR: if (value) { + host_t *addr; + addr = host_create_from_string(value, 0); - } - if (!addr) - { - fprintf(stderr, "invalid 'addr' in filter string.\n"); - exit(EXIT_FAILURE); + if (!addr) + { + fprintf(stderr, "invalid 'addr' in filter string.\n"); + exit(EXIT_FAILURE); + } + addr_chunk = chunk_clone(addr->get_address(addr)); + array_insert_create(to_free, ARRAY_TAIL, addr_chunk.ptr); + addr->destroy(addr); } break; case FIL_TSTAMP: @@ -710,11 +723,11 @@ static enumerator_t *create_lease_query(char *filter) "AND (? OR (identities.type = ? AND identities.data = ?)) " "AND (? OR address = ?)", DB_INT, pool == NULL, DB_TEXT, pool, - DB_INT, id == NULL, - DB_INT, id ? id->get_type(id) : 0, - DB_BLOB, id ? id->get_encoding(id) : chunk_empty, - DB_INT, addr == NULL, - DB_BLOB, addr ? addr->get_address(addr) : chunk_empty, + DB_INT, !id_chunk.ptr, + DB_INT, id_type, + DB_BLOB, id_chunk, + DB_INT, !addr_chunk.ptr, + DB_BLOB, addr_chunk, DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp, DB_INT, !valid, DB_INT, time(NULL), DB_INT, !expired, DB_INT, time(NULL), @@ -722,14 +735,13 @@ static enumerator_t *create_lease_query(char *filter) /* union */ DB_INT, !(valid || expired), DB_INT, pool == NULL, DB_TEXT, pool, - DB_INT, id == NULL, - DB_INT, id ? id->get_type(id) : 0, - DB_BLOB, id ? id->get_encoding(id) : chunk_empty, - DB_INT, addr == NULL, - DB_BLOB, addr ? addr->get_address(addr) : chunk_empty, + DB_INT, !id_chunk.ptr, + DB_INT, id_type, + DB_BLOB, id_chunk, + DB_INT, !addr_chunk.ptr, + DB_BLOB, addr_chunk, /* res */ DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT); - /* id and addr leak but we can't destroy them until query is destroyed. */ return query; } @@ -739,6 +751,7 @@ static enumerator_t *create_lease_query(char *filter) static void leases(char *filter, bool utc) { enumerator_t *query; + array_t *to_free = NULL; chunk_t address_chunk, identity_chunk; int identity_type; char *name; @@ -748,7 +761,7 @@ static void leases(char *filter, bool utc) identification_t *identity; bool found = FALSE; - query = create_lease_query(filter); + query = create_lease_query(filter, &to_free); if (!query) { fprintf(stderr, "querying leases failed.\n"); @@ -809,6 +822,10 @@ static void leases(char *filter, bool utc) identity->destroy(identity); } query->destroy(query); + if (to_free) + { + array_destroy_function(to_free, (void*)free, NULL); + } if (!found) { fprintf(stderr, "no matching leases found.\n"); |