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]

Reply via email to