On Fri, Oct 22, 2010 at 5:01 PM, Andy Polyakov <ap...@openssl.org> wrote: >> 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. 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.
While Jan Pechanec suggests the *CALLING* program to work around with LD_PRELOAD, I don't believe a caller should be bother with bull shit details like this - they just want the stuff to work. I feel its the library's responsibility to get it right if they provide a shared object (or packagers if a distribution is providing the shared object). There are alternativesto Pechanec's suggestion to compile with ld's "-znodelete". See for example, Jonathan Whale's (GCC team member) at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46097#c16. Vladimir Simonov's advice at http://gcc.gnu.org/ml/gcc-help/2010-10/msg00256.html looks most promising, as it gives me the behavior I expect from a Windows DLL. And judging from your comment below, you expect it also: Have you tried to add -fvisibility=hidden to "g++ -g -c static.cpp -o static.o" ? As I remember gcc 4.1.x had -fvisibility=default by default. Newer gcc has -fvisibility=hidden. Really it is very good thing to have -fvisibility=hidden as default (specified explicitly in command line), especially for shared libraries. >> Since OpenSSL is a C library, a packager could be doing something with >> side effects. Or if there are globals and an Uninitialize function, >> the function might be whacking data that's still in use. >> >> 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. I was appalled - its an absolutely horrible choices in rules. Here's the most twisted part: constructors don't run multiple times on the same object - only the destructors!!! > Well, unless second process was created > with vfork (but vfork should/may be used only for immediate exec) or > object was created in MAP_SHARED or shmat-ed memory (in which case > destruction should be controlled by reference counter and not by library > unload). If either is case, then it's plain wrong and should be fixed. I > mean it's plain wrong to use vfork or objects in explicitly shared > memory in such way. I have to plead ignorance here. >> The interactions described above are specified in the Linux ABI, >> and result in a One Definition Rule (ODR) violation. > At present neither of openssl shared libraries have destructor. Though > I'm considering adding destructor to address above mentioned #2325... A. If you do add it, hide it in case OpenSSL's libs are loaded with RTLD_GLOBAL. See the comment at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46097#c16 and comment's to Jan's work arounds. These sum up my feelings on the ABI and the One Defintion Rule: "I think the problem here is that the rule is f**k'd up. I would argue that many folks probably know about the rule. But how many know about it because they got bit in the ass by it versus RTFM'ing the manual in their spare time?" - http://gcc.gnu.org/ml/gcc-help/2010-10/msg00270.html "RTFM and and ODR are great - until the attacker causes SELinux (or other important sub system) to crash due to this 'documented feature'. Shared data segments are evil and should not be the default." - http://gcc.gnu.org/ml/gcc-help/2010-10/msg00297.html "Am I the only guy under the impression that a Microsoft platform can suffer from Insecure Library Loading, while the Linux platform can suffer from Insecure Library Unloading due to ABI, ODR, and RTLD_GLOBAL?" - http://gcc.gnu.org/ml/gcc-help/2010-10/msg00297.html ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org