diff options
-rw-r--r-- | include/linux/slab_def.h | 2 | ||||
-rw-r--r-- | mm/slab.c | 80 | ||||
-rw-r--r-- | mm/slab.h | 14 | ||||
-rw-r--r-- | mm/slab_common.c | 47 |
4 files changed, 82 insertions, 61 deletions
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 8694f7a5d92b..339ba027ade9 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h | |||
@@ -81,7 +81,7 @@ struct kmem_cache { | |||
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | #ifdef CONFIG_SLAB_FREELIST_RANDOM | 83 | #ifdef CONFIG_SLAB_FREELIST_RANDOM |
84 | void *random_seq; | 84 | unsigned int *random_seq; |
85 | #endif | 85 | #endif |
86 | 86 | ||
87 | struct kmem_cache_node *node[MAX_NUMNODES]; | 87 | struct kmem_cache_node *node[MAX_NUMNODES]; |
@@ -1236,61 +1236,6 @@ static void __init set_up_node(struct kmem_cache *cachep, int index) | |||
1236 | } | 1236 | } |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | #ifdef CONFIG_SLAB_FREELIST_RANDOM | ||
1240 | static void freelist_randomize(struct rnd_state *state, freelist_idx_t *list, | ||
1241 | size_t count) | ||
1242 | { | ||
1243 | size_t i; | ||
1244 | unsigned int rand; | ||
1245 | |||
1246 | for (i = 0; i < count; i++) | ||
1247 | list[i] = i; | ||
1248 | |||
1249 | /* Fisher-Yates shuffle */ | ||
1250 | for (i = count - 1; i > 0; i--) { | ||
1251 | rand = prandom_u32_state(state); | ||
1252 | rand %= (i + 1); | ||
1253 | swap(list[i], list[rand]); | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | /* Create a random sequence per cache */ | ||
1258 | static int cache_random_seq_create(struct kmem_cache *cachep, gfp_t gfp) | ||
1259 | { | ||
1260 | unsigned int seed, count = cachep->num; | ||
1261 | struct rnd_state state; | ||
1262 | |||
1263 | if (count < 2) | ||
1264 | return 0; | ||
1265 | |||
1266 | /* If it fails, we will just use the global lists */ | ||
1267 | cachep->random_seq = kcalloc(count, sizeof(freelist_idx_t), gfp); | ||
1268 | if (!cachep->random_seq) | ||
1269 | return -ENOMEM; | ||
1270 | |||
1271 | /* Get best entropy at this stage */ | ||
1272 | get_random_bytes_arch(&seed, sizeof(seed)); | ||
1273 | prandom_seed_state(&state, seed); | ||
1274 | |||
1275 | freelist_randomize(&state, cachep->random_seq, count); | ||
1276 | return 0; | ||
1277 | } | ||
1278 | |||
1279 | /* Destroy the per-cache random freelist sequence */ | ||
1280 | static void cache_random_seq_destroy(struct kmem_cache *cachep) | ||
1281 | { | ||
1282 | kfree(cachep->random_seq); | ||
1283 | cachep->random_seq = NULL; | ||
1284 | } | ||
1285 | #else | ||
1286 | static inline int cache_random_seq_create(struct kmem_cache *cachep, gfp_t gfp) | ||
1287 | { | ||
1288 | return 0; | ||
1289 | } | ||
1290 | static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { } | ||
1291 | #endif /* CONFIG_SLAB_FREELIST_RANDOM */ | ||
1292 | |||
1293 | |||
1294 | /* | 1239 | /* |
1295 | * Initialisation. Called after the page allocator have been initialised and | 1240 | * Initialisation. Called after the page allocator have been initialised and |
1296 | * before smp_init(). | 1241 | * before smp_init(). |
@@ -2535,7 +2480,7 @@ static void cache_init_objs_debug(struct kmem_cache *cachep, struct page *page) | |||
2535 | union freelist_init_state { | 2480 | union freelist_init_state { |
2536 | struct { | 2481 | struct { |
2537 | unsigned int pos; | 2482 | unsigned int pos; |
2538 | freelist_idx_t *list; | 2483 | unsigned int *list; |
2539 | unsigned int count; | 2484 | unsigned int count; |
2540 | unsigned int rand; | 2485 | unsigned int rand; |
2541 | }; | 2486 | }; |
@@ -2554,7 +2499,7 @@ static bool freelist_state_initialize(union freelist_init_state *state, | |||
2554 | unsigned int rand; | 2499 | unsigned int rand; |
2555 | 2500 | ||
2556 | /* Use best entropy available to define a random shift */ | 2501 | /* Use best entropy available to define a random shift */ |
2557 | get_random_bytes_arch(&rand, sizeof(rand)); | 2502 | rand = get_random_int(); |
2558 | 2503 | ||
2559 | /* Use a random state if the pre-computed list is not available */ | 2504 | /* Use a random state if the pre-computed list is not available */ |
2560 | if (!cachep->random_seq) { | 2505 | if (!cachep->random_seq) { |
@@ -2576,13 +2521,20 @@ static freelist_idx_t next_random_slot(union freelist_init_state *state) | |||
2576 | return (state->list[state->pos++] + state->rand) % state->count; | 2521 | return (state->list[state->pos++] + state->rand) % state->count; |
2577 | } | 2522 | } |
2578 | 2523 | ||
2524 | /* Swap two freelist entries */ | ||
2525 | static void swap_free_obj(struct page *page, unsigned int a, unsigned int b) | ||
2526 | { | ||
2527 | swap(((freelist_idx_t *)page->freelist)[a], | ||
2528 | ((freelist_idx_t *)page->freelist)[b]); | ||
2529 | } | ||
2530 | |||
2579 | /* | 2531 | /* |
2580 | * Shuffle the freelist initialization state based on pre-computed lists. | 2532 | * Shuffle the freelist initialization state based on pre-computed lists. |
2581 | * return true if the list was successfully shuffled, false otherwise. | 2533 | * return true if the list was successfully shuffled, false otherwise. |
2582 | */ | 2534 | */ |
2583 | static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page) | 2535 | static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page) |
2584 | { | 2536 | { |
2585 | unsigned int objfreelist = 0, i, count = cachep->num; | 2537 | unsigned int objfreelist = 0, i, rand, count = cachep->num; |
2586 | union freelist_init_state state; | 2538 | union freelist_init_state state; |
2587 | bool precomputed; | 2539 | bool precomputed; |
2588 | 2540 | ||
@@ -2607,7 +2559,15 @@ static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page) | |||
2607 | * Later use a pre-computed list for speed. | 2559 | * Later use a pre-computed list for speed. |
2608 | */ | 2560 | */ |
2609 | if (!precomputed) { | 2561 | if (!precomputed) { |
2610 | freelist_randomize(&state.rnd_state, page->freelist, count); | 2562 | for (i = 0; i < count; i++) |
2563 | set_free_obj(page, i, i); | ||
2564 | |||
2565 | /* Fisher-Yates shuffle */ | ||
2566 | for (i = count - 1; i > 0; i--) { | ||
2567 | rand = prandom_u32_state(&state.rnd_state); | ||
2568 | rand %= (i + 1); | ||
2569 | swap_free_obj(page, i, rand); | ||
2570 | } | ||
2611 | } else { | 2571 | } else { |
2612 | for (i = 0; i < count; i++) | 2572 | for (i = 0; i < count; i++) |
2613 | set_free_obj(page, i, next_random_slot(&state)); | 2573 | set_free_obj(page, i, next_random_slot(&state)); |
@@ -3979,7 +3939,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) | |||
3979 | int shared = 0; | 3939 | int shared = 0; |
3980 | int batchcount = 0; | 3940 | int batchcount = 0; |
3981 | 3941 | ||
3982 | err = cache_random_seq_create(cachep, gfp); | 3942 | err = cache_random_seq_create(cachep, cachep->num, gfp); |
3983 | if (err) | 3943 | if (err) |
3984 | goto end; | 3944 | goto end; |
3985 | 3945 | ||
@@ -42,6 +42,7 @@ struct kmem_cache { | |||
42 | #include <linux/kmemcheck.h> | 42 | #include <linux/kmemcheck.h> |
43 | #include <linux/kasan.h> | 43 | #include <linux/kasan.h> |
44 | #include <linux/kmemleak.h> | 44 | #include <linux/kmemleak.h> |
45 | #include <linux/random.h> | ||
45 | 46 | ||
46 | /* | 47 | /* |
47 | * State of the slab allocator. | 48 | * State of the slab allocator. |
@@ -464,4 +465,17 @@ int memcg_slab_show(struct seq_file *m, void *p); | |||
464 | 465 | ||
465 | void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr); | 466 | void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr); |
466 | 467 | ||
468 | #ifdef CONFIG_SLAB_FREELIST_RANDOM | ||
469 | int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count, | ||
470 | gfp_t gfp); | ||
471 | void cache_random_seq_destroy(struct kmem_cache *cachep); | ||
472 | #else | ||
473 | static inline int cache_random_seq_create(struct kmem_cache *cachep, | ||
474 | unsigned int count, gfp_t gfp) | ||
475 | { | ||
476 | return 0; | ||
477 | } | ||
478 | static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { } | ||
479 | #endif /* CONFIG_SLAB_FREELIST_RANDOM */ | ||
480 | |||
467 | #endif /* MM_SLAB_H */ | 481 | #endif /* MM_SLAB_H */ |
diff --git a/mm/slab_common.c b/mm/slab_common.c index 82317abb03ed..da88c1588752 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
@@ -1030,6 +1030,53 @@ void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order) | |||
1030 | EXPORT_SYMBOL(kmalloc_order_trace); | 1030 | EXPORT_SYMBOL(kmalloc_order_trace); |
1031 | #endif | 1031 | #endif |
1032 | 1032 | ||
1033 | #ifdef CONFIG_SLAB_FREELIST_RANDOM | ||
1034 | /* Randomize a generic freelist */ | ||
1035 | static void freelist_randomize(struct rnd_state *state, unsigned int *list, | ||
1036 | size_t count) | ||
1037 | { | ||
1038 | size_t i; | ||
1039 | unsigned int rand; | ||
1040 | |||
1041 | for (i = 0; i < count; i++) | ||
1042 | list[i] = i; | ||
1043 | |||
1044 | /* Fisher-Yates shuffle */ | ||
1045 | for (i = count - 1; i > 0; i--) { | ||
1046 | rand = prandom_u32_state(state); | ||
1047 | rand %= (i + 1); | ||
1048 | swap(list[i], list[rand]); | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | /* Create a random sequence per cache */ | ||
1053 | int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count, | ||
1054 | gfp_t gfp) | ||
1055 | { | ||
1056 | struct rnd_state state; | ||
1057 | |||
1058 | if (count < 2 || cachep->random_seq) | ||
1059 | return 0; | ||
1060 | |||
1061 | cachep->random_seq = kcalloc(count, sizeof(unsigned int), gfp); | ||
1062 | if (!cachep->random_seq) | ||
1063 | return -ENOMEM; | ||
1064 | |||
1065 | /* Get best entropy at this stage of boot */ | ||
1066 | prandom_seed_state(&state, get_random_long()); | ||
1067 | |||
1068 | freelist_randomize(&state, cachep->random_seq, count); | ||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | /* Destroy the per-cache random freelist sequence */ | ||
1073 | void cache_random_seq_destroy(struct kmem_cache *cachep) | ||
1074 | { | ||
1075 | kfree(cachep->random_seq); | ||
1076 | cachep->random_seq = NULL; | ||
1077 | } | ||
1078 | #endif /* CONFIG_SLAB_FREELIST_RANDOM */ | ||
1079 | |||
1033 | #ifdef CONFIG_SLABINFO | 1080 | #ifdef CONFIG_SLABINFO |
1034 | 1081 | ||
1035 | #ifdef CONFIG_SLAB | 1082 | #ifdef CONFIG_SLAB |