Skip to content

Commit 9e49d49

Browse files
committed
mod_ssl: Use OPENSSL_INIT_NO_ATEXIT when available.
1 parent 0ba38c2 commit 9e49d49

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

modules/ssl/mod_ssl.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,15 @@ int ssl_running_on_valgrind = 0;
4242

4343
#if HAVE_OPENSSL_INIT_SSL || (OPENSSL_VERSION_NUMBER >= 0x10100000L && \
4444
!defined(LIBRESSL_VERSION_NUMBER))
45-
/* Openssl v1.1+ handles all termination automatically from
46-
* OPENSSL_init_ssl(). No manual initialization is required. */
45+
/* Openssl v1.1+ handles all initializations automatically from
46+
* OPENSSL_init_ssl(). */
47+
#define USE_OPENSSL_INIT_SSL 1
4748
#else
4849
/* For older OpenSSL releases, "manual" initialization and cleanup are
4950
* required. */
50-
#define NEED_MANUAL_OPENSSL_INIT
51+
#define USE_OPENSSL_INIT_SSL 0
52+
53+
#if !USE_OPENSSL_INIT_SSL
5154
/* Will be set to true if mod_ssl is built statically into httpd. */
5255
static int modssl_running_statically = 0;
5356
#endif
@@ -328,7 +331,7 @@ static const command_rec ssl_config_cmds[] = {
328331
AP_END_CMD
329332
};
330333

331-
#ifdef NEED_MANUAL_OPENSSL_INIT
334+
#if !USE_OPENSSL_INIT_SSL
332335
static int modssl_is_prelinked(void)
333336
{
334337
apr_size_t i = 0;
@@ -340,11 +343,26 @@ static int modssl_is_prelinked(void)
340343
}
341344
return 0;
342345
}
346+
#endif /* !USE_OPENSSL_INIT_SSL */
343347

344-
/* Termination below is for legacy Openssl versions v1.0.x and
345-
* older. */
348+
/* Cleanup what's done in ssl_hook_pre_config() */
346349
static apr_status_t ssl_cleanup_pre_config(void *data)
347350
{
351+
#if USE_OPENSSL_INIT_SSL
352+
/* Nothing to do when an OpenSSL builtin atexit() handler is registered,
353+
* but with OPENSSL_INIT_NO_ATEXIT we want to call OPENSSL_cleanup() when
354+
* exiting only, not on restart/reload or the next OPENSSL_init_ssl() in
355+
* pre_config would not (re)initialize anything.
356+
*/
357+
#ifdef OPENSSL_INIT_NO_ATEXIT
358+
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING)
359+
OPENSSL_cleanup();
360+
#endif
361+
362+
#else /* USE_OPENSSL_INIT_SSL */
363+
/* Termination below is for legacy Openssl versions v1.0.x and
364+
* older. */
365+
348366
/* Corresponds to OBJ_create()s */
349367
OBJ_cleanup();
350368
/* Corresponds to OPENSSL_load_builtin_modules() */
@@ -367,7 +385,7 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
367385
#else
368386
ERR_remove_state(0);
369387
#endif
370-
#endif
388+
#endif /* USE_OPENSSL_INIT_SSL */
371389

372390
/* Don't call ERR_free_strings in earlier versions, ERR_load_*_strings only
373391
* actually loaded the error strings once per process due to static
@@ -391,9 +409,10 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
391409
* CRYPTO_mem_leaks_fp(stderr);
392410
*/
393411

412+
#endif /* USE_OPENSSL_INIT_SSL */
413+
394414
return APR_SUCCESS;
395415
}
396-
#endif /* NEED_MANUAL_OPENSSL_INIT */
397416

398417
static int ssl_hook_pre_config(apr_pool_t *pconf,
399418
apr_pool_t *plog,
@@ -403,17 +422,26 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
403422
ssl_running_on_valgrind = RUNNING_ON_VALGRIND;
404423
#endif
405424

406-
#ifndef NEED_MANUAL_OPENSSL_INIT
407-
/* Openssl v1.1+ handles all initialisation automatically, apart
408-
* from hints as to how we want to use the library.
425+
#if USE_OPENSSL_INIT_SSL
426+
/* Openssl v1.1+ handles all initialisation and termination automatically,
427+
* apart from hints as to how we want to use the library. We tell openssl
428+
* we want to include engine support.
409429
*
410-
* We tell openssl we want to include engine support.
430+
* Openssl v3.0+ allows to disable builtin atexit() handler for termination
431+
* by using OPENSSL_INIT_NO_ATEXIT, which we use because atexit() handlers
432+
* are inherited by children processes and can cause issues/crashes when
433+
* run multiple times. This allows to call OPENSSL_cleanup() manually from
434+
* ssl_cleanup_pre_config() when (and only when) httpd is exiting.
411435
*/
412-
OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
436+
OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN
437+
#ifdef OPENSSL_INIT_NO_ATEXIT
438+
| OPENSSL_INIT_NO_ATEXIT
439+
#endif
440+
, NULL);
413441

414-
#else
442+
#else /* USE_OPENSSL_INIT_SSL */
415443
/* Configuration below is for legacy versions Openssl v1.0 and
416-
* older.
444+
* older, "manual" initialization and cleanup are required.
417445
*/
418446
modssl_running_statically = modssl_is_prelinked();
419447

@@ -433,7 +461,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
433461
#endif
434462
OpenSSL_add_all_algorithms();
435463
OPENSSL_load_builtin_modules();
436-
#endif /* NEED_MANUAL_OPENSSL_INIT */
464+
#endif /* USE_OPENSSL_INIT_SSL */
437465

438466
if (OBJ_txt2nid("id-on-dnsSRV") == NID_undef) {
439467
(void)OBJ_create("1.3.6.1.5.5.7.8.7", "id-on-dnsSRV",
@@ -444,13 +472,11 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
444472
ERR_clear_error();
445473

446474

447-
#ifdef NEED_MANUAL_OPENSSL_INIT
448475
/*
449476
* Let us cleanup the ssl library when the module is unloaded
450477
*/
451478
apr_pool_cleanup_register(pconf, NULL, ssl_cleanup_pre_config,
452-
apr_pool_cleanup_null);
453-
#endif
479+
apr_pool_cleanup_null);
454480

455481
/* Register to handle mod_status status page generation */
456482
ssl_scache_status_register(pconf);

0 commit comments

Comments
 (0)