Mark Phalan wrote:
The threads(3) manpage states that to use OpenSSL in multi-threaded
applications then locking callback functions must be set otherwise
random crashes may occur.
This poses a challenge when using OpenSSL in a library which should be
MT safe. There is no safe way to set the locking callbacks from within
the library itself. The calling application may or may not be using
OpenSSL or may be linking against multiple libraries some of which may
be linked against OpenSSL. The application may not even be aware that it
will end up calling into OpenSSL code.
I agree this is a genuine concern.
Thing 1) It is one thing for OpenSSL to have multi-platform support by
delegating the locking mechanism with callbacks via abstraction. This
allows the library to be used with all major large platforms as well as
any tiny embedded platform (for which OpenSSL has not way in advance to
know or understand the locking mechanism on that platform). No one is
saying this is not a good and correct thing to do and such a thing shall
remain.
Thing 2) It is another thing not to provide a default implementation for
setting up those callback with a usable locking mechanism specific for
each platform it can be compiled for where one is known. It is not like
the WIN32 version is going to be used on Linux and the Linux on
Nokia-Symbian. This mechanism can have a common API symbol across all
platforms which will attempt to setup the locking mechanism in a
re-entrant multi-thread safe manner, it should also reference count the
setup mechanism so multiple users can load OpenSSL DSO and initialize it
independently in safety.
These two things are not mutually exclusive. I think there is some
common misconception that they are on the openssl-dev list.
--- THOUGHTS ON IMPLEMENTATION, SKIP IF BORED ---
On every large platform there is a default locking implementation that
can be used, there really are not too many options any more, on every
platform OpenSSL compiles for but does not know of such a lock mechanism
the API would error. Documentation would need to be produced about how
the OpenSSL library startup/shutdown would be implemented that conforms
to the re-entrant multi-thread safe requirements.
Maybe we should petition the binutils and ELF maintainers of open-source
platform about providing hooks in DSO for "on first load" and "on load"
and "on unload" and "on last unload", maybe such things already exist ?
Maybe this could be implemented as a single section with a control
word indicating a bitmask of which callbacks it is for followed by a
function pointer. Both items are of the platform native bit-width for
function pointers. The dynamic linker would then use this section if it
exists to fire callbacks. The use of the hook would be tagged in GCC
using __attribute(()) around symbols. Plenty of other criteria to add
should it be taken forward.
--- THOUGHTS ON IMPLEMENTATION, SKIP IF BORED ---
In this modern day with dlopen/GetProcAddress that dynamically loads
modules/DSOs/DLLs into executable which themselves can have compile time
dependencies causing additional DSOs/DLLs to loaded with them. The top
level application is no longer in control of proceedings the dynamic
linker is.
You are correct the application that needed to use OpenSSL doesn't know
it is the "first user" of OpenSSL in the process address space since
there is nothing provided within OpenSSL library API to arbitrate this
matter. If it could know it was the first user it could setup the
multi-threading callbacks accordingly, but again this all needs to be
arbitrated in a re-entrant thread-safe manner.
Not so long ago (~7 years) it was conceivable that OpenSSL developers
could say the controlling application needs to perform the arbitration
but this just isn't how people use dlopen/GetProcAddress these days,
rightly or wrongly.
I think that developing the OpenSSL API in this area will not limit or
change any existing behavior it will just ratify how to deal with these
new situations consistently.
Is it this use case there the OpenSSL's historic (archaic) view of the
world is wrong. The world has evolved and OpenSSL should do so too.
The only safe way to ensure that the OpenSSL code will be MT safe would
be for the OpenSSL library itself to set locking callbacks, however I
don't see any compile-time option to do that.
With the above two things implemented it would them be a step away from
a providing a compile time option. But the same thing can be achieved
on every platform is the API callback to set a default locking
implementation was consistent (since part of what I'm claiming here is
that new API call would be re-entrant multi-thread safe, i.e. bullet
proof and not requiring multiple threads to co-operate outside of OpenSSL).
Is there a reason I'm missing as to why this option isn't available?
It just is so (at this time).
Without this, the library can do its best to set the locking callbacks
when loaded if they are not set and then remove them when unloaded,
however this will always be inherently racy if there are other parts of
the process using OpenSSL.
I have had previous discussions in the list over better startup and
shutdown APIs/documentation for the OpenSSL library, I do think this is
an area that needs improvement. Those improvements don't need to
radically change how things are currently done. The matters brought up
here were loosely thought about then; but as time has passed my thoughts
on "the problem" have become much clearer to me.
Unfortunately at this time I can only provide input/guidance into how
such a thing could/should be done, not the man power.
Darryl
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]