tech-userlevel archive

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

Re: getrandom and getentropy



> Date: Sat, 2 May 2020 12:22:20 +0000
> From: maya%NetBSD.org@localhost
> 
> The getrandom interface intentionally traps people to make questionable
> design choices.

I agree that the getrandom interface is not perfect, and I found the
Linux documentation rather confusing, but after having reimplemented
the semantics I realized the confusion is mostly a matter of
documentation, which is why I addressed this in my original message:

   ### Why were you initially reluctant to adopt them and what changed?

   - I found the Linux documentation for getrandom difficult to follow,
     and I suspect most other people do too.  It is hard to see what
     configuration of flags give you the semantics you want, and with
     eight different choices for the three separate flags it seemed like
     a good way to have lots of people shoot themselves in the foot.

     However, after implementing the semantics and distilling it, I
     realized that it cleanly breaks down into only three usage models
     (with an nonblocking option -- meaning when it would block, it
     returns EAGAIN/EWOULDBLOCK instead), two of which are reasonable
     (flags=0 and flags=GRND_INSECURE), and one of which we didn't
     already have a pathway for.

     So the cost of adopting a silly operation (flags=GRND_RANDOM)
     strikes me as quite small in exchange for the benefit of source
     compatibility, and I tried to address the confusing API by writing
     short usage guidelines with clear examples in the man page
     <https://www.netbsd.org/~riastradh/tmp/20200430/getrandom.html> for
     what the flags argument can be.  If in doubt, use flags=0.

In the end, getrandom(...,0) is the _only_ API to reliably block once
after boot and then return arbirarily much data across many operating
systems; neither /dev/random nor /dev/urandom nor getentropy nor
sysctl kern.arandom nor anything else does that reliably on many
operating systes.

So I think it is worthwhile to adopt that API, and if we have that it
takes very little to get source compatibility with the other getrandom
options -- getrandom(...,GRND_INSECURE) is just another name for what
we already have as sysctl(kern.arandom,...), and getrandom(...,
GRND_RANDOM) is just another name for reading from /dev/random.

> We might immediately take https://www.2uo.de/myths-about-urandom/
> 
> And re-write bits about /dev/random as being about getrandom(...,GRND_RANDOM).

This would be a reasonable article to write, not because NetBSD might
adopt getrandom(...,GRND_RANDOM) as a silly quirk, but because lots of
other systems support _and advertise_ getrandom(...,GRND_RANDOM), like
<https://blogs.oracle.com/solaris/solaris-new-system-calls%3a-getentropy2-and-getrandom2-v2>
and <http://man7.org/linux/man-pages/man2/getrandom.2.html>.

> Calling it "/dev/random" behaviour is ambiguous. Didn't you fix
> /dev/random to not have this limitation, and be more like
> getrandom(...,0)?

getrandom(...,GRND_RANDOM) has a small limit on the data it will
return, as in Linux.  The same has been true of /dev/random for a long
time -- ask to read 1000 bytes, and you might get 16.  /dev/random has
never been appropriate for large reads; GRND_RANDOM is the same.

Generally GRND_RANDOM is silly, and I don't think it's worth spending
time on it, except for the sake of source compatibility with Linux and
everyone else, and to point out in the man page that it's a bad idea
and to decline to give examples of using it.

> Having compat shims in libc is as good as having compat shims in syscall
> because it isn't possible to share raw syscall code between NetBSD and
> other operating systems -- our calling convention is different.

I agree -- any sort of compatibility between the underlying syscalls
is _not_ the point of adding a new getrandom syscall.  The point, from
my original message, is that we simply don't have a path in the kernel
that blocks the way getrandom is expected to, without access to the
/dev/random file, so we need to add _some_ underlying syscall or other
interface to the kernel:

   ### Why a new getrandom system call?  Why not a userland libc wrapper?

   While getentropy(p,n) is essentially the same as
   sysctl(kern.arandom,p,n), the semantics of getrandom(p,n,0) (and the
   slightly silly semantics of getrandom(p,n,GRND_RANDOM)) requires a
   potentially blocking code path that is currently available to userland
   only via /dev/random.

   In other words, we have no path accessible from userland to
   simultaneously to satisfy desiderata (2) and (4).  So if we want to
   satisfy them, we need a new path into the kernel.


Home | Main Index | Thread Index | Old Index