Ensure OpenSSL entropy state reset across forks.
authorPhil Pennock <pdp@exim.org>
Tue, 2 Apr 2013 16:37:03 +0000 (12:37 -0400)
committerPhil Pennock <pdp@exim.org>
Tue, 2 Apr 2013 16:37:03 +0000 (12:37 -0400)
Note that this function is never going to be called pre-fork unless the
admin is doing something highly unusual with ${randint:..} in a context
evaluated in the listening daemon.  Other forks should result in a
re-exec(), thus resetting state.

Nonetheless, be more cautious, explicitly reset state.

Fix per PostgreSQL.

PS: why does OpenSSL not document RAND_cleanup() on the same page as all
    the other entropy pool maintenance functions?

src/src/tls-openssl.c

index 42afd3949ec343caa29d5f26e7508114f6b0ddd8..18cb787a5a6addd64540a954b3e40cee255da27c 100644 (file)
@@ -1753,12 +1753,26 @@ vaguely_random_number(int max)
 {
 unsigned int r;
 int i, needed_len;
+static pid_t pidlast = 0;
+pid_t pidnow;
 uschar *p;
 uschar smallbuf[sizeof(r)];
 
 if (max <= 1)
   return 0;
 
+pidnow = getpid();
+if (pidnow != pidlast)
+  {
+  /* Although OpenSSL documents that "OpenSSL makes sure that the PRNG state
+  is unique for each thread", this doesn't apparently apply across processes,
+  so our own warning from vaguely_random_number_fallback() applies here too.
+  Fix per PostgreSQL. */
+  if (pidlast != 0)
+    RAND_cleanup();
+  pidlast = pidnow;
+  }
+
 /* OpenSSL auto-seeds from /dev/random, etc, but this a double-check. */
 if (!RAND_status())
   {