Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Aug 2018 02:17:55 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r338084 - head/lib/libc/gen
Message-ID:  <201808200217.w7K2Huem021338@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Mon Aug 20 02:17:55 2018
New Revision: 338084
URL: https://svnweb.freebsd.org/changeset/base/338084

Log:
  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

Modified:
  head/lib/libc/gen/getentropy.c

Modified: head/lib/libc/gen/getentropy.c
==============================================================================
--- head/lib/libc/gen/getentropy.c	Mon Aug 20 02:08:39 2018	(r338083)
+++ head/lib/libc/gen/getentropy.c	Mon Aug 20 02:17:55 2018	(r338084)
@@ -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. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808200217.w7K2Huem021338>