All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephan Mueller <smueller@chronox.de>
To: Alex Xu <alex_y_xu@yahoo.ca>
Cc: Nikos Mavrogiannopoulos <nmav@gnutls.org>,
	Linux Crypto Mailing List <linux-crypto@vger.kernel.org>,
	virtualization@lists.linux-foundation.org
Subject: Re: getrandom waits for a long time when /dev/random is insufficiently read from
Date: Fri, 29 Jul 2016 15:12:30 +0200	[thread overview]
Message-ID: <2622345.NpnZjxROFX@tauon.atsec.com> (raw)
In-Reply-To: <20160729090345.798c3e6f.alex_y_xu@yahoo.ca>

Am Freitag, 29. Juli 2016, 09:03:45 CEST schrieb Alex Xu:

Hi Alex,

> On Fri, 29 Jul 2016 12:24:27 +0200
> 
> Nikos Mavrogiannopoulos <nmav@gnutls.org> wrote:
> > On Fri, Jul 29, 2016 at 7:40 AM, Stephan Mueller
> > 
> > <smueller@chronox.de> wrote:
> > > And finally, you have a coding error that is very very common but
> > > fatal when reading from /dev/random: you do not account for short
> > > reads which implies that your loop continues even in the case of
> > > short reads.
> > > 
> > > Fix your code with something like the following:
> > > int read_random(char *buf, size_t buflen)
> > > {
> > > 
> > >         int fd = 0;
> > >         ssize_t ret = 0;
> > >         size_t len = 0;
> > >         
> > >         fd = open("/dev/random", O_RDONLY|O_CLOEXEC);
> > >         if(0 > fd)
> > >         
> > >                 return fd;
> > >         
> > >         do {
> > >         
> > >                 ret = read(fd, (buf + len), (buflen - len));
> > >                 if (0 < ret)
> > >                 
> > >                         len += ret;
> > >         
> > >         } while ((0 < ret || EINTR == errno || ERESTART == errno)
> > >         
> > >                  && buflen > len);
> > 
> > Unless there is a documentation error, the same is required when using
> > getrandom(). It can also return short as well as to be interrupted.
> > 
> > regards,
> > Nikos
> 
> I am aware that (according to the documentation) both random(4) and
> getrandom(2) may not return the full size of the read. However, that is
> (as far as I know) not relevant to the point that I am making.
> 
> What I am saying is that based on my understanding of random(4) and
> getrandom(2), at boot, given the same buffer size, reading
> from /dev/random should have the same behavior as calling getrandom
> passing no flags.

/dev/random can return after at least 64 bits received in the input_pool 
whereas getrandom waits for 128 bits.
> 
> The buffer size can also be set to 1 with similar results, but the
> iteration number for success must be then increased to a large number.
> IME 30 worked consistently while 29 hung; your results may vary.
> 
> The interesting thing is though, if GRND_RANDOM is passed to getrandom,
> then it does not hang and returns 1 byte immediately (whether or not
> GRND_NONBLOCK is set).

Sure, because there is one byte in the input_pool at the time user space 
boots. Note again, /dev/random waits until having 64 bits.

> 
> 1, 2..29: reads all return 1 byte, getrandom pauses for 90-110 secs then
> returns 1 byte
> 30+: reads all return 1 byte, getrandom immediately returns 1 byte
> -r 0: getrandom immediately returns 1 byte
> -r 1, -r 2, -r 128, -r 256: reads all return 1 byte, getrandom
> immediately returns 1 byte
> 
I would say that this is expected.

> Moving the open and close calls outside of the loop produces the same
> results. Writing 4096 bytes to /dev/urandom also has no effect.

Sure, it does not update the input_pool. Only the IOCTL can update the 
input_pool from user space.
> 
> In my opinion, assuming I am not doing something terribly wrong, this
> constitutes a bug in the kernel's handling of getrandom calls at boot,
> possibly only when the primary source of entropy is virtio.

Nope, I do not think that this is true:

- /dev/random returns one byte for one byte of entropy received, but it has a 
lower limit of 64 bits

- getrandom behaves like /dev/urandom (i.e. nonblocking) except during boot 
where it waits until the RNG has collected 128 bits before operating like a 
DRNG that is seeded once in a while when entropy comes in.


Ciao
Stephan

  reply	other threads:[~2016-07-29 13:12 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-28 22:07 getrandom waits for a long time when /dev/random is insufficiently read from Alex Xu
2016-07-29  5:40 ` Stephan Mueller
2016-07-29 10:24   ` Nikos Mavrogiannopoulos
2016-07-29 10:24   ` Nikos Mavrogiannopoulos
2016-07-29 13:03     ` Alex Xu
2016-07-29 13:12       ` Stephan Mueller [this message]
2016-07-29 14:14         ` Alex Xu via Virtualization
2016-07-29 14:14         ` Alex Xu
2016-07-29 17:03           ` Stephan Mueller
2016-07-29 17:31             ` Alex Xu via Virtualization
2016-07-29 17:31             ` Alex Xu
2016-07-30 22:09               ` Theodore Ts'o
2016-07-31  1:53                 ` Alex Xu via Virtualization
2016-07-29 17:03           ` Stephan Mueller
2016-07-29 13:12       ` Stephan Mueller
2016-07-29 13:03     ` Alex Xu via Virtualization
2016-07-29  5:40 ` Stephan Mueller
  -- strict thread matches above, loose matches on Subject: below --
2016-07-28 22:07 Alex Xu via Virtualization

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2622345.NpnZjxROFX@tauon.atsec.com \
    --to=smueller@chronox.de \
    --cc=alex_y_xu@yahoo.ca \
    --cc=linux-crypto@vger.kernel.org \
    --cc=nmav@gnutls.org \
    --cc=virtualization@lists.linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.