diff options
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r-- | src/libstrongswan/utils/identification.c | 13 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 132 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils/atomics.h | 10 |
3 files changed, 127 insertions, 28 deletions
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 56298a60f..36c0c9daa 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -1222,6 +1222,7 @@ static private_identification_t* create_from_string_with_prefix_type(char *str) { "dns:", ID_FQDN }, { "asn1dn:", ID_DER_ASN1_DN }, { "asn1gn:", ID_DER_ASN1_GN }, + { "xmppaddr:", ID_DER_ASN1_GN }, { "keyid:", ID_KEY_ID }, }; private_identification_t *this; @@ -1233,6 +1234,7 @@ static private_identification_t* create_from_string_with_prefix_type(char *str) { this = identification_create(prefixes[i].type); str += strlen(prefixes[i].str); + if (*str == '#') { this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL); @@ -1241,6 +1243,17 @@ static private_identification_t* create_from_string_with_prefix_type(char *str) { this->encoded = chunk_clone(chunk_from_str(str)); } + + if (prefixes[i].type == ID_DER_ASN1_GN && + strcasepfx(prefixes[i].str, "xmppaddr:")) + { + this->encoded = asn1_wrap(ASN1_CONTEXT_C_0, "mm", + asn1_build_known_oid(OID_XMPP_ADDR), + asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_wrap(ASN1_UTF8STRING, "m", + this->encoded))); + } + return this; } } diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index b873e12a8..efeb0f478 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Tobias Brunner + * Copyright (C) 2013-2018 Tobias Brunner * Copyright (C) 2006-2013 Martin Willi * HSR Hochschule fuer Technik Rapperswil * @@ -162,7 +162,12 @@ static spinlock_t *lock; /** * Is leak detection currently enabled? */ -static bool enabled = FALSE; +static bool enabled; + +/** + * Whether to report calls to free() with memory not allocated by us + */ +static bool ignore_unknown; /** * Is leak detection disabled for the current thread? @@ -609,6 +614,11 @@ static char *whitelist[] = { /* FHH IMCs and IMVs */ "TNC_IMC_NotifyConnectionChange", "TNC_IMV_NotifyConnectionChange", + /* Botan */ + "botan_public_key_load", + "botan_privkey_create_ecdsa", + "botan_privkey_create_ecdh", + "botan_privkey_load_ecdh", }; /** @@ -883,7 +893,7 @@ HOOK(void, free, void *ptr) return; } /* allow freeing of NULL */ - if (ptr == NULL) + if (!ptr) { return; } @@ -894,21 +904,47 @@ HOOK(void, free, void *ptr) if (hdr->magic != MEMORY_HEADER_MAGIC || tail->magic != MEMORY_TAIL_MAGIC) { + bool bt = TRUE; + + /* check if memory appears to be allocated by our hooks */ if (has_hdr(hdr)) { - /* memory was allocated by our hooks but is corrupted */ fprintf(stderr, "freeing corrupted memory (%p): " - "header magic 0x%x, tail magic 0x%x:\n", - ptr, hdr->magic, tail->magic); + "%u bytes, header magic 0x%x, tail magic 0x%x:\n", + ptr, hdr->bytes, hdr->magic, tail->magic); + remove_hdr(hdr); + + if (hdr->magic == MEMORY_HEADER_MAGIC) + { /* only access the old backtrace if header magic is valid */ + hdr->backtrace->log(hdr->backtrace, stderr, TRUE); + hdr->backtrace->destroy(hdr->backtrace); + } + else + { + fprintf(stderr, " header magic invalid, ignore backtrace of " + "allocation\n"); + } } else { - /* memory was not allocated by our hooks */ - fprintf(stderr, "freeing invalid memory (%p)\n", ptr); + /* just free this block of unknown memory */ + hdr = ptr; + + if (ignore_unknown) + { + bt = FALSE; + } + else + { + fprintf(stderr, "freeing unknown memory (%p):\n", ptr); + } + } + if (bt) + { + backtrace = backtrace_create(2); + backtrace->log(backtrace, stderr, TRUE); + backtrace->destroy(backtrace); } - backtrace = backtrace_create(2); - backtrace->log(backtrace, stderr, TRUE); - backtrace->destroy(backtrace); } else { @@ -916,12 +952,11 @@ HOOK(void, free, void *ptr) hdr->backtrace->destroy(hdr->backtrace); - /* clear MAGIC, set mem to something remarkable */ + /* set mem to something remarkable */ memset(hdr, MEMORY_FREE_PATTERN, sizeof(memory_header_t) + hdr->bytes + sizeof(memory_tail_t)); - - real_free(hdr); } + real_free(hdr); enable_thread(before); } @@ -933,19 +968,19 @@ HOOK(void*, realloc, void *old, size_t bytes) memory_header_t *hdr; memory_tail_t *tail; backtrace_t *backtrace; - bool before; + bool before, have_backtrace = TRUE; if (!enabled || thread_disabled->get(thread_disabled)) { return real_realloc(old, bytes); } /* allow reallocation of NULL */ - if (old == NULL) + if (!old) { return malloc(bytes); } /* handle zero size as a free() */ - if (bytes == 0) + if (!bytes) { free(old); return NULL; @@ -954,22 +989,64 @@ HOOK(void*, realloc, void *old, size_t bytes) hdr = old - sizeof(memory_header_t); tail = old + hdr->bytes; - remove_hdr(hdr); - + before = enable_thread(FALSE); if (hdr->magic != MEMORY_HEADER_MAGIC || tail->magic != MEMORY_TAIL_MAGIC) { - fprintf(stderr, "reallocating invalid memory (%p):\n" - "header magic 0x%x:\n", old, hdr->magic); - backtrace = backtrace_create(2); - backtrace->log(backtrace, stderr, TRUE); - backtrace->destroy(backtrace); + bool bt = TRUE; + + /* check if memory appears to be allocated by our hooks */ + if (has_hdr(hdr)) + { + fprintf(stderr, "reallocating corrupted memory (%p, %u bytes): " + "%zu bytes, header magic 0x%x, tail magic 0x%x:\n", + old, hdr->bytes, bytes, hdr->magic, tail->magic); + remove_hdr(hdr); + + if (hdr->magic == MEMORY_HEADER_MAGIC) + { /* only access header fields (backtrace, bytes) if header magic + * is still valid */ + hdr->backtrace->log(hdr->backtrace, stderr, TRUE); + memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); + } + else + { + fprintf(stderr, " header magic invalid, ignore backtrace of " + "allocation\n"); + have_backtrace = FALSE; + hdr->magic = MEMORY_HEADER_MAGIC; + } + } + else + { + /* adopt this block of unknown memory */ + hdr = old; + have_backtrace = FALSE; + + if (ignore_unknown) + { + bt = FALSE; + } + else + { + fprintf(stderr, "reallocating unknown memory (%p): %zu bytes:\n", + old, bytes); + } + } + if (bt) + { + backtrace = backtrace_create(2); + backtrace->log(backtrace, stderr, TRUE); + backtrace->destroy(backtrace); + } } else { + remove_hdr(hdr); /* clear tail magic, allocate, set tail magic */ memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); } + hdr = real_realloc(hdr, sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); tail = ((void*)hdr) + bytes + sizeof(memory_header_t); @@ -978,8 +1055,10 @@ HOOK(void*, realloc, void *old, size_t bytes) /* update statistics */ hdr->bytes = bytes; - before = enable_thread(FALSE); - hdr->backtrace->destroy(hdr->backtrace); + if (have_backtrace) + { + hdr->backtrace->destroy(hdr->backtrace); + } hdr->backtrace = backtrace_create(2); enable_thread(before); @@ -1022,6 +1101,7 @@ leak_detective_t *leak_detective_create() free(this); return NULL; } + ignore_unknown = getenv("LEAK_DETECTIVE_IGNORE_UNKNOWN") != NULL; lock = spinlock_create(); thread_disabled = thread_value_create(NULL); diff --git a/src/libstrongswan/utils/utils/atomics.h b/src/libstrongswan/utils/utils/atomics.h index a973b1adc..c23b361ec 100644 --- a/src/libstrongswan/utils/utils/atomics.h +++ b/src/libstrongswan/utils/utils/atomics.h @@ -27,8 +27,14 @@ */ typedef u_int refcount_t; +/* use __atomic* built-ins with clang, if available (note that clang also + * defines __GNUC__, however only claims to be GCC 4.2) */ +#if defined(__clang__) +# if __has_builtin(__atomic_add_fetch) +# define HAVE_GCC_ATOMIC_OPERATIONS +# endif /* use __atomic* built-ins with GCC 4.7 and newer */ -#ifdef __GNUC__ +#elif defined(__GNUC__) # if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)) # define HAVE_GCC_ATOMIC_OPERATIONS # endif @@ -47,7 +53,7 @@ typedef u_int refcount_t; #define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL)) #define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED) -#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \ +#define _cas_impl(ptr, oldval, newval) ({ typeof(*ptr) _old = oldval; \ __atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); }) #define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval) |