diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-06-19 01:22:57 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-06-19 05:09:35 +0200 |
commit | 5d7bdaaf0bd7b5a28ad196109f5ec3cdb550bd02 (patch) | |
tree | d3ddb13296b3676478cdf778b0e27a9d7c347951 /src/compat/compat.h | |
parent | f9759e17543657e62bd2a487762f419ed6d2f907 (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.h | 53 |
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> |