[Pkg-openssl-devel] Re: OpenSSL bug in libcrypto.so:RAND_poll() crashes apache2 @ startup

Christoph Martin martin at uni-mainz.de
Tue Apr 4 08:36:53 UTC 2006


Hi Vito,

vito at hostway.com schrieb:
> Hello Christoph,
> 
> Included below is an email I've already submitted to openssl-bugs at openssl.org,
> you may want to get the debian package updated to fix this bug for debian users.

Thanks for your report and the patch. I did not see any feedback on your
mail to openssl-bugs. Did you get any reply on your patch proposal?

Christoph

> -------------------------------------------------------------------------
> 
> Hello,
> 
> I have found a bug in libcrypto.so which causes Apache2 to crash or
> deadlock when a few hundred virtual hosts are configured in a
> SSL-enabled Apache2 instance.
> 
> The problem is Apache2 opens a number of files per virtual host before
> initializing libcrypto.so's random seed, given enough virtual hosts the
> file descriptor the RAND_poll() open() gets when it opens its entropy
> source will exceed FD_SETSIZE.  This is a serious problem because RAND_poll()
> internally uses select() to watch for data ready to be read from the
> entropy source.  When the fd exceeds FD_SETSIZE (1024 on modern linux
> systems) this will cause deadlocks / segfaults.
> 
> I have created a patch to convert this to use poll() which does not have
> this limitation and is much better suited for watching a single file
> descriptor.  The patch is included below.  I'm not sure if you guys need
> to make this check if poll() is available in the system to keep things
> portable, but if the select() call needs to be kept when poll() is
> unavailable, it has to deal with fd >= FD_SETSIZE and not give it to
> select().
> 
> This was using 0.9.7e-3sarge1 from debian stable as the original source tree, I
> checked the 0.9.7i source on openssl.org and the related code is the same.
> 
> It's a relatively high priority because it makes apache2 flip out when it gets
> hit, might wanna get a fixed version out soon.
> 
> Thanks for the OpenSSL project,
> Vito Caputo
> Hostway Linux Systems Developer
> 
> 
> 
> 
> 
> --- rand_unix.c.orig	2006-03-21 17:01:24.000000000 -0600
> +++ rand_unix.c	2006-03-21 21:58:12.000000000 -0600
> @@ -114,6 +114,7 @@
>  #include "cryptlib.h"
>  #include <openssl/rand.h>
>  #include "rand_lcl.h"
> +#include <sys/poll.h>
>  
>  #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS))
>  
> @@ -124,6 +125,7 @@
>  #include <unistd.h>
>  #include <time.h>
>  
> +
>  #ifdef __OpenBSD__
>  int RAND_poll(void)
>  {
> @@ -165,53 +167,37 @@ int RAND_poll(void)
>  	 * have this. Use /dev/urandom if you can as /dev/random may block
>  	 * if it runs out of random entries.  */
>  
> -	for (randomfile = randomfiles; *randomfile && n < ENTROPY_NEEDED; randomfile++)
> -		{
> +	for (randomfile = randomfiles; *randomfile && n < ENTROPY_NEEDED; randomfile++) {
>  		if ((fd = open(*randomfile, O_RDONLY|O_NONBLOCK
>  #ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it
>  		   our controlling tty */
> -			|O_NOCTTY
> +		|O_NOCTTY
>  #endif
>  #ifdef O_NOFOLLOW /* Fail if the file is a symbolic link */
> -			|O_NOFOLLOW
> +		|O_NOFOLLOW
>  #endif
> -			)) >= 0)
> -			{
> -			struct timeval t = { 0, 10*1000 }; /* Spend 10ms on
> -							      each file. */
> +		)) >= 0) {
>  			int r;
> -			fd_set fset;
> +			struct pollfd rfd = {fd, POLLIN, 0};
> +			int t = 10; /* Spend 10ms on each file. */
> +
> +			/* Patched to use poll() instead of select(), sometimes this gets called
> +			 * with >= FD_SETSIZE files opened already (apache2).
> +			 * When fd is >= FD_SETSIZE the behavior is undefined (likely a buffer
> +			 * overflow...), I observed segfaults & deadlocks.
> +			 * 3/21/2006 - Vito Caputo - <vito at hostway.com> */
>  
> -			do
> -				{
> -				FD_ZERO(&fset);
> -				FD_SET(fd, &fset);
> +			do {
>  				r = -1;
>  
> -				if (select(fd+1,&fset,NULL,NULL,&t) < 0)
> -					t.tv_usec=0;
> -				else if (FD_ISSET(fd, &fset))
> -					{
> -					r=read(fd,(unsigned char *)tmpbuf+n,
> -					       ENTROPY_NEEDED-n);
> -					if (r > 0)
> -						n += r;
> -					}
> -
> -				/* Some Unixen will update t, some
> -				   won't.  For those who won't, give
> -				   up here, otherwise, we will do
> -				   this once again for the remaining
> -				   time. */
> -				if (t.tv_usec == 10*1000)
> -					t.tv_usec=0;
> +				if((poll(&rfd, 1, t) > 0) && (rfd.revents & POLLIN)) {
> +					r = read(fd, (unsigned char *)tmpbuf + n, ENTROPY_NEEDED - n);
> +					if(r > 0) n += r;
>  				}
> -			while ((r > 0 || (errno == EINTR || errno == EAGAIN))
> -				&& t.tv_usec != 0 && n < ENTROPY_NEEDED);
> -
> +			} while((r > 0 || (errno == EINTR || errno == EAGAIN)) && n < ENTROPY_NEEDED);
>  			close(fd);
> -			}
>  		}
> +	}
>  #endif
>  
>  #ifdef DEVRANDOM_EGD
> 

-- 
============================================================================
Christoph Martin, EDV der Verwaltung, Uni-Mainz, Germany
 Internet-Mail:  Christoph.Martin at Verwaltung.Uni-Mainz.DE
  Telefon: +49-6131-3926337
      Fax: +49-6131-3922856

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
Url : http://lists.alioth.debian.org/pipermail/pkg-openssl-devel/attachments/20060404/73624476/signature.pgp


More information about the Pkg-openssl-devel mailing list