always read if we can't use select because of a too large FD
authorBodo Möller <bodo@openssl.org>
Wed, 28 Jun 2006 14:49:39 +0000 (14:49 +0000)
committerBodo Möller <bodo@openssl.org>
Wed, 28 Jun 2006 14:49:39 +0000 (14:49 +0000)
(it's non-blocking mode anyway)

CHANGES
crypto/rand/rand_unix.c

diff --git a/CHANGES b/CHANGES
index 8ca7b0b87d6d9c816e27af20d8b78cc24bd3ca7c..f2d42a28473d679aa752ddbc5d083b3e7ca69db2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -7,7 +7,7 @@
   *) Change the Unix randomness entropy gathering to use poll() when
      possible instead of select(), since the latter has some
      undesirable limitations.
-     [Darryl Miles via Richard Levitte]
+     [Darryl Miles via Richard Levitte and Bodo Moeller]
 
   *) Disable rogue ciphersuites:
 
index bb0e719201f2197448f1eb299450441282b79a4c..89e65abe9d45d0837edc4140e2818dbfe76d1d48 100644 (file)
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <fcntl.h>
 #include <unistd.h>
 #include <time.h>
-
 #if defined(OPENSSL_SYS_LINUX)
- /* lets use poll() */
 # include <sys/poll.h>
-# define IOWAIT_VARS           struct pollfd pset; struct timeval t
-# define IOWAIT_INIT(f, t)     do {                                    \
-                                       pset.fd = (f);                  \
-                                       pset.events = POLLIN;           \
-                                       pset.revents = 0;               \
-                                       (t)->tv_sec = 0;                \
-                                       (t)->tv_usec = 10*1000;         \
-                                       /* Spend 10ms on each file. */  \
-                               } while(0)
-# define IOWAIT_FUNC(f, t)     poll(&pset, 1, ((t)->tv_sec * 1000) + ((t)->tv_usec / 1000))
-# define IOWAIT_CHECK(f)       ((pset.revents & POLLIN) != 0)
-#else
- /* lets use select() */
-
- /* For each platform we could do with making a guess at
-  *  how many FDs we support.  With glibc/Linux its possible
-  *  to use FD_SETSIZE directly, but this may not be very
-  *  portable. Another options was to use _POSIX_OPEN_MAX
-  *  but that value is a tad dull on modern hardware.  So
-  *  I ended up trying sizeof(fd_set)*8 which should be
-  *  closer to the real value.
-  * If this causes a problem on your platform because we
-  *  can not guess correctly then set it to zero.
-  */
-# if defined(FD_SETSIZE)
-#  define IOWAIT_FD_SETSIZE    (FD_SETSIZE)
-# else
-  /* fallback method */
-#  define IOWAIT_FD_SETSIZE    (sizeof(fd_set) * 8)
-# endif
-# define IOWAIT_VARS           fd_set fset; struct timeval t
-# define IOWAIT_INIT(f, t)     do {                                    \
-                                       FD_ZERO(&fset);                 \
-                                       if(IOWAIT_FD_SETSIZE > 0        \
-                                          && (f) >= IOWAIT_FD_SETSIZE) \
-                                               { break; }              \
-                                       FD_SET((f), &fset);             \
-                                       (t)->tv_sec = 0;                \
-                                       (t)->tv_usec = 10*1000;         \
-                                       /* Spend 10ms on each file. */  \
-                               } while(0)
-# define IOWAIT_FUNC(f, t)     select((f)+1,&fset,NULL,NULL,(t))
-# define IOWAIT_CHECK(f)       FD_ISSET((f), &fset)
+#endif
+#include <limits.h>
+#ifndef FD_SETSIZE
+# define FD_SETSIZE (8*sizeof(fd_set))
 #endif
 
 #ifdef __OpenBSD__
@@ -190,7 +149,7 @@ int RAND_poll(void)
 
        return 1;
 }
-#else
+#else /* !defined(__OpenBSD__) */
 int RAND_poll(void)
 {
        unsigned long l;
@@ -230,8 +189,8 @@ int RAND_poll(void)
 #endif
                        )) >= 0)
                        {
+                       int usec = 10*1000; /* spend 10ms on each file */
                        int r,j;
-                       IOWAIT_VARS;
                        struct stat *st=&randomstats[i];
 
                        /* Avoid using same input... Used to be O_NOFOLLOW
@@ -247,34 +206,75 @@ int RAND_poll(void)
 
                        do
                                {
-                               r = -1;
-                               IOWAIT_INIT(fd, &t);
+                               int try_read = 0;
+
+#if defined(OPENSSL_SYS_LINUX)
+                               /* use poll() */
+                               struct pollfd pset;
+                               
+                               pset.fd = fd;
+                               pset.events = POLLIN;
+                               pset.revents = 0;
 
-                               if (IOWAIT_FUNC(fd, &t) < 0)
-                                       t.tv_usec=0;
-                               else if (IOWAIT_CHECK(fd))
+                               if (poll(&pset, 1, usec / 1000) < 0)
+                                       usec = 0;
+                               else
+                                       try_read = (pset.revents & POLLIN) != 0;
+
+#else
+                               /* use select() */
+                               fd_set fset;
+                               struct timeval t;
+                               
+                               t.tv_sec = 0;
+                               t.tv_usec = usec;
+
+                               if (FD_SETSIZE > 0 && fd >= FD_SETSIZE)
                                        {
-                                       r=read(fd,(unsigned char *)tmpbuf+n,
-                                              ENTROPY_NEEDED-n);
+                                       /* can't use select, so just try to read once anyway */
+                                       try_read = 1;
+                                       }
+                               else
+                                       {
+                                       FD_ZERO(&fset);
+                                       FD_SET(fd, &fset);
+                                       
+                                       if (select(fd+1,&fset,NULL,NULL,&t) >= 0)
+                                               {
+                                               usec = t.tv_usec;
+                                               if (FD_ISSET(fd, &fset))
+                                                       try_read = 1;
+                                               }
+                                       else
+                                               usec = 0;
+                                       }
+#endif
+                               
+                               if (try_read)
+                                       {
+                                       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
+                               else
+                                       r = -1;
+                               
+                               /* Some Unixen will update t in select(), some
+                                  won't.  For those who won't, or if we
+                                  didn't use select() in the first place,
+                                  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 (usec == 10*1000)
+                                       usec = 0;
                                }
-                       while ((r > 0 || (errno == EINTR || errno == EAGAIN))
-                               && t.tv_usec != 0 && n < ENTROPY_NEEDED);
+                       while ((r > 0 ||
+                              (errno == EINTR || errno == EAGAIN)) && usec != 0 && n < ENTROPY_NEEDED);
 
                        close(fd);
                        }
                }
-#endif
+#endif /* defined(DEVRANDOM) */
 
 #ifdef DEVRANDOM_EGD
        /* Use an EGD socket to read entropy from an EGD or PRNGD entropy
@@ -289,7 +289,7 @@ int RAND_poll(void)
                if (r > 0)
                        n += r;
                }
-#endif
+#endif /* defined(DEVRANDOM_EGD) */
 
 #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD)
        if (n > 0)
@@ -315,12 +315,13 @@ int RAND_poll(void)
 #endif
 }
 
-#endif
-#endif
+#endif /* defined(__OpenBSD__) */
+#endif /* !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) */
+
 
 #if defined(OPENSSL_SYS_VXWORKS)
 int RAND_poll(void)
-{
-    return 0;
-}
+       {
+       return 0;
+       }
 #endif