Message ID | 20200909200134.88614-1-cascardo@canonical.com |
---|---|
State | New |
Headers | show |
Series | [SRU,Focal:oem-5.6] random32: update the net random state on interrupt and activity | expand |
On 09/09/2020 21:01, Thadeu Lima de Souza Cascardo wrote: > From: Willy Tarreau <w@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@gmail.com> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Kees Cook <keescook@chromium.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Willy Tarreau <w@1wt.eu> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > CVE-2020-16166 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@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@canonical.com>
On 09.09.20 22:01, Thadeu Lima de Souza Cascardo wrote: > From: Willy Tarreau <w@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@gmail.com> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Kees Cook <keescook@chromium.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Willy Tarreau <w@1wt.eu> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > CVE-2020-16166 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> This commit introduces build errors/warnings in some non-x86 arches which are fixed by the following commits: 0c83b277ada7 powerpc: Fix circular dependency between percpu.h and mmu.h aa54ea903abb ARM: percpu.h: fix build error 1c9df907da83 random: fix circular include dependency on arm64 after addition of percpu.h 835d1c3a9879 arm64: Drop unnecessary include from asm/smp.h We probably don't care about those as we build this kernel only for amd64, but have you considered including the following fixup? 83bdc7275e62 random32: remove net_rand_state from the latent entropy gcc plugin Kleber > --- > 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. >
On Tue, Sep 15, 2020 at 11:56:42AM +0200, Kleber Souza wrote: > On 09.09.20 22:01, Thadeu Lima de Souza Cascardo wrote: > > From: Willy Tarreau <w@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@gmail.com> > > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > > Cc: Eric Dumazet <edumazet@google.com> > > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > > Cc: Andy Lutomirski <luto@kernel.org> > > Cc: Kees Cook <keescook@chromium.org> > > Cc: Thomas Gleixner <tglx@linutronix.de> > > Cc: Peter Zijlstra <peterz@infradead.org> > > Cc: <stable@vger.kernel.org> > > Signed-off-by: Willy Tarreau <w@1wt.eu> > > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > > CVE-2020-16166 > > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> > > This commit introduces build errors/warnings in some non-x86 arches > which are fixed by the following commits: > > 0c83b277ada7 powerpc: Fix circular dependency between percpu.h and mmu.h > aa54ea903abb ARM: percpu.h: fix build error > 1c9df907da83 random: fix circular include dependency on arm64 after addition of percpu.h > 835d1c3a9879 arm64: Drop unnecessary include from asm/smp.h > > We probably don't care about those as we build this kernel only > for amd64, but have you considered including the following fixup? > > 83bdc7275e62 random32: remove net_rand_state from the latent entropy gcc plugin > Yes, I took those into consideration and ignored because they wouldn't cause problems with oem-5.6. So, I went with the minimal backport, tested that it builds on all supported architectures (that is, only amd64), and decided to close the issue for a kernel that won't live too much more. Thanks. Cascardo. > > Kleber > > > --- > > 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. > > >
On 09.09.20 22:01, Thadeu Lima de Souza Cascardo wrote: > From: Willy Tarreau <w@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@gmail.com> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Kees Cook <keescook@chromium.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Willy Tarreau <w@1wt.eu> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > CVE-2020-16166 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Thanks Thadeu for the additional clarification. The fix looks good to me. Acked-by: Kleber Sacilotto de Souza <kleber.souza@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. >
On 09.09.20 22:01, Thadeu Lima de Souza Cascardo wrote: > From: Willy Tarreau <w@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@gmail.com> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Kees Cook <keescook@chromium.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Willy Tarreau <w@1wt.eu> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > CVE-2020-16166 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Acked-by: Stefan Bader <stefan.bader@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. >
On 9.9.2020 23.01, Thadeu Lima de Souza Cascardo wrote: > From: Willy Tarreau <w@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@gmail.com> > Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Kees Cook <keescook@chromium.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: <stable@vger.kernel.org> > Signed-off-by: Willy Tarreau <w@1wt.eu> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > (cherry picked from commit f227e3ec3b5cad859ad15666874405e8c1bbc1d4) > CVE-2020-16166 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@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. > applied to oem-5.6, thanks
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.