Hi, I'm sorry if this has all been discussed extensively before.  A
brief search for "DLL hell" in the archives turns up disappointingly
(and surprisingly) little.  I do see a thread with messages from my
erstwhile colleagues at Sun/Oracle, so I know it's been discussed,
e.g., here: http://www.mail-archive.com/openssl-dev@openssl.org/msg27453.html
.  Recent developments, like Android's failure to properly initialize
OpenSSL's PRNG make me think it's time to table (in the British sense)
the issue once more.

To summarize the rest of this long post (please forgive me):

    There should be no need for run-time, global initialization of
OpenSSL (or any sub-system of it) by applications.  Moreover, any
existing functions for such initialization should become no-ops or do
their work just once, and in a thread-safe way.  As much configuration
of threading and other system libraries should be done at build-time
as possible; as little should be done at run-time as possible.  Even
for special-purpose OSes.


OpenSSL requires too much explicit and global run-time initialization
of it by applications in ways that preclude (or at least used to and
still might cause problems for) multiple distinct callers of OpenSSL
in the same process.  And yet the layered software systems we've built
over the past decade result in just that happening.  Typical examples
include: applications that use TLS and Kerberos, PAM applications
(each module might need to use OpenSSL, and so might the application),
systems running without nscd (the name service switch modules may need
OpenSSL, and so might the app), and so on.

Are there best practices for dealing with this other than "don't do
that"?  (We *really* can't not do that: horse, barn door, and all
that.)

More to the point: why are there *any* initialization requirements at
all?  I can understand the need for it on some embedded systems, but
on modern general-purpose operating systems there should always be:

 - a single threading library to depend on for locking and which includes:

 - a way to perform one-time initialization (e.g., POSIX's
pthread_once(), Win32's  InitOnceExecuteOnce());

 - a decent source of entropy (but even if you must gather some on
your own, measuring jitter or what have you, one-time initialization
should suffice).

I realize that in the past there have been a multiplicity of threading
libraries (e.g., Solaris' native vs. POSIX threads, Linux's
LinuxThreads vs. NPTL).  But in practice these have either been
unified or one has been deprecated -- for the latter case you could
have OpenSSL build options for special cases, but the OpenSSL
distributed by distros should be linked with the standard/dominant
thread library.  I also realize that on special-purpose systems the
builder of OpenSSL may have to provide a thread library one way or
another, but even then doing so at build-time is easier than at
run-time.

Another source of DLL hell besides multiple initializations in one
process has been multiple dependents in one process dependning on
different versions of OpenSSL that are not ABI compatible with each
other.  There's less that OpenSSL can do about this (besides the
obvious "be ABI backwards-compatible going forward"), but distros can
do some things, like use -B direct (Solaris) or versioned symbols
(Linux), and this can be documented.

(To be fair there are still problems with multiple instances of a
library in a process, on POSIX systems anyways, because of things like
POSIX file locking being insane (I'm referring to the
drop-locks-on-first-close nonsense), so that two libraries (of similar
or different pedigree -- doesn't matter) using POSIX file locking to
synchronize access to a shared file will end up stepping on each
other's toes if they run in the same process concurrently.  But by and
large ensuring that accidental interposition (see previous paragraph)
doesn't happen should suffice for many cases.  In any case, OpenSSL
thankfully appears not to use POSIX file locking for anything, thank
goodness.)

Note the self-contradicting text in the FAQ:

"
* Is OpenSSL thread-safe?

Yes (with limitations: an SSL connection may not concurrently be used
by multiple threads).  On Windows and many Unix systems, OpenSSL
automatically uses the multi-threaded versions of the standard
libraries.  If your platform is not one of these, consult the INSTALL
file.

Multi-threaded applications must provide two callback functions to
OpenSSL by calling CRYPTO_set_locking_callback() and
CRYPTO_set_id_callback(), for all versions of OpenSSL up to and
including 0.9.8[abc...]. As of version 1.0.0, CRYPTO_set_id_callback()
and associated APIs are deprecated by CRYPTO_THREADID_set_callback()
and friends. This is described in the threads(3) manpage.
"

Huh?  Which is it?  Must apps call CRYPTO_THREADID_set_callback() even
though "[o]n Windows and many Unix systems, OpenSSL automatically uses
the multi-threaded versions of the standard libraries"?  Why?  One
would think that the "multi-threaded versions of the standard
libraries" on such OSes would provide all that OpenSSL needs.  I don't
get it.

I'll note that this:

int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
        {
        if (threadid_callback)
                return 0;
        threadid_callback = func;
        return 1;
        }

is not terribly thread-safe.  In practice any threads racing to call
this will (hopefully) be setting callbacks that produce the same
results anyways so that nothing bad should ever happen.  But this
really gets to the above points: more build-time / less run-time
configuration would make it easier to use OpenSSL in safe ways.

Also, CRYPTO_THREADID_current() seems to have a reasonable default
when CRYPTO_THREADID_set_callback() has not been called.  That seems
to contradict part of the above FAQ text.

Is the FAQ wrong?  The manpage does describe the sane default
behavior.  It'd be better to document that there is no need to call it
at all on the relevant OSes.

Finally, what can I do to help?  What fixes might be welcomed?  Would
patches to automatically initialize the PRNG on first use (and so on)
be welcomed?  Would patches to the docs/FAQ indicating that
applications should NOT call the thread callback setting functions be
welcomed?  Would patches making those functions no-ops (when the build
system finds/is to use standard ones) be welcomed?

Nico
--
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to