[openssl-dev] Self-initialization of locking/threadid callbacks and auto-detection of features

Nico Williams nico at cryptonector.com
Mon Jun 15 16:02:36 UTC 2015


On Thu, Jun 11, 2015 at 10:41:58AM +0200, Florian Weimer wrote:
> Detecting things in libcrypto is very difficult on GNU/Linux due to the
> way dynamic linking works.

Details?

> On GNU/Linux, you should try very hard to avoid linking -lpthread and
> restrict yourself to the pthreads API subset which is available without
> -lpthread.  If something is missing, we (as in glibc upstream) can move
> additional functionality from libpthread to libc.

[My apologies for making this so long.  There's a lot to say about this.]

Perhaps OpenSSL should have several configuration flavors for Linux
then.  If you want to statically link a non-threaded program with
OpenSSL, then you should use the libpthread static link meant for it.

Or perhaps we could have the OpenSSL static link archives assume
non-threaded processes (callers must initialize lock callbacks) but the
shared objects link with -lpthread and assume a threaded environment.
(This means supporting two "process models" instead of *four*.)

In any case, use of OpenSSL by *libraries* (which is rather common, I
gather; certainly in the case of Kerberos implementations) is currently
a disaster waiting to happen, and sometimes a disaster that strikes.

A workaound for libraries may be to use a private copy (as if by static
linking) of OpenSSL with distinct SONAME/symbols and initialize that
copy properly.  This is generally safe (we've tried it) but also a bit
troublesome.  On the plus side this means that ABI incompatibilities
betwee OpenSSL releases become a non-issue.

Or indeed, libpthread should move into libc (which I gather would take a
long time and is beyond what we can do here).

For background, Solaris moved libpthread into libc around 2004, during
S10 development.  Solaris 10 also dropped support for static linking of
libc and dropped all static linking archives from OS/Net (but not ld(1)
support for static linking).  Before that S9 had basically four process
models: statically-linked,-not-threaded, statically-linked,-threaded,
dynamically-linked,-not-threaded, dynamically-linked,-threaded.  This
was awful in a great many ways (think of statically-linked, single-
threaded programs that dlopen()ed dynamically-linked threaded objects
via, e.g., the name service switch).  Dropping support for statically
linking with libc greatly simplified a lot of things.  Linux ought to do
the same, but there's a fascination with static linking in Linux land...

...Static linking wouldn't be so bad if it had dependency tracking and
symbol resolution semantics closer to dynamic linking.  The startup
times for one process would be awesome, though startup times for entire
systems would be awful.  (Solaris 10 boot times improved significantly
when static linking was dropped.)  And then there's the need for PIE to
still get any benefit from ASLR, which then applies to the whole
program, not each library.  (Can gdb debug PIE nowadays?  Last I checked
it could not.)

(Moving the implementation of a library to another requires support for
shared object "filters", at least on Solaris, so that dynamically-linked
dependents of libpthread and such will find the symbols they need there,
though the RTLD knows to go look in the object they moved to.  We say
that libpthread is a filter of libc because only the pthread-related
symbols of libc appear in libpthread.  IIUC the Linux RTLD does not
support filters.)

(I help maintain an open source project that distributes a statically-
linked executable as that's a great way to avoid needing packaging and
installers.  So perhaps I shouldn't speak so ill of static linking.  But
then, static linking truly is awful.)

> Linking -lpthread has a real performance hit for unthreaded
> applications, so core libraries should avoid it.

It shouldn't.  Having *four* process models is an enormous burden on
developers, especially libc and libpthread developers, but this burden
leaks into other system libraries, such as OpenSSL's.  Solaris saw a
sizeable net performance win in switching to a single process model
(dynamically-linked, threaded) (for many processes there's just one
thread, natch).

> If you have received advice to the contrary, your source of advice is
> wrong. :-)

Or maybe I'm rather spoiled by Solaris and am continually suprised to
see that developers on Linux must struggle with problems that Solaris
tackled a decade ago.

In any case, the initialization problems when OpenSSL is used by
*libraries* are simply unacceptable.  Either that means that OpenSSL
cannot and must not be used by libraries, or we must find a solution
that doesn't suck.  See above and let me know which paths, if any, are
the way forward; I offered several, and there may be more that I have
not seen.

Nico
-- 


More information about the openssl-dev mailing list