Skip to contentSkip to conversation

random: Seed the fallback random number generator

PATCH In review Ossama Othman 2 participants 2 messages Oct 24, 2019

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 random: Seed the fallback random number generator

The random() PRNG is used as a fallback in case of getrandom() syscall failure. However, the PRNG was not seeded prior to initial use, resulting in the same predictable sequence of numbers being generated. Explicitly seed the PRNG on initial use with random data retrieved from the ELF binary loader to decrease predictability.

---
 ell/random.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)
ell/random.c +18 -1
index 0b5b09e..99aa06e 100644
@@ -28,6 +28,8 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <time.h>
+#include <sys/auxv.h>
 #include <sys/syscall.h>
 
 #include "random.h"
@@ -95,11 +97,26 @@ LIB_EXPORT uint32_t l_getrandom_uint32(void)
 {
 	int ret;
 	uint32_t u;
+	static unsigned int seed = 0;  /* For fallback PRNG. */
 
 	ret = getrandom(&u, sizeof(u), GRND_NONBLOCK);
 
 	if (ret == sizeof(u))
 		return u;
 
-        return random() * RAND_MAX + random();
+	if (seed == 0) {
+		/*
+		 * Seed the fallback PRNG below with the
+		 * process-specific random data supplied by the
+		 * kernel, skipping the canary in the first half.
+		 */
+		unsigned long addr =
+			getauxval(AT_RANDOM) + sizeof(void *);
+
+		seed = *((unsigned long *) addr) ^ time(NULL);
+
+		srandom(seed);
+	}
+
+	return random() * RAND_MAX + random();
 }
Signature · 1 line
2.20.1
#1 lore raw
Quoted 32 lines · Ossama Othman

The random() PRNG is used as a fallback in case of getrandom() syscall failure. However, the PRNG was not seeded prior to initial use, resulting in the same predictable sequence of numbers being generated. Explicitly seed the PRNG on initial use with random data retrieved from the ELF binary loader to decrease predictability.
---
ell/random.c | 19 ++++++++++++++++++-

1 file changed, 18 insertions(+), 1 deletion(-)
ell/random.c +3 -0
index 0b5b09e..99aa06e 100644
@@ -28,6 +28,8 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <time.h>
+#include <sys/auxv.h>
 #include <sys/syscall.h>
 
 #include "random.h"
@@ -95,11 +97,26 @@ LIB_EXPORT uint32_t l_getrandom_uint32(void)
 {
 	int ret;
 	uint32_t u;
+	static unsigned int seed = 0;  /* For fallback PRNG. */
 
 	ret = getrandom(&u, sizeof(u), GRND_NONBLOCK);
 
 	if (ret == sizeof(u))
 		return u;

ell/random.c LIB_EXPORT uint32_t l_getrandom_uint32(void) · line 114

Quoted 10 lines
ell/random.c +8 -1
 
-        return random() * RAND_MAX + random();
+	if (seed == 0) {
+		/*
+		 * Seed the fallback PRNG below with the
+		 * process-specific random data supplied by the
+		 * kernel, skipping the canary in the first half.
+		 */
+		unsigned long addr =
+			getauxval(AT_RANDOM) + sizeof(void *);

getauxval is a nonstandard glibc extension, so there needs to be a way to fall back to something else (or skip this) for other C libraries.

Quoted 14 lines
ell/random.c +7 -0
+
+		seed = *((unsigned long *) addr) ^ time(NULL);
+
+		srandom(seed);
+	}
+
+	return random() * RAND_MAX + random();
 }
Signature · 4 lines
2.20.1
_______________________________________________
ell mailing list -- ell(a)lists.01.org
To unsubscribe send an email to ell-leave(a)lists.01.org

--
Mat Martineau
Intel