[gnutls-devel] [TLS] multiple clients in one process (was: Re: Deployment ... Re: This working group has failed)

Andy Lutomirski luto at amacapital.net
Thu Nov 28 01:18:39 CET 2013

On Wed, Nov 27, 2013 at 4:16 PM, Nico Williams <nico at cryptonector.com> wrote:
> On Wed, Nov 27, 2013 at 5:58 PM, Andy Lutomirski <luto at amacapital.net> wrote:
>> [stripped tls at ietf.org]
>> On Wed, Nov 27, 2013 at 3:54 PM, Nico Williams <nico at cryptonector.com> wrote:
>>> All of this is off-topic for this list.  I'll post a reply anyways, and
>>> I apologize to the list.
>>> On Tue, Nov 19, 2013 at 10:24:03PM -0800, Andy Lutomirski wrote:
>>>>                     [...].  gnutls_global_init is documented as being
>>>> unsafe if called from multiple threads, which seems silly.
>>> Initialization is not thread-safe in OpenSSL either.  This is a terrible
>>> thing.  It *can* be made thread-safe, so there's no excuse for it not
>>> being thread-safe.
>>>> GnuTLS has gnutls_pkcs11_init, which is rather impolite -- it
>>>> manipulates global state, and it sometimes causes things to
>>>> malfunction after forking.  [...]
>>> PKCS#11 is by definition fork-unsafe (see the PKCS#11 docs).
>>> Any API dealing with "tokens" (in the PKCS#11 sense) is bound to be
>>> fork-unsafe for at least open sessions/objects on tokens that require
>>> authentication (PIN).  That's because any library using file descriptors
>>> where offset is not a relevant concept will necessarily be fork-unsafe
>>> by default.  And: any stateful cryptography library (e.g., an
>>> implementation of TLS) will tend to be fork-unsafe (imagine a process
>>> trying to use a TLS connection on both sides of a fork()!).
>> I agree with all of this, except that I don't think that GnuTLS has
>> any business even trying to use PKCS11 unless something explicitly
>> requests it.  I've had all kinds of problems with libvmime causing
>> GnuTLS to start interfacing with some mysterious GNOME PKCS11 token,
>> when I don't want any of the above.  It breaks fork for no good
>> reason.  (I'm not even trying to do crypto in the child -- I just want
>> to avoid getting all kinds of random errors.)
> The thing to do is to arrange to re-initialize on the child-side of
> fork().  I don't mean lock-everything in a pre-fork() atfork handler,
> then unlock everything in the parent and child handlers -- that's not
> safe.  I mean: reset all global state in the PKCS#11 implementation on
> the child-side of fork() in a child atfork handler -- yes, this means
> leaking memory (and its contents), but hopefully the child will
> immediately _exit() or exec*().  Also, O_CLOEXEC should be safely set
> on all file descriptors used by the PKCS#11 implementation.

The thing to do for whom?  I think that GnuTLS should stay far away
from anything PKCS11 by default until something actually requests a
key from a PKCS11 token.  Again, I'm not trying to use PKCS11.

>>> Of course, that's all rather POSIX-specific, but the problem is inherent
>>> to any fork()-like interface.  Use posix_spawn() or similar, then you
>>> won't have to worry about fork-safety at all.  Long ago I used to think
>>> fork+exec superior to spawn since spawn was easy to implement in terms
>>> of fork+exec, but in truth fork() is a dangerous and difficult-to-use
>>> interface -- the only safe things to do on the child side of fork() are:
>>> async-signal-safe things, culminating in _exit() or exec*() ASAP.
>> Except that glibc's posix_spawn is screwed up wrt atfork.  There are
>> some bugs open about it.
> That's because it needs a real vfork() (or at least to tell fork() not
> to run atfork handlers when called from posix_spawn()).

It has a real vfork.  It just opts not to use it.


More information about the Gnutls-devel mailing list