glib-aux: cleanup handling of getrandom() and handle EAGAIN

- the return value of getrandom() is ssize_t.
- handle EAGAIN to indicate low entropy.
- treat a return value of zero the same as any other
  low "n", by falling back to bad random bytes.

(cherry picked from commit 416f97c5a9)
This commit is contained in:
Thomas Haller 2021-07-13 16:51:28 +02:00
parent 2a9dd6c2e5
commit a8d5c346bd
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728

View file

@ -229,17 +229,20 @@ nm_utils_random_bytes(void *p, size_t n)
static gboolean have_syscall = TRUE;
if (have_syscall) {
r = getrandom(buf, n, GRND_NONBLOCK);
if (r > 0) {
if ((size_t) r == n)
ssize_t r2;
int errsv;
r2 = getrandom(buf, n, GRND_NONBLOCK);
if (r2 >= 0) {
if ((size_t) r2 == n)
return TRUE;
/* no or partial read. There is not enough entropy.
* Fill the rest reading with the fallback code and remember
* that some bits are not high quality. */
nm_assert(r < n);
buf += r;
n -= r;
nm_assert((size_t) r2 < n);
buf += r2;
n -= r2;
/* At this point, we don't want to read /dev/urandom, because
* the entropy pool is low (early boot?), and asking for more
@ -251,13 +254,17 @@ nm_utils_random_bytes(void *p, size_t n)
* a situation where we want to avoid reading /dev/urandom too much. */
goto out_bad_random;
}
if (errno == ENOSYS) {
errsv = errno;
if (errsv == ENOSYS) {
/* no support for getrandom(). We don't know whether
* we urandom will give us good quality. Assume yes. */
* we /dev/urandom will give us good quality. Assume yes. */
have_syscall = FALSE;
} else if (errsv == EAGAIN) {
/* No entropy. We avoid reading /dev/urandom. */
goto out_bad_random;
} else {
/* unknown error. We'll read urandom below, but we don't have
* high-quality randomness. */
/* Unknown error, likely no entropy. We'll read /dev/urandom below, but we don't
* have high-quality randomness. */
has_high_quality = FALSE;
}
}
@ -277,7 +284,7 @@ fd_open:
return has_high_quality;
out_bad_random:
/* we failed to fill the bytes reading from urandom.
/* we failed to fill the bytes reading from /dev/urandom.
* Fill the bits using our pseudo random numbers.
*
* We don't have good quality.