summaryrefslogtreecommitdiff
path: root/random
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-09-08 10:53:12 +0200
committerWerner Koch <wk@gnupg.org>2011-09-08 10:53:12 +0200
commit9487099071af4478d2882e633a0ade805801d6fa (patch)
tree7226866ea3efd53f13d24c08d78907a480816e24 /random
parent5e14de02b323d207151429d37f006ec30bbf7783 (diff)
downloadlibgcrypt-9487099071af4478d2882e633a0ade805801d6fa.tar.gz
Fix a problem with select and high fds.
If on systems where the maximum number of fds may be dynamically configured to a value of FD_MAXSIZE or higher and the RNG is first used after more than FD_SETSIZE-1 descriptors are in use, we disable the progress messages from the RNG. A better solution would be too use poll but that requires more tests. The same problem exists in rndunix.c - however this rng is only used on old Unices and I assume that they don't feature dynamically configured maximum fd sizes.
Diffstat (limited to 'random')
-rw-r--r--random/ChangeLog5
-rw-r--r--random/rndlinux.c50
-rw-r--r--random/rndunix.c3
3 files changed, 37 insertions, 21 deletions
diff --git a/random/ChangeLog b/random/ChangeLog
index 7784d44e..b7a0d5a1 100644
--- a/random/ChangeLog
+++ b/random/ChangeLog
@@ -1,3 +1,8 @@
+2011-09-08 Werner Koch <wk@g10code.com>
+
+ * rndlinux.c (_gcry_rndlinux_gather_random): Don't use select if
+ the fd number is too high. Reported by Jakub Bogusz.
+
2010-10-18 Werner Koch <wk@g10code.com>
* rndw32.c (registry_poll): Disable performace fata gathering if
diff --git a/random/rndlinux.c b/random/rndlinux.c
index 5b84a19c..b304cc9e 100644
--- a/random/rndlinux.c
+++ b/random/rndlinux.c
@@ -134,29 +134,39 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
struct timeval tv;
int rc;
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- tv.tv_sec = delay;
- tv.tv_usec = delay? 0 : 100000;
- if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
+ /* If the system has no limit on the number of file descriptors
+ and we encounter an fd which is larger than the fd_set size,
+ we don't use the select at all. The select code is only used
+ to emit progress messages. A better solution would be to
+ fall back to poll() if available. */
+#ifdef FD_SETSIZE
+ if (fd < FD_SETSIZE)
+#endif
{
- if (!any_need_entropy || last_so_far != (want - length) )
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = delay;
+ tv.tv_usec = delay? 0 : 100000;
+ if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
{
- last_so_far = want - length;
- _gcry_random_progress ("need_entropy", 'X',
- (int)last_so_far, (int)want);
- any_need_entropy = 1;
- }
- delay = 3; /* Use 3 seconds henceforth. */
- continue;
- }
- else if( rc == -1 )
- {
- log_error ("select() error: %s\n", strerror(errno));
- if (!delay)
- delay = 1; /* Use 1 second if we encounter an error before
+ if (!any_need_entropy || last_so_far != (want - length) )
+ {
+ last_so_far = want - length;
+ _gcry_random_progress ("need_entropy", 'X',
+ (int)last_so_far, (int)want);
+ any_need_entropy = 1;
+ }
+ delay = 3; /* Use 3 seconds henceforth. */
+ continue;
+ }
+ else if( rc == -1 )
+ {
+ log_error ("select() error: %s\n", strerror(errno));
+ if (!delay)
+ delay = 1; /* Use 1 second if we encounter an error before
we have ever blocked. */
- continue;
+ continue;
+ }
}
do
diff --git a/random/rndunix.c b/random/rndunix.c
index cc5eb145..1b810d72 100644
--- a/random/rndunix.c
+++ b/random/rndunix.c
@@ -551,7 +551,8 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
#else
#error O_NONBLOCK is missing
#endif
-
+ /* FIXME: We need to make sure that the fd is less than
+ FD_SETSIZE. */
FD_SET(dataSources[i].pipeFD, &fds);
dataSources[i].length = 0;