summaryrefslogtreecommitdiffhomepage
path: root/src/compat/compat.h
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-06-19 01:22:57 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-06-19 05:09:35 +0200
commit5d7bdaaf0bd7b5a28ad196109f5ec3cdb550bd02 (patch)
treed3ddb13296b3676478cdf778b0e27a9d7c347951 /src/compat/compat.h
parentf9759e17543657e62bd2a487762f419ed6d2f907 (diff)
receive: drop handshake packets if rng is not initialized
Otherwise it's too easy to trigger cookie reply messages. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/compat/compat.h')
-rw-r--r--src/compat/compat.h53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index 2853c09..f2d7e17 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -623,6 +623,59 @@ static inline void new_icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32
#define icmpv6_send(a,b,c,d) new_icmpv6_send(a,b,c,d)
#endif
+/* https://lkml.org/lkml/2018/6/18/1361 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+#include <linux/random.h>
+#include <linux/slab.h>
+struct rng_is_initialized_callback {
+ struct random_ready_callback cb;
+ atomic_t *rng_state;
+};
+static inline void rng_is_initialized_callback(struct random_ready_callback *cb)
+{
+ struct rng_is_initialized_callback *rdy = container_of(cb, struct rng_is_initialized_callback, cb);
+ atomic_set(rdy->rng_state, 2);
+ kfree(rdy);
+}
+static inline bool rng_is_initialized(void)
+{
+ static atomic_t rng_state = ATOMIC_INIT(0);
+
+ if (atomic_read(&rng_state) == 2)
+ return true;
+
+ if (atomic_cmpxchg(&rng_state, 0, 1) == 0) {
+ int ret;
+ struct rng_is_initialized_callback *rdy = kmalloc(sizeof(*rdy), GFP_ATOMIC);
+ if (!rdy) {
+ atomic_set(&rng_state, 0);
+ return false;
+ }
+ rdy->cb.owner = THIS_MODULE;
+ rdy->cb.func = rng_is_initialized_callback;
+ rdy->rng_state = &rng_state;
+ ret = add_random_ready_callback(&rdy->cb);
+ if (ret)
+ kfree(rdy);
+ if (ret == -EALREADY) {
+ atomic_set(&rng_state, 2);
+ return true;
+ } else if (ret)
+ atomic_set(&rng_state, 0);
+ return false;
+ }
+ return false;
+}
+#else
+/* 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 bool rng_is_initialized(void)
+{
+ return true;
+}
+#endif
+
/* PaX compatibility */
#ifdef CONSTIFY_PLUGIN
#include <linux/cache.h>