Skip to content

Commit

Permalink
random: Fix crashes with sparse node ids
Browse files Browse the repository at this point in the history
On a system with sparse node ids, eg. a powerpc system with 4 nodes
numbered like so:

  node   0: [mem 0x0000000000000000-0x00000007ffffffff]
  node   1: [mem 0x0000000800000000-0x0000000fffffffff]
  node  16: [mem 0x0000001000000000-0x00000017ffffffff]
  node  17: [mem 0x0000001800000000-0x0000001fffffffff]

The code in rand_initialize() will allocate 4 pointers for the pool
array, and initialise them correctly.

However when go to use the pool, in eg. extract_crng(), we use the
numa_node_id() to index into the array. For the higher numbered node ids
this leads to random memory corruption, depending on what was kmalloc'ed
adjacent to the pool array.

Fix it by using nr_node_ids to size the pool array.

Fixes: 1e7f583 ("random: make /dev/urandom scalable for silly userspace programs")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Michael Ellerman authored and Linus Torvalds committed Jul 31, 2016
1 parent 7f155c7 commit dd0f0cf
Showing 1 changed file with 2 additions and 3 deletions.
5 changes: 2 additions & 3 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
#include <linux/genhd.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/nodemask.h>
#include <linux/spinlock.h>
#include <linux/kthread.h>
#include <linux/percpu.h>
Expand Down Expand Up @@ -1656,7 +1657,6 @@ static int rand_initialize(void)
{
#ifdef CONFIG_NUMA
int i;
int num_nodes = num_possible_nodes();
struct crng_state *crng;
struct crng_state **pool;
#endif
Expand All @@ -1666,8 +1666,7 @@ static int rand_initialize(void)
crng_initialize(&primary_crng);

#ifdef CONFIG_NUMA
pool = kmalloc(num_nodes * sizeof(void *),
GFP_KERNEL|__GFP_NOFAIL|__GFP_ZERO);
pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
for_each_online_node(i) {
crng = kmalloc_node(sizeof(struct crng_state),
GFP_KERNEL | __GFP_NOFAIL, i);
Expand Down

0 comments on commit dd0f0cf

Please sign in to comment.