Skip to content

Commit

Permalink
mm/slab.c: fix SLAB freelist randomization duplicate entries
Browse files Browse the repository at this point in the history
This patch fixes a bug in the freelist randomization code.  When a high
random number is used, the freelist will contain duplicate entries.  It
will result in different allocations sharing the same chunk.

It will result in odd behaviours and crashes.  It should be uncommon but
it depends on the machines.  We saw it happening more often on some
machines (every few hours of running tests).

Fixes: c7ce4f6 ("mm: SLAB freelist randomization")
Link: http://lkml.kernel.org/r/20170103181908.143178-1-thgarnie@google.com
Signed-off-by: John Sperbeck <jsperbeck@google.com>
Signed-off-by: Thomas Garnier <thgarnie@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
John Sperbeck authored and torvalds committed Jan 11, 2017
1 parent b09ab05 commit c4e490c
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions mm/slab.c
Original file line number Diff line number Diff line change
Expand Up @@ -2457,7 +2457,6 @@ union freelist_init_state {
unsigned int pos;
unsigned int *list;
unsigned int count;
unsigned int rand;
};
struct rnd_state rnd_state;
};
Expand All @@ -2483,8 +2482,7 @@ static bool freelist_state_initialize(union freelist_init_state *state,
} else {
state->list = cachep->random_seq;
state->count = count;
state->pos = 0;
state->rand = rand;
state->pos = rand % count;
ret = true;
}
return ret;
Expand All @@ -2493,7 +2491,9 @@ static bool freelist_state_initialize(union freelist_init_state *state,
/* Get the next entry on the list and randomize it using a random shift */
static freelist_idx_t next_random_slot(union freelist_init_state *state)
{
return (state->list[state->pos++] + state->rand) % state->count;
if (state->pos >= state->count)
state->pos = 0;
return state->list[state->pos++];
}

/* Swap two freelist entries */
Expand Down

0 comments on commit c4e490c

Please sign in to comment.