On Thu, Aug 22, 2013 at 1:00 AM, Patrick Pelletier
<c...@funwithsoftware.org> wrote:
> On 8/21/13 8:55 AM, Nico Williams wrote:
>
>> OpenSSL should use pthread_atfork() and mix in more /dev/urandom into
>> its pool in the child-side of the fork(),  Only a child-side handler
>> is needed, FYI, unless there's locks to acquire and release, in which
>> case you also need a pre-fork and parent-side handlers, or unless
>> fork() is just a good excuse to add entropy to the pool on the parent
>> side anyways :)
>
>
> Yeah, it seems like a good excuse.  Actually, it probably makes more sense
> to only add entropy on the parent side, since the parent is likely to live
> longer, and there's a good chance the child is just going to exec() anyway,
> in which case adding entropy to it will have been for nothing.

The parent might be multi-threaded, leading to the risk that a thread
in the parent and the child will obtain the same PRNG outputs until
the parent thread that fork()ed completes the re-seeding.  This would
be bad, unless there's locking around the PRNG, in which case there'd
be no problem.  (Perhaps each thread should maintain its own PRNG,
seeded separately, to avoid the need for locking.)

> The downside with using pthread_atfork() is that it requires pthreads. Since
> you pointed out there are still non-threaded libcs (at least for static
> linking), that would be an issue.

That's OK.  If you want to build OpenSSL for static linking w/o
pthreads you should get to, just don't upgrade the process model to
threaded later on.  It'd be best to not support static,
single-threaded process models that can upgrade to multi-threaded, but
that may not be possible, in which case the right answer is to require
consumers to run in or upgrade to threaded process models.

Also, it's not a requirement that pthread_atfork() require -lpthread.
It's entirely possible (and on Solaris 10 and up, for example, it is
in fact so) that pthread_atfork() is in libc.

> Most other libraries I've seen handle this by saving the pid in a static
> variable, and then comparing the current pid to it.  This has the advantage
> of not needing pthreads, and also of only adding the entropy to the child if
> it is actually needed (i. e. it doesn't exec after fork).

Optimizing getpid() using pthread_atfork() is nice, though decent
getpid() implementations effectively do so anyways.

> The only thing that bothers me about doing the pid check is that in theory
> it could still fail, although it's a really unlikely case. Imagine a parent
> process that forks a child process.  The child doesn't generate any random
> numbers, so the reseed doesn't happen in the child.  The parent dies, and
> then the child forks a grandchild.  In an incredibly rare and unlucky case,
> the grandchild could have the same pid as the original parent, and then the
> grandchild wouldn't detect it had forked.

Right, it's best to re-seed on the child-side of fork().

If you are going to exec() anyways you should have used vfork(), or
better! you should have used posix_spawn() or equivalent.

Use of fork() presents many problems, not the least of which is a
performance problem in multi-threaded processes with very large heaps
and high page dirtying rates, such as Java programs.  vfork() helps to
some degree, but the correct and portable thing to do is spawn,
specifically posix_spawn(), which avoids all child-side-of-fork
re-initialization problems by definition.

Nico
--
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to