getrandom waits for a long time when /dev/random is insufficiently read from

Stephan Mueller
Fri, 29 Jul 2016 05:40:02 -0000

Am Donnerstag, 28. Juli 2016, 18:07:32 CEST schrieb Alex Xu:

Hi Alex,

> Linux 4.6, also tried 4.7, qemu 2.6, using this C program:

I am not sure what problem you are referring to, but that is an expected
behavior.

You get partial reads when reading from /dev/random with a minimum of 64
bits. On the other hand getrandom(2) is woken up after the input_pool
received 128 bits of entropy.

In you strace you see that after reading 16 bytes from /dev/random, the
getrandom unblocks and starts delivering.

Note, in virtualized environments the current Linux /dev/random
implementation collects massively less entropy compared to a bare-metal
system. Hence the long wait time of your 90 to 100 secs until getrandom
unblocks.

Besides, even without reading from /dev/random, your getrandom will wait that
long.

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);

...

Ciao
Stephan