In r331279 the code used ENOSYS to check the existence of getrandom(2).

This will only work if the caller already handles SIGSYS, which is not
always the case.

Address this by checking osreldate instead. Note that because there
was not __FreeBSD_version bump when the system call was added, use
1200061 (r332100) which is the first bump after the introduction of
the system call.

PR:		230762
Reported by:	Jenkins via Mark Millard
Reviewed by:	cem
Differential Revision:	https://reviews.freebsd.org/D16807
This commit is contained in:
Xin LI 2018-08-20 02:17:55 +00:00
parent beacffb30d
commit 59488f25ad

View File

@ -34,10 +34,14 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include "libc_private.h"
/* First __FreeBSD_version bump after introduction of getrandom(2) (r331279) */
#define GETRANDOM_FIRST 1200061
extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
static size_t
@ -99,21 +103,38 @@ int
getentropy(void *buf, size_t buflen)
{
ssize_t rd;
bool have_getrandom;
if (buflen > 256) {
errno = EIO;
return (-1);
}
have_getrandom = (__getosreldate() >= GETRANDOM_FIRST);
while (buflen > 0) {
rd = getrandom(buf, buflen, 0);
if (rd == -1) {
if (errno == EINTR)
continue;
else if (errno == ENOSYS || errno == ECAPMODE)
return (getentropy_fallback(buf, buflen));
else
return (-1);
if (have_getrandom) {
rd = getrandom(buf, buflen, 0);
if (rd == -1) {
switch (errno) {
case ECAPMODE:
/*
* Kernel >= r331280 and < r337999
* will return ECAPMODE when the
* caller is already in capability
* mode, fallback to traditional
* method in this case.
*/
have_getrandom = false;
continue;
case EINTR:
continue;
default:
return (-1);
}
}
} else {
return (getentropy_fallback(buf, buflen));
}
/* This cannot happen. */