summaryrefslogtreecommitdiffstatshomepage
path: root/src/compat
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-06-02 17:41:11 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-06-08 04:24:14 +0200
commitf3a1c6504679b039ba563b5b45c9bbe1113dfbad (patch)
treed5367904bbb69ed360d5af2f97b998fc8911f4bf /src/compat
parentnoise: fix race when replacing handshake (diff)
downloadwireguard-monolithic-historical-f3a1c6504679b039ba563b5b45c9bbe1113dfbad.tar.xz
wireguard-monolithic-historical-f3a1c6504679b039ba563b5b45c9bbe1113dfbad.zip
config: ensure the RNG is initialized before setting
It's possible that get_random_bytes() will return bad randomness if it hasn't been seeded. This patch makes configuration block until the RNG is properly initialized. Reference: http://www.openwall.com/lists/kernel-hardening/2017/06/02/2
Diffstat (limited to 'src/compat')
-rw-r--r--src/compat/compat.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index 6a5f33c..68d62b9 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -222,6 +222,49 @@ static const struct in6_addr our_in6addr_any = IN6ADDR_ANY_INIT;
#define in6addr_any our_in6addr_any
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+#include <linux/completion.h>
+#include <linux/random.h>
+#include <linux/errno.h>
+struct rng_initializer {
+ struct completion done;
+ struct random_ready_callback cb;
+};
+static inline void rng_initialized_callback(struct random_ready_callback *cb)
+{
+ complete(&container_of(cb, struct rng_initializer, cb)->done);
+}
+static inline int wait_for_random_bytes(void)
+{
+ static bool rng_is_initialized = false;
+ int ret;
+ if (unlikely(!rng_is_initialized)) {
+ struct rng_initializer rng = {
+ .done = COMPLETION_INITIALIZER(rng.done),
+ .cb = { .owner = THIS_MODULE, .func = rng_initialized_callback }
+ };
+ ret = add_random_ready_callback(&rng.cb);
+ if (!ret) {
+ ret = wait_for_completion_interruptible(&rng.done);
+ if (ret) {
+ del_random_ready_callback(&rng.cb);
+ return ret;
+ }
+ } else if (ret != -EALREADY)
+ return ret;
+ rng_is_initialized = true;
+ }
+ return 0;
+}
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+/* This is a disaster. Without this API, we really have no way of
+ * knowing if it's initialized. We just return that it has and hope
+ * for the best... */
+static inline int wait_for_random_bytes(void)
+{
+ return 0;
+}
+#endif
/* https://lkml.org/lkml/2015/6/12/415 */
#include <linux/netdevice.h>