summaryrefslogtreecommitdiffstats
path: root/fs/pstore
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2018-03-07 15:18:33 -0500
committerKees Cook <keescook@chromium.org>2018-03-07 15:47:06 -0500
commitf2531f1976d98a7a4328da7f3cbf31b7c1927738 (patch)
treefa32c230298182b5124ebb32ab2f2de287972d47 /fs/pstore
parentfe1d475888eecf1319458ee916e642e3e5e41c28 (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.c29
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
110static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, 110static 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}