mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Use custom isc_mem based allocator for OpenSSL
The OpenSSL library provides a way to replace the default allocator with user supplied allocator (malloc, realloc, and free). Create a memory context specifically for OpenSSL to allow tracking the memory usage that has originated from within OpenSSL. This will provide a separate memory context for OpenSSL to track the allocations and when shutting down the application it will check that all OpenSSL allocations were returned to the allocator.
This commit is contained in:
@@ -204,7 +204,6 @@ libisc_la_SOURCES = \
|
|||||||
time.c \
|
time.c \
|
||||||
timer.c \
|
timer.c \
|
||||||
tls.c \
|
tls.c \
|
||||||
tls_p.h \
|
|
||||||
tm.c \
|
tm.c \
|
||||||
trampoline.c \
|
trampoline.c \
|
||||||
trampoline_p.h \
|
trampoline_p.h \
|
||||||
|
@@ -562,3 +562,12 @@ isc_tlsctx_cache_find(
|
|||||||
* 'pstore' still might get initialised as there is one to many
|
* 'pstore' still might get initialised as there is one to many
|
||||||
* relation between stores and contexts.
|
* relation between stores and contexts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__tls_initialize(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__tls_shutdown(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__tls_setdestroycheck(bool check);
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#include "mem_p.h"
|
#include "mem_p.h"
|
||||||
#include "mutex_p.h"
|
#include "mutex_p.h"
|
||||||
#include "os_p.h"
|
#include "os_p.h"
|
||||||
#include "tls_p.h"
|
|
||||||
#include "trampoline_p.h"
|
#include "trampoline_p.h"
|
||||||
|
|
||||||
#ifndef ISC_CONSTRUCTOR
|
#ifndef ISC_CONSTRUCTOR
|
||||||
|
151
lib/isc/tls.c
151
lib/isc/tls.c
@@ -37,6 +37,7 @@
|
|||||||
#include <isc/ht.h>
|
#include <isc/ht.h>
|
||||||
#include <isc/log.h>
|
#include <isc/log.h>
|
||||||
#include <isc/magic.h>
|
#include <isc/magic.h>
|
||||||
|
#include <isc/mem.h>
|
||||||
#include <isc/mutex.h>
|
#include <isc/mutex.h>
|
||||||
#include <isc/mutexblock.h>
|
#include <isc/mutexblock.h>
|
||||||
#include <isc/once.h>
|
#include <isc/once.h>
|
||||||
@@ -49,15 +50,11 @@
|
|||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
#include "openssl_shim.h"
|
#include "openssl_shim.h"
|
||||||
#include "tls_p.h"
|
|
||||||
|
|
||||||
#define COMMON_SSL_OPTIONS \
|
#define COMMON_SSL_OPTIONS \
|
||||||
(SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
|
(SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
|
||||||
|
|
||||||
static isc_once_t init_once = ISC_ONCE_INIT;
|
static isc_mem_t *isc__tls_mctx = NULL;
|
||||||
static isc_once_t shut_once = ISC_ONCE_INIT;
|
|
||||||
static atomic_bool init_done = false;
|
|
||||||
static atomic_bool shut_done = false;
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
static isc_mutex_t *locks = NULL;
|
static isc_mutex_t *locks = NULL;
|
||||||
@@ -80,26 +77,116 @@ isc__tls_set_thread_id(CRYPTO_THREADID *id) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER)
|
||||||
|
/*
|
||||||
|
* This was crippled with LibreSSL, so just skip it:
|
||||||
|
* https://cvsweb.openbsd.org/src/lib/libcrypto/Attic/mem.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ISC_MEM_TRACKLINES
|
||||||
|
/*
|
||||||
|
* We use the internal isc__mem API here, so we can pass the file and line
|
||||||
|
* arguments passed from OpenSSL >= 1.1.0 to our memory functions for better
|
||||||
|
* tracking of the OpenSSL allocations. Without this, we would always just see
|
||||||
|
* isc__tls_{malloc,realloc,free} in the tracking output, but with this in place
|
||||||
|
* we get to see the places in the OpenSSL code where the allocations happen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void *
|
||||||
|
isc__tls_malloc_ex(size_t size, const char *file, int line) {
|
||||||
|
return (isc__mem_allocate(isc__tls_mctx, size, file,
|
||||||
|
(unsigned int)line));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
isc__tls_realloc_ex(void *ptr, size_t size, const char *file, int line) {
|
||||||
|
return (isc__mem_reallocate(isc__tls_mctx, ptr, size, file,
|
||||||
|
(unsigned int)line));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_initialize(void) {
|
isc__tls_free_ex(void *ptr, const char *file, int line) {
|
||||||
REQUIRE(!atomic_load(&init_done));
|
if (ptr == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isc__mem_free(isc__tls_mctx, ptr, file, (unsigned int)line);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
|
||||||
|
static void *
|
||||||
|
isc__tls_malloc_ex(size_t size, const char *file, int line) {
|
||||||
|
UNUSED(file);
|
||||||
|
UNUSED(line);
|
||||||
|
return (isc_mem_allocate(isc__tls_mctx, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
isc__tls_realloc_ex(void *ptr, size_t size, const char *file, int line) {
|
||||||
|
UNUSED(file);
|
||||||
|
UNUSED(line);
|
||||||
|
return (isc_mem_reallocate(isc__tls_mctx, ptr, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isc__tls_free_ex(void *ptr, const char *file, int line) {
|
||||||
|
UNUSED(file);
|
||||||
|
UNUSED(line);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isc__mem_free(isc__tls_mctx, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ISC_MEM_TRACKLINES */
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
static void
|
||||||
|
isc__tls_free(void *ptr) {
|
||||||
|
isc__tls_free_ex(ptr, __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__tls_initialize(void) {
|
||||||
|
isc_mem_create(&isc__tls_mctx);
|
||||||
|
isc_mem_setname(isc__tls_mctx, "OpenSSL");
|
||||||
|
isc_mem_setdestroycheck(isc__tls_mctx, false);
|
||||||
|
|
||||||
|
#if !defined(LIBRESSL_VERSION_NUMBER)
|
||||||
|
/*
|
||||||
|
* CRYPTO_set_mem_(_ex)_functions() returns 1 on success or 0 on
|
||||||
|
* failure, which means OpenSSL already allocated some memory. There's
|
||||||
|
* nothing we can do about it.
|
||||||
|
*/
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
(void)CRYPTO_set_mem_functions(isc__tls_malloc_ex, isc__tls_realloc_ex,
|
||||||
|
isc__tls_free_ex);
|
||||||
|
#else
|
||||||
|
(void)CRYPTO_set_mem_ex_functions(isc__tls_malloc_ex,
|
||||||
|
isc__tls_realloc_ex, isc__tls_free);
|
||||||
|
#endif
|
||||||
|
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
RUNTIME_CHECK(OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
|
uint64_t opts = OPENSSL_INIT_ENGINE_ALL_BUILTIN |
|
||||||
OPENSSL_INIT_LOAD_CONFIG,
|
OPENSSL_INIT_LOAD_CONFIG;
|
||||||
NULL) == 1);
|
#if defined(OPENSSL_INIT_NO_ATEXIT)
|
||||||
|
/*
|
||||||
|
* We call OPENSSL_cleanup() manually, in a correct order, thus disable
|
||||||
|
* the automatic atexit() handler.
|
||||||
|
*/
|
||||||
|
opts |= OPENSSL_INIT_NO_ATEXIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RUNTIME_CHECK(OPENSSL_init_ssl(opts, NULL) == 1);
|
||||||
#else
|
#else
|
||||||
nlocks = CRYPTO_num_locks();
|
nlocks = CRYPTO_num_locks();
|
||||||
/*
|
locks = isc_mem_get(isc__tls_mctx, nlocks * sizeof(locks[0]));
|
||||||
* We can't use isc_mem API here, because it's called too
|
memset(locks, 0, nlocks * sizeof(locks[0]));
|
||||||
* early and when the isc_mem_debugging flags are changed
|
|
||||||
* later.
|
|
||||||
*
|
|
||||||
* Actually, since this is a single allocation at library load
|
|
||||||
* and deallocation at library unload, using the standard
|
|
||||||
* allocator without the tracking is fine for this purpose.
|
|
||||||
*/
|
|
||||||
locks = calloc(nlocks, sizeof(locks[0]));
|
|
||||||
isc_mutexblock_init(locks, nlocks);
|
isc_mutexblock_init(locks, nlocks);
|
||||||
CRYPTO_set_locking_callback(isc__tls_lock_callback);
|
CRYPTO_set_locking_callback(isc__tls_lock_callback);
|
||||||
CRYPTO_THREADID_set_callback(isc__tls_set_thread_id);
|
CRYPTO_THREADID_set_callback(isc__tls_set_thread_id);
|
||||||
@@ -127,22 +214,10 @@ tls_initialize(void) {
|
|||||||
"cannot be initialized (see the `PRNG not "
|
"cannot be initialized (see the `PRNG not "
|
||||||
"seeded' message in the OpenSSL FAQ)");
|
"seeded' message in the OpenSSL FAQ)");
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_compare_exchange_enforced(&init_done, &(bool){ false }, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__tls_initialize(void) {
|
isc__tls_shutdown(void) {
|
||||||
isc_result_t result = isc_once_do(&init_once, tls_initialize);
|
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
|
||||||
REQUIRE(atomic_load(&init_done));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tls_shutdown(void) {
|
|
||||||
REQUIRE(atomic_load(&init_done));
|
|
||||||
REQUIRE(!atomic_load(&shut_done));
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
OPENSSL_cleanup();
|
OPENSSL_cleanup();
|
||||||
#else
|
#else
|
||||||
@@ -161,19 +236,17 @@ tls_shutdown(void) {
|
|||||||
|
|
||||||
if (locks != NULL) {
|
if (locks != NULL) {
|
||||||
isc_mutexblock_destroy(locks, nlocks);
|
isc_mutexblock_destroy(locks, nlocks);
|
||||||
free(locks);
|
isc_mem_put(isc__tls_mctx, locks, nlocks * sizeof(locks[0]));
|
||||||
locks = NULL;
|
locks = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
atomic_compare_exchange_enforced(&shut_done, &(bool){ false }, true);
|
isc_mem_destroy(&isc__tls_mctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__tls_shutdown(void) {
|
isc__tls_setdestroycheck(bool check) {
|
||||||
isc_result_t result = isc_once_do(&shut_once, tls_shutdown);
|
isc_mem_setdestroycheck(isc__tls_mctx, check);
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
|
||||||
REQUIRE(atomic_load(&shut_done));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*
|
|
||||||
* See the COPYRIGHT file distributed with this work for additional
|
|
||||||
* information regarding copyright ownership.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
void
|
|
||||||
isc__tls_initialize(void);
|
|
||||||
|
|
||||||
void
|
|
||||||
isc__tls_shutdown(void);
|
|
Reference in New Issue
Block a user