From: Stephan Mueller Subject: Re: getrandom waits for a long time when /dev/random is insufficiently read from Date: Fri, 29 Jul 2016 15:12:30 +0200 Message-ID: <2622345.NpnZjxROFX@tauon.atsec.com> References: <20160728180732.12d38880@alex-desktop> <20160729090345.798c3e6f.alex_y_xu@yahoo.ca> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7Bit Cc: Nikos Mavrogiannopoulos , Linux Crypto Mailing List , virtualization@lists.linux-foundation.org To: Alex Xu Return-path: Received: from mail.eperm.de ([89.247.134.16]:33868 "EHLO mail.eperm.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751365AbcG2NMf (ORCPT ); Fri, 29 Jul 2016 09:12:35 -0400 In-Reply-To: <20160729090345.798c3e6f.alex_y_xu@yahoo.ca> Sender: linux-crypto-owner@vger.kernel.org List-ID: 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 wrote: > > On Fri, Jul 29, 2016 at 7:40 AM, Stephan Mueller > > > > 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