Skip to content

Commit ba21419

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

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

modules/ssl/mod_ssl.c

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ 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
5152
/* Will be set to true if mod_ssl is built statically into httpd. */
5253
static int modssl_running_statically = 0;
5354
#endif
@@ -328,7 +329,7 @@ static const command_rec ssl_config_cmds[] = {
328329
AP_END_CMD
329330
};
330331

331-
#ifdef NEED_MANUAL_OPENSSL_INIT
332+
#if !USE_OPENSSL_INIT_SSL
332333
static int modssl_is_prelinked(void)
333334
{
334335
apr_size_t i = 0;
@@ -340,11 +341,26 @@ static int modssl_is_prelinked(void)
340341
}
341342
return 0;
342343
}
344+
#endif /* !USE_OPENSSL_INIT_SSL */
343345

344-
/* Termination below is for legacy Openssl versions v1.0.x and
345-
* older. */
346+
/* Cleanup what's done in ssl_hook_pre_config() */
346347
static apr_status_t ssl_cleanup_pre_config(void *data)
347348
{
349+
#if USE_OPENSSL_INIT_SSL
350+
/* Nothing to do when an OpenSSL builtin atexit() handler is registered,
351+
* but with OPENSSL_INIT_NO_ATEXIT we want to call OPENSSL_cleanup() when
352+
* exiting only, not on restart/reload or the next OPENSSL_init_ssl() in
353+
* pre_config would not (re)initialize anything.
354+
*/
355+
#ifdef OPENSSL_INIT_NO_ATEXIT
356+
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING)
357+
OPENSSL_cleanup();
358+
#endif
359+
360+
#else /* USE_OPENSSL_INIT_SSL */
361+
/* Termination below is for legacy Openssl versions v1.0.x and
362+
* older. */
363+
348364
/* Corresponds to OBJ_create()s */
349365
OBJ_cleanup();
350366
/* Corresponds to OPENSSL_load_builtin_modules() */
@@ -367,7 +383,7 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
367383
#else
368384
ERR_remove_state(0);
369385
#endif
370-
#endif
386+
#endif /* USE_OPENSSL_INIT_SSL */
371387

372388
/* Don't call ERR_free_strings in earlier versions, ERR_load_*_strings only
373389
* actually loaded the error strings once per process due to static
@@ -391,9 +407,10 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
391407
* CRYPTO_mem_leaks_fp(stderr);
392408
*/
393409

410+
#endif /* USE_OPENSSL_INIT_SSL */
411+
394412
return APR_SUCCESS;
395413
}
396-
#endif /* NEED_MANUAL_OPENSSL_INIT */
397414

398415
static int ssl_hook_pre_config(apr_pool_t *pconf,
399416
apr_pool_t *plog,
@@ -403,17 +420,26 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
403420
ssl_running_on_valgrind = RUNNING_ON_VALGRIND;
404421
#endif
405422

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.
423+
#if USE_OPENSSL_INIT_SSL
424+
/* Openssl v1.1+ handles all initialisation and termination automatically,
425+
* apart from hints as to how we want to use the library. We tell openssl
426+
* we want to include engine support.
409427
*
410-
* We tell openssl we want to include engine support.
428+
* Openssl v3.0+ allows to disable builtin atexit() handler for termination
429+
* by using OPENSSL_INIT_NO_ATEXIT, which we use because atexit() handlers
430+
* are inherited by children processes and can cause issues/crashes when
431+
* run multiple times. This allows to call OPENSSL_cleanup() manually from
432+
* ssl_cleanup_pre_config() when (and only when) httpd is exiting.
411433
*/
412-
OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
434+
OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN
435+
#ifdef OPENSSL_INIT_NO_ATEXIT
436+
| OPENSSL_INIT_NO_ATEXIT
437+
#endif
438+
, NULL);
413439

414-
#else
440+
#else /* USE_OPENSSL_INIT_SSL */
415441
/* Configuration below is for legacy versions Openssl v1.0 and
416-
* older.
442+
* older, "manual" initialization and cleanup are required.
417443
*/
418444
modssl_running_statically = modssl_is_prelinked();
419445

@@ -433,7 +459,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
433459
#endif
434460
OpenSSL_add_all_algorithms();
435461
OPENSSL_load_builtin_modules();
436-
#endif /* NEED_MANUAL_OPENSSL_INIT */
462+
#endif /* USE_OPENSSL_INIT_SSL */
437463

438464
if (OBJ_txt2nid("id-on-dnsSRV") == NID_undef) {
439465
(void)OBJ_create("1.3.6.1.5.5.7.8.7", "id-on-dnsSRV",
@@ -444,13 +470,11 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
444470
ERR_clear_error();
445471

446472

447-
#ifdef NEED_MANUAL_OPENSSL_INIT
448473
/*
449474
* Let us cleanup the ssl library when the module is unloaded
450475
*/
451476
apr_pool_cleanup_register(pconf, NULL, ssl_cleanup_pre_config,
452-
apr_pool_cleanup_null);
453-
#endif
477+
apr_pool_cleanup_null);
454478

455479
/* Register to handle mod_status status page generation */
456480
ssl_scache_status_register(pconf);

0 commit comments

Comments
 (0)