Hi! Can anyone give some pointers to the documentation for the OpenSSL test suite.
Regards -Nitin -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of [EMAIL PROTECTED] via RT Sent: Wednesday, March 22, 2006 2:26 PM Cc: openssl-dev@openssl.org Subject: [openssl.org #1298] OpenSSL bug in libcrypto.so:RAND_poll() crashes apache2 @ startup 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 - <[EMAIL PROTECTED]> */ - 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 ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager [EMAIL PROTECTED] ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager [EMAIL PROTECTED]