Re: [PATCH v2] arc4random: simplify design for better safety

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Mark,

On Mon, Jul 25, 2022 at 06:10:06PM -0700, Mark Harris wrote:
> Jason A. Donenfeld wrote:
> > +      l = __getrandom_nocancel (p, n, 0);
> > +      if (l > 0)
> > +       {
> > +         if ((size_t) l == n)
> > +           return; /* Done reading, success. */
> > +         p = (uint8_t *) p + l;
> > +         n -= l;
> > +         continue; /* Interrupted by a signal; keep going. */
> > +       }
> > +      else if (l == 0)
> > +       arc4random_getrandom_failure (); /* Weird, should never happen. */
> > +      else if (errno == ENOSYS)
> > +       {
> > +         have_getrandom = false;
> > +         break; /* No syscall, so fallback to /dev/urandom. */
> > +       }
> > +      arc4random_getrandom_failure (); /* Unknown error, should never happen. */
> 
> Isn't EINTR also possible?  Aborting in that case does not seem reasonable.

Not in current kernels, where it always returns at least PAGE_SIZE bytes
before checking for pending signals. In older kernels, if there was a
signal pending at the top, it would do no work and return -ERESTARTSYS,
which I believe should then get restarted by glibc's syscaller? I might
be wrong about how restarts work though, so if you know better, please
let me know. TEMP_FAILURE_RETRY relies on errno, so that's not what we
want. I guess I can just add a case for it.

> Also the __getrandom_nocancel function does not set errno on Linux; it
> just returns INTERNAL_SYSCALL_CALL (getrandom, buf, buflen, flags).
> So unless that is changed, it doesn't look like this ENOSYS check will
> detect old Linux kernels.

Thanks. It looks like INTERNAL_SYSCALL_CALL just returns the errno as-is
as a return value, right? I'll adjust the code to account for that.

> > +      struct pollfd pfd = { .events = POLLIN };
> > +      pfd.fd = TEMP_FAILURE_RETRY (
> > +         __open64_nocancel ("/dev/random", O_RDONLY | O_CLOEXEC | O_NOCTTY));
> > +      if (pfd.fd < 0)
> > +       arc4random_getrandom_failure ();
> > +      if (__poll (&pfd, 1, -1) < 0)
> > +       arc4random_getrandom_failure ();
> > +      if (__close_nocancel (pfd.fd) < 0)
> > +       arc4random_getrandom_failure ();
> 
> The TEMP_FAILURE_RETRY handles EINTR on open, but __poll can also
> result in EINTR.

Thanks. I'll surround the __poll in TEMP_FAILURE_RETRY.

Thank you for the review! v3 will have the above changes.

Jason



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]
  Powered by Linux