diff options
author | Kees Cook <keescook@chromium.org> | 2018-03-07 15:18:33 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2018-03-07 15:47:06 -0500 |
commit | f2531f1976d98a7a4328da7f3cbf31b7c1927738 (patch) | |
tree | fa32c230298182b5124ebb32ab2f2de287972d47 /fs/pstore | |
parent | fe1d475888eecf1319458ee916e642e3e5e41c28 (diff) |
pstore/ram: Do not use stack VLA for parity workspace
Instead of using a stack VLA for the parity workspace, preallocate a
memory region. The preallocation is done to keep from needing to perform
allocations during crash dump writing, etc. This also fixes a missed
release of librs on free.
Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'fs/pstore')
-rw-r--r-- | fs/pstore/ram_core.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index e11672aa4575..951a14edcf51 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c | |||
@@ -98,24 +98,23 @@ static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, | |||
98 | uint8_t *data, size_t len, uint8_t *ecc) | 98 | uint8_t *data, size_t len, uint8_t *ecc) |
99 | { | 99 | { |
100 | int i; | 100 | int i; |
101 | uint16_t par[prz->ecc_info.ecc_size]; | ||
102 | 101 | ||
103 | /* Initialize the parity buffer */ | 102 | /* Initialize the parity buffer */ |
104 | memset(par, 0, sizeof(par)); | 103 | memset(prz->ecc_info.par, 0, |
105 | encode_rs8(prz->rs_decoder, data, len, par, 0); | 104 | prz->ecc_info.ecc_size * sizeof(prz->ecc_info.par[0])); |
105 | encode_rs8(prz->rs_decoder, data, len, prz->ecc_info.par, 0); | ||
106 | for (i = 0; i < prz->ecc_info.ecc_size; i++) | 106 | for (i = 0; i < prz->ecc_info.ecc_size; i++) |
107 | ecc[i] = par[i]; | 107 | ecc[i] = prz->ecc_info.par[i]; |
108 | } | 108 | } |
109 | 109 | ||
110 | static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, | 110 | static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, |
111 | void *data, size_t len, uint8_t *ecc) | 111 | void *data, size_t len, uint8_t *ecc) |
112 | { | 112 | { |
113 | int i; | 113 | int i; |
114 | uint16_t par[prz->ecc_info.ecc_size]; | ||
115 | 114 | ||
116 | for (i = 0; i < prz->ecc_info.ecc_size; i++) | 115 | for (i = 0; i < prz->ecc_info.ecc_size; i++) |
117 | par[i] = ecc[i]; | 116 | prz->ecc_info.par[i] = ecc[i]; |
118 | return decode_rs8(prz->rs_decoder, data, par, len, | 117 | return decode_rs8(prz->rs_decoder, data, prz->ecc_info.par, len, |
119 | NULL, 0, NULL, 0, NULL); | 118 | NULL, 0, NULL, 0, NULL); |
120 | } | 119 | } |
121 | 120 | ||
@@ -228,6 +227,15 @@ static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, | |||
228 | return -EINVAL; | 227 | return -EINVAL; |
229 | } | 228 | } |
230 | 229 | ||
230 | /* allocate workspace instead of using stack VLA */ | ||
231 | prz->ecc_info.par = kmalloc_array(prz->ecc_info.ecc_size, | ||
232 | sizeof(*prz->ecc_info.par), | ||
233 | GFP_KERNEL); | ||
234 | if (!prz->ecc_info.par) { | ||
235 | pr_err("cannot allocate ECC parity workspace\n"); | ||
236 | return -ENOMEM; | ||
237 | } | ||
238 | |||
231 | prz->corrected_bytes = 0; | 239 | prz->corrected_bytes = 0; |
232 | prz->bad_blocks = 0; | 240 | prz->bad_blocks = 0; |
233 | 241 | ||
@@ -514,6 +522,13 @@ void persistent_ram_free(struct persistent_ram_zone *prz) | |||
514 | } | 522 | } |
515 | prz->vaddr = NULL; | 523 | prz->vaddr = NULL; |
516 | } | 524 | } |
525 | if (prz->rs_decoder) { | ||
526 | free_rs(prz->rs_decoder); | ||
527 | prz->rs_decoder = NULL; | ||
528 | } | ||
529 | kfree(prz->ecc_info.par); | ||
530 | prz->ecc_info.par = NULL; | ||
531 | |||
517 | persistent_ram_free_old(prz); | 532 | persistent_ram_free_old(prz); |
518 | kfree(prz); | 533 | kfree(prz); |
519 | } | 534 | } |