[SRU Focal:oem-5.6] random32: update the net random state on interrupt and activity
Colin Ian King
colin.king at canonical.com
Wed Sep 9 21:23:04 UTC 2020
On 09/09/2020 21:01, Thadeu Lima de Souza Cascardo wrote:
> From: Willy Tarreau <w at 1wt.eu>
>
> This modifies the first 32 bits out of the 128 bits of a random CPU's
> net_rand_state on interrupt or CPU activity to complicate remote
> observations that could lead to guessing the network RNG's internal
> state.
>
> Note that depending on some network devices' interrupt rate moderation
> or binding, this re-seeding might happen on every packet or even almost
> never.
>
> In addition, with NOHZ some CPUs might not even get timer interrupts,
> leaving their local state rarely updated, while they are running
> networked processes making use of the random state. For this reason, we
> also perform this update in update_process_times() in order to at least
> update the state when there is user or system activity, since it's the
> only case we care about.
>
> Reported-by: Amit Klein <aksecurity at gmail.com>
> Suggested-by: Linus Torvalds <torvalds at linux-foundation.org>
> Cc: Eric Dumazet <edumazet at google.com>
> Cc: "Jason A. Donenfeld" <Jason at zx2c4.com>
> Cc: Andy Lutomirski <luto at kernel.org>
> Cc: Kees Cook <keescook at chromium.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Willy Tarreau <w at 1wt.eu>
> Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
> (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4)
> CVE-2020-16166
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at canonical.com>
> ---
> drivers/char/random.c | 1 +
> include/linux/random.h | 3 +++
> kernel/time/timer.c | 8 ++++++++
> lib/random32.c | 2 +-
> 4 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/char/random.c b/drivers/char/random.c
> index 6cf5a5f416ff..eb5ed0455e34 100644
> --- a/drivers/char/random.c
> +++ b/drivers/char/random.c
> @@ -1249,6 +1249,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
>
> fast_mix(fast_pool);
> add_interrupt_bench(cycles);
> + this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]);
>
> if (unlikely(crng_init == 0)) {
> if ((fast_pool->count >= 64) &&
> diff --git a/include/linux/random.h b/include/linux/random.h
> index d319f9a1e429..114db225ac3e 100644
> --- a/include/linux/random.h
> +++ b/include/linux/random.h
> @@ -9,6 +9,7 @@
>
> #include <linux/list.h>
> #include <linux/once.h>
> +#include <linux/percpu.h>
>
> #include <uapi/linux/random.h>
>
> @@ -117,6 +118,8 @@ struct rnd_state {
> __u32 s1, s2, s3, s4;
> };
>
> +DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
> +
> u32 prandom_u32_state(struct rnd_state *state);
> void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
> void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
> diff --git a/kernel/time/timer.c b/kernel/time/timer.c
> index 4820823515e9..226da9217f26 100644
> --- a/kernel/time/timer.c
> +++ b/kernel/time/timer.c
> @@ -43,6 +43,7 @@
> #include <linux/sched/debug.h>
> #include <linux/slab.h>
> #include <linux/compat.h>
> +#include <linux/random.h>
>
> #include <linux/uaccess.h>
> #include <asm/unistd.h>
> @@ -1731,6 +1732,13 @@ void update_process_times(int user_tick)
> scheduler_tick();
> if (IS_ENABLED(CONFIG_POSIX_TIMERS))
> run_posix_cpu_timers();
> +
> + /* The current CPU might make use of net randoms without receiving IRQs
> + * to renew them often enough. Let's update the net_rand_state from a
> + * non-constant value that's not affine to the number of calls to make
> + * sure it's updated when there's some activity (we don't care in idle).
> + */
> + this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick);
> }
>
> /**
> diff --git a/lib/random32.c b/lib/random32.c
> index 763b920a6206..c4d317be2997 100644
> --- a/lib/random32.c
> +++ b/lib/random32.c
> @@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void)
> }
> #endif
>
> -static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
> +DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
>
> /**
> * prandom_u32_state - seeded pseudo-random number generator.
>
That's an interesting fix to a subtle flaw. Clean cherry pick; looks OK
to me.
Acked-by: Colin Ian King <colin.king at canonical.com>
More information about the kernel-team
mailing list