[WireGuard] [PATCH] use runtime check for getrandom syscall

Daniel Kahn Gillmor dkg at fifthhorseman.net
Sat Jul 2 17:34:17 CEST 2016


wg(8) used a compile-time check for the getrandom syscall.  This means
it's possible to build wg against a kernel that knows about getrandom,
but then move it to another system that doesn't and have it fail to
execute with:

    getrandom: Function not implemented

This changeset makes the check at runtime instead of compile time.

--

Out of curiosity: any reason to not use getrandom(2) explicitly
instead of using the syscall(2) interface?
---
 src/tools/genkey.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/src/tools/genkey.c b/src/tools/genkey.c
index 1602ae1..d260f6b 100644
--- a/src/tools/genkey.c
+++ b/src/tools/genkey.c
@@ -8,18 +8,12 @@
 #include <syscall.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "curve25519.h"
 #include "base64.h"
 
-#ifdef __NR_getrandom
-static inline ssize_t get_random_bytes(uint8_t *out, size_t len)
-{
-	return syscall(__NR_getrandom, out, len, 0);
-}
-#else
-#include <fcntl.h>
-static inline ssize_t get_random_bytes(uint8_t *out, size_t len)
+static inline ssize_t get_urandom_bytes(uint8_t *out, size_t len)
 {
 	ssize_t ret;
 	int fd = open("/dev/urandom", O_RDONLY);
@@ -29,7 +23,19 @@ static inline ssize_t get_random_bytes(uint8_t *out, size_t len)
 	close(fd);
 	return ret;
 }
+
+
+static inline ssize_t get_random_bytes(uint8_t *out, size_t len)
+{
+	long sysret = -1, local_errno = ENOSYS;
+#ifdef __NR_getrandom
+	 sysret = syscall(__NR_getrandom, out, len, 0);
+	 local_errno = errno;
 #endif
+	 if (sysret == -1 && local_errno == ENOSYS)
+		 return get_urandom_bytes(out, len);
+	 return sysret;
+}
 
 int genkey_main(int argc, char *argv[])
 {
-- 
2.8.1



More information about the WireGuard mailing list