#include "log.h"
#include "bio.h"
+#include <sys/mman.h>
#include <openssl/conf.h>
#include <openssl/provider.h>
#include <freeradius-devel/tls/engine.h>
#include <freeradius-devel/util/atexit.h>
#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/math.h>
+#include <freeradius-devel/util/syserror.h>
static uint32_t openssl_instance_count = 0;
return 0;
}
+#if OPENSSL_VERSION_NUMBER >= 0x30400000L
+static void *fr_openssl_stack_alloc(size_t *len)
+{
+ size_t page_size = (size_t)getpagesize();
+ void *stack;
+
+ /*
+ * OpenSSL uses 32K stacks by default
+ * Do that here, then add an extra page's worth of
+ * of memory at the end for poisoning.
+ */
+ size_t stack_size = ROUND_UP_POW2(32768, page_size); /* Ensure this is a multiple of our page size */
+ if (posix_memalign(&stack, page_size, stack_size + page_size) != 0) {
+ fr_tls_log(NULL, "Failed allocating OpenSSL stack: %s", fr_syserror(errno));
+ return NULL;
+ }
+
+ /*
+ * Catch reads and writes going off the end of the stack.
+ */
+ if (mprotect((uint8_t *)stack + stack_size, page_size, PROT_NONE) < 0) {
+ fr_tls_log(NULL, "Failed adding guard page to OpenSSL stack: %s", fr_syserror(errno));
+ free(stack);
+ return NULL;
+ }
+ *len = stack_size;
+
+ return stack;
+}
+
+static void fr_openssl_stack_free(void *stack)
+{
+ size_t page_size = (size_t)getpagesize();
+
+ /*
+ * Remove the guard page. If this failed, we can't continue
+ * as we'll have random protected memory chunks
+ */
+ if (unlikely(mprotect(stack, page_size, PROT_READ | PROT_WRITE) < 0)) {
+ fr_assert_msg(0, "Uprotecting OpenSSL stack memory failed, can't continue: %s", fr_syserror(errno));
+ fr_exit(1);
+ }
+ free(stack);
+}
+#endif
+
/** Add all the default ciphers and message digests to our context.
*
* This should be called exactly once from main, before reading the main config
return -1;
}
+ /*
+ * Setup custom memory allocators for allocating greenthread
+ * stacks, so we can add guard pages.
+ */
+#if OPENSSL_VERSION_NUMBER >= 0x30400000L
+ if (ASYNC_set_mem_functions(fr_openssl_stack_alloc, fr_openssl_stack_free) != 1) {
+ fr_tls_log(NULL, "Failed to set OpenSSL async stack allocation functions");
+ return -1;
+ }
+#endif
+
/*
* NO_ATEXIT has no effect if init is done after
* loading providers, and we need to control the