Commit 45888b40 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Kees Cook

rslib: Allocate decoder buffers to avoid VLAs

To get rid of the variable length arrays on stack in the RS decoder it's
necessary to allocate the decoder buffers per control structure instance.

All usage sites have been checked for potential parallel decoder usage and
fixed where necessary. Kees confirmed that the pstore decoding is strictly
single threaded so there should be no surprises.

Allocate them in the rs control structure sized depending on the number of
roots for the chosen codec and adapt the decoder code to make use of them.

Document the fact that decode operations based on a particular rs control
instance cannot run in parallel and the caller has to ensure that as it's
not possible to provide a proper locking construct which fits all use
cases.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarKees Cook <keescook@chromium.org>
Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Segher Boessenkool <segher@kernel.crashing.org>
Cc: Kernel Hardening <kernel-hardening@lists.openwall.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Mike Snitzer <snitzer@redhat.com>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Colin Cross <ccross@android.com>
Cc: Andrew Morton <akpm@linuxfoundation.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alasdair Kergon <agk@redhat.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent 964dfce9
...@@ -50,9 +50,11 @@ struct rs_codec { ...@@ -50,9 +50,11 @@ struct rs_codec {
/** /**
* struct rs_control - rs control structure per instance * struct rs_control - rs control structure per instance
* @codec: The codec used for this instance * @codec: The codec used for this instance
* @buffers: Internal scratch buffers used in calls to decode_rs()
*/ */
struct rs_control { struct rs_control {
struct rs_codec *codec; struct rs_codec *codec;
uint16_t buffers[0];
}; };
/* General purpose RS codec, 8-bit data width, symbol width 1-15 bit */ /* General purpose RS codec, 8-bit data width, symbol width 1-15 bit */
......
...@@ -21,16 +21,22 @@ ...@@ -21,16 +21,22 @@
uint16_t *alpha_to = rs->alpha_to; uint16_t *alpha_to = rs->alpha_to;
uint16_t *index_of = rs->index_of; uint16_t *index_of = rs->index_of;
uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error; uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
/* Err+Eras Locator poly and syndrome poly The maximum value
* of nroots is 8. So the necessary stack size will be about
* 220 bytes max.
*/
uint16_t lambda[nroots + 1], syn[nroots];
uint16_t b[nroots + 1], t[nroots + 1], omega[nroots + 1];
uint16_t root[nroots], reg[nroots + 1], loc[nroots];
int count = 0; int count = 0;
uint16_t msk = (uint16_t) rs->nn; uint16_t msk = (uint16_t) rs->nn;
/*
* The decoder buffers are in the rs control struct. They are
* arrays sized [nroots + 1]
*/
uint16_t *lambda = rsc->buffers + RS_DECODE_LAMBDA * (nroots + 1);
uint16_t *syn = rsc->buffers + RS_DECODE_SYN * (nroots + 1);
uint16_t *b = rsc->buffers + RS_DECODE_B * (nroots + 1);
uint16_t *t = rsc->buffers + RS_DECODE_T * (nroots + 1);
uint16_t *omega = rsc->buffers + RS_DECODE_OMEGA * (nroots + 1);
uint16_t *root = rsc->buffers + RS_DECODE_ROOT * (nroots + 1);
uint16_t *reg = rsc->buffers + RS_DECODE_REG * (nroots + 1);
uint16_t *loc = rsc->buffers + RS_DECODE_LOC * (nroots + 1);
/* Check length parameter for validity */ /* Check length parameter for validity */
pad = nn - nroots - len; pad = nn - nroots - len;
BUG_ON(pad < 0 || pad >= nn); BUG_ON(pad < 0 || pad >= nn);
......
...@@ -37,6 +37,18 @@ ...@@ -37,6 +37,18 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
enum {
RS_DECODE_LAMBDA,
RS_DECODE_SYN,
RS_DECODE_B,
RS_DECODE_T,
RS_DECODE_OMEGA,
RS_DECODE_ROOT,
RS_DECODE_REG,
RS_DECODE_LOC,
RS_DECODE_NUM_BUFFERS
};
/* This list holds all currently allocated rs codec structures */ /* This list holds all currently allocated rs codec structures */
static LIST_HEAD(codec_list); static LIST_HEAD(codec_list);
/* Protection for the list */ /* Protection for the list */
...@@ -204,6 +216,7 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, ...@@ -204,6 +216,7 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly,
{ {
struct list_head *tmp; struct list_head *tmp;
struct rs_control *rs; struct rs_control *rs;
unsigned int bsize;
/* Sanity checks */ /* Sanity checks */
if (symsize < 1) if (symsize < 1)
...@@ -215,7 +228,13 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, ...@@ -215,7 +228,13 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly,
if (nroots < 0 || nroots >= (1<<symsize)) if (nroots < 0 || nroots >= (1<<symsize))
return NULL; return NULL;
rs = kzalloc(sizeof(*rs), GFP_KERNEL); /*
* The decoder needs buffers in each control struct instance to
* avoid variable size or large fixed size allocations on
* stack. Size the buffers to arrays of [nroots + 1].
*/
bsize = sizeof(uint16_t) * RS_DECODE_NUM_BUFFERS * (nroots + 1);
rs = kzalloc(sizeof(*rs) + bsize, gfp);
if (!rs) if (!rs)
return NULL; return NULL;
...@@ -330,6 +349,11 @@ EXPORT_SYMBOL_GPL(encode_rs8); ...@@ -330,6 +349,11 @@ EXPORT_SYMBOL_GPL(encode_rs8);
* The syndrome and parity uses a uint16_t data type to enable * The syndrome and parity uses a uint16_t data type to enable
* symbol size > 8. The calling code must take care of decoding of the * symbol size > 8. The calling code must take care of decoding of the
* syndrome result and the received parity before calling this code. * syndrome result and the received parity before calling this code.
*
* Note: The rs_control struct @rsc contains buffers which are used for
* decoding, so the caller has to ensure that decoder invocations are
* serialized.
*
* Returns the number of corrected bits or -EBADMSG for uncorrectable errors. * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
*/ */
int decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len, int decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len,
...@@ -374,6 +398,11 @@ EXPORT_SYMBOL_GPL(encode_rs16); ...@@ -374,6 +398,11 @@ EXPORT_SYMBOL_GPL(encode_rs16);
* @corr: buffer to store correction bitmask on eras_pos * @corr: buffer to store correction bitmask on eras_pos
* *
* Each field in the data array contains up to symbol size bits of valid data. * Each field in the data array contains up to symbol size bits of valid data.
*
* Note: The rc_control struct @rsc contains buffers which are used for
* decoding, so the caller has to ensure that decoder invocations are
* serialized.
*
* Returns the number of corrected bits or -EBADMSG for uncorrectable errors. * Returns the number of corrected bits or -EBADMSG for uncorrectable errors.
*/ */
int decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len, int decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment