OPENSSL_thread_stop() fiber local storage and questions
Matthew Ogilvie
mmogilvi4711+ssl at gmail.com
Fri Jan 19 01:32:52 UTC 2024
I work on portable applications that often link Open SSL statically,
so the "NOTE" in the man page about needing to call OPENSSL_thread_stop()
under certain conditions is probably relevant.
https://github.com/openssl/openssl/issues/6081
When researching this situation on Windows and how to organize an app
to do this, I found the following blog post that describes some
workarounds for this basic problem with thread local storage.
https://devblogs.microsoft.com/oldnewthing/20191011-00/?p=102989
The most interesting workaround is switching to using "fiber local
storage" instead of "thread local storage", but otherwise ignoring fibers.
https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-flsalloc
I found it through this stack overflow question, which mentions a
few more things, like Windows versions:
https://stackoverflow.com/questions/74735255/winapi-thread-local-storage-cleanup
-------
IDEA/QUESTION 1: This is probably not a short-term change, but in the
longer term, is there any chance Open SSL may switch to Windows fiber
local storage, thereby simplifying the most common cases where users
need to call OPENSSL_thread_stop()?
The biggest concern I can see is that I think this fiber local storage
idea only works on Windows Vista or later, which raises the question:
What is Open SSL's policy about supporting old versions of Windows
that Microsoft no longer supports (XP/2000)? (Perhaps it could
be a (pre-build) configure option, or auto-determined at runtime
using GetProcAddress()...)
Outside Open SSL, I'm not sure, but maybe an application could
use this to keep track of when to call OPENSSL_thread_stop()?
Although depending on the structure of the application, ensuring
each thread that might have allocated storage in Open SSL also
allocates an app-level FLS per-thread slot with FlsSetValue() could
be more difficult than just directly calling OPENSSL_thread_stop()
as each thread ends...
-------
QUESTION 2: When a thread is ending, is it necessary to
call OPENSSL_thread_stop_ex() for every allocated OSSL_LIB_CTX, or
is a single call to OPENSSL_thread_stop() sufficient?
The one man page for both functions has a "NOTE" section doesn't mention
OPENSSL_thread_stop_ex(), only OPENSSL_thread_stop(), and earlier
sections don't say anything about the apparent global nature
of the non-"ex" function:
In code, it looks like the "if (arg != NULL && curr->arg != arg)"
condition in the underlying init_thread_stop() function
(crypto/initthread.c) suggests that NULL is treated specially to free
up thread local storage related to everything (all OSSL_LIB_CTX's),
while non-NULL only cleans up the indicated OSSL_LIB_CTX? (But I'm not
familiar enough with how this code works to be confident of
this conclusion, or why exposing a cleanup-only-a-single-context
option in the public API is even useful.)
- Matthew Ogilvie
More information about the openssl-users
mailing list