>>> I helped Wei Dai wrestle with a similar problem for Crypto++. We wrote >>> a couple audit tools, one of which is attached. I just completed an >>> audit on my /usr/lib. The following OpenSSL modules crashed during a >>> simple load/unload cycle: >>> >>> /usr/lib/debug/lib/libcrypto.so.0.9.8 >>> /usr/lib/debug/lib/libssl.so.0.9.8 >>> /usr/lib/debug/usr/lib/ssl/engines/lib4758cca.so >>> /usr/lib/debug/usr/lib/ssl/engines/libaep.so >>> /usr/lib/debug/usr/lib/ssl/engines/libatalla.so >>> /usr/lib/debug/usr/lib/ssl/engines/libcapi.so >>> /usr/lib/debug/usr/lib/ssl/engines/libchil.so >> Have you seen ticket #2325? Google for "[openssl.org #2325]"... Even >> though it discusses libssl, engines should be affected too... Is it >> possible that you experience same problem? In which order were libraries >> loaded when IsKnownToCrash was composed? Can you confirm that >> loading/unloading libcrypto *alone* is problematic? In such case can you >> provide stack backtrace? > Oh yea - that's it.
??? There were four questions, was "oh yeah" answer to every one of them? It can't be, because some of the questions couldn't be answered with just "yes". So I have to assume something. It seems natural to assume that it was answer to the first question, i.e. "is it possible that you experience same problem?" But the whole point behind that question was actually to have you realize that it's completely different situation from what you describe... You describe that an object instantiated by a shared library is destroyed several times in violation with ODR, because it's *allegedly* shared between multiple processes. Problem with #2325 is that libcrypto.so can crash because libssl.so[!] (or engine) is loaded/unloaded and loaded again at alternative address. And the problem there is that there is no finalization code in libssl.so[!] (nor any engine), or one can say that there is no destructor. > But the problem is much more maniacal because the > ABI brought the mess on (apparently at version 3). The GCC team > (though helpful) generally had the attitude, its documented behavor - > RTFM to change the behavior. You must be referring to GCC C++ ABI. How does it apply to OpenSSL? >>> In the Crypto++ case, there was a global object with a destructor that >>> would destroy an object during unload. No problem, since that's what >>> destructors do. However, if you want to catch a C++ exception across a >>> module boundary, you need RTLD_GLOBAL. But RTLD_GLOBAL causes the >>> runtime linker-loader to fold non-private symbols into one. So if two >>> processes have the shared library open, both processes will call the >>> dtor on the same object. The first will exit cleanly, the second >>> process will continue to run [for a while] with a bad object. >> ??? Objects belonging to different processes reside in disjoint address >> spaces, and destructor executed in one process context has no effect on >> corresponding object in another. > Coming from the Windows world, that what I thought also. That behavior > exists if an OpenSSL lib is opened with RTLD_LOCAL. > > But be careful of RTLD_GLOBAL and any global variables you might have. > To satisfy the ABI: they might be separate processes, but they operate > on a single *shared* data item to because of the One Definition Rule > (ODR). See http://gcc.gnu.org/ml/gcc-help/2010-10/msg00260.html. Can you provide a reference that ABI would require data objects [instantiated in a shared library] to be shared among multiple processes? > I was appalled - its an absolutely horrible choices in rules. Is it possible that everything that might have happened can be explained without stating that RTLD_GLOBAL implies inter-process data sharing? And don't just say "oh no", think about it for an hour... Simplest scenario is two copies of the same shared library loaded to single process [which doesn't even have to be multi-threaded]... More refined scenario is two completely different shared libraries that shared a name of a data object... > Here's > the most twisted part: constructors don't run multiple times on the > same object - only the destructors!!! I can't confirm this... At least not in simplest scenario. I mean if I have two identical shared libraries, let's say class foo { public: foo() { cout<<"constructor"<<endl; } ~foo() { cout<<"destructor"<<endl; } } bar; and bring them in to process address space, "constructor" is printed twice, so as "destructor"... A. ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List [email protected] Automated List Manager [email protected]
