>>> 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]

Reply via email to