[gnutls-devel] [TLS] multiple clients in one process (was: Re: Deployment ... Re: This working group has failed)
Nico Williams
nico at cryptonector.com
Sun Dec 1 03:03:14 CET 2013
On Sat, Nov 30, 2013 at 2:58 AM, Nikos Mavrogiannopoulos
<nmav at gnutls.org> wrote:
> On Fri, 2013-11-29 at 18:03 -0600, Nico Williams wrote:
>> It is not safe to use PKCS#11 on the child-side of fork() without
>> [...]
>
> I was referring to his issue. As far as I understood he didn't use PKCS
> #11 at all, so there should be no breakage. When ones uses PKCS #11 in
> gnutls he is (currently) required to call gnutls_pkcs11_reinit() on a
> fork.
Remember, we're talking about layered software. This might be a
process using PAM and loading multiple PAMs that use GnuTLS, so: which
one of them should reinit GnuTLS? No, the library *must*
self-[re-]initialize. Always. Period. Full stop. There must be no
question of some caller being first to initialize, there must be no
way for two callers to step on each others' toes by re-initializing
the library and destroying the other caller's state.
Yes, nothing should fork() and try to use a non-async-signal-safe
interface on the child-side of the fork. That does give a library an
excuse to have undefined fork-safety. But it's much, much better to
have well-defined fork-safety. It's OK to lose access to all
objects/whatever on the child-side of fork(), and it's even OK to leak
them (since the data structures in question may not be in a consistent
state, the library may not be able to walk them, and free() is not
async-signal-safe). It'd even be better to abort() if called on the
child-side of fork() than to have undefined behavior -- after all,
callers of fork() are not supposed to call async-signal-unsafe code.
The key is to have deterministic and *noticeable* behavior.
The recipe is simple:
- use a InitOnceInitialize/pthread_once interface to initialize once as needed
(don't require that the caller initialize the library)
- use a pthread_atfork() child-side handler to reinitialize all
global state (all locks, ...), leaking all of it OR to set a flag,
then abort() if called with this flag set
Nico
--
More information about the Gnutls-devel
mailing list