km4arr / openpgm

Automatically exported from code.google.com/p/openpgm
0 stars 0 forks source link

pgm_rand_create fails if leftover errno value even if call to open /dev/urandom succeeds #12

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.  Could only reproduce from another using. framework (libzmq)

The issue was called out here in libzmq: but was not actually their issue.

https://zeromq.jira.com/browse/LIBZMQ-296

The issue is in the rand.c file in the pgm_rand_create 
60 PGM_GNUC_INTERNAL
 61 void
 62 pgm_rand_create (
 63         pgm_rand_t*     new_rand
 64         )
 65 {
 66 /* pre-conditions */
 67         pgm_assert (NULL != new_rand);
 68 
 69 #ifndef _WIN32
 70 /* attempt to read seed from kernel
 71  */
 72         FILE* fp;
 73         do {
 74                 fp = fopen ("/dev/urandom", "rb");
 75         } while (PGM_UNLIKELY(EINTR == errno));
 76         if (fp) {
 77                 size_t items_read;
 78                 do {
 79                         items_read = fread (&new_rand->seed, sizeof(new_rand->seed), 1, fp);
 80                 } while (PGM_UNLIKELY(EINTR == errno));
 81                 fclose (fp);
 82                 if (1 == items_read)
 83                         return;
 84         }
 85 #endif /* !_WIN32 */
 86         const pgm_time_t now = pgm_time_update_now();
 87         new_rand->seed = (uint32_t)pgm_to_msecs (now);
 88 }

The issue of course is this bit right here:

73         do {
74                 fp = fopen ("/dev/urandom", "rb");
75         } while (PGM_UNLIKELY(EINTR == errno));

The author is NOT checking that the value of fp is in error (ie fp != NULL). If 
errno has some garbage value from some other error, this do while will loop 
forever until it runs out of file descriptors per the process ulimit on the 
system (mine being 1024).

I was able to get by, by changing:

- 75         } while (PGM_UNLIKELY(EINTR == errno));

+ 75         } while ((fp == NULL) && (PGM_UNLIKELY(EINTR == errno)));

This is probably sub-optimal and not the best solution, but given it's a 
function which returns void I wasn't sure as to the best approach for 
signalling error back to the user.

Thanks

Original issue reported on code.google.com by rmorri...@countertack.com on 23 Dec 2011 at 8:36

GoogleCodeExporter commented 9 years ago
I'd go with:

} while (PGM_UNLIKELY(NULL == fp && EINTR == errno));

Original comment by fnjo...@gmail.com on 23 Dec 2011 at 9:45

GoogleCodeExporter commented 9 years ago
Finally committed, revision 1461.

Original comment by fnjo...@gmail.com on 20 May 2012 at 2:21