Skip to content

Commit 02361bc

Browse files
keesBoris Brezillon
authored andcommitted
lib/bch: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this allocates a fixed size stack array to cover the range needed for bch. This was done instead of a preallocation on the SLAB due to performance reasons, shown by Ivan Djelic: little-endian, type sizes: int=4 long=8 longlong=8 cpu: Intel(R) Core(TM) i5 CPU         650  @ 3.20GHz calibration: iter=4.9143µs niter=2034 nsamples=200 m=13 t=4   Buffer allocation |  Encoding throughput (Mbit/s) ---------------------------------------------------  on-stack, VLA      |   3988  on-stack, fixed    |   4494  kmalloc            |   1967 So this change actually improves performance too, it seems. The resulting stack allocation can get rather large; without CONFIG_BCH_CONST_PARAMS, it will allocate 4096 bytes, which trips the stack size checking: lib/bch.c: In function ‘encode_bch’: lib/bch.c:261:1: warning: the frame size of 4432 bytes is larger than 2048 bytes [-Wframe-larger-than=] Even the default case for "allmodconfig" (with CONFIG_BCH_CONST_M=14 and CONFIG_BCH_CONST_T=4) would have started throwing a warning: lib/bch.c: In function ‘encode_bch’: lib/bch.c:261:1: warning: the frame size of 2288 bytes is larger than 2048 bytes [-Wframe-larger-than=] But this is how large it's always been; it was just hidden from the checker because it was a VLA. So the Makefile has been adjusted to silence this warning for anything smaller than 4500 bytes, which should provide room for normal cases, but still low enough to catch any future pathological situations. [1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Ivan Djelic <ivan.djelic@parrot.com> Tested-by: Ivan Djelic <ivan.djelic@parrot.com> Acked-by: Boris Brezillon <boris.brezillon@bootlin.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
1 parent ce397d2 commit 02361bc

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

lib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
123123
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
124124
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
125125
obj-$(CONFIG_BCH) += bch.o
126+
CFLAGS_bch.o := $(call cc-option,-Wframe-larger-than=4500)
126127
obj-$(CONFIG_LZO_COMPRESS) += lzo/
127128
obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
128129
obj-$(CONFIG_LZ4_COMPRESS) += lz4/

lib/bch.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,22 @@
7878
#define GF_M(_p) (CONFIG_BCH_CONST_M)
7979
#define GF_T(_p) (CONFIG_BCH_CONST_T)
8080
#define GF_N(_p) ((1 << (CONFIG_BCH_CONST_M))-1)
81+
#define BCH_MAX_M (CONFIG_BCH_CONST_M)
8182
#else
8283
#define GF_M(_p) ((_p)->m)
8384
#define GF_T(_p) ((_p)->t)
8485
#define GF_N(_p) ((_p)->n)
86+
#define BCH_MAX_M 15
8587
#endif
8688

89+
#define BCH_MAX_T (((1 << BCH_MAX_M) - 1) / BCH_MAX_M)
90+
8791
#define BCH_ECC_WORDS(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
8892
#define BCH_ECC_BYTES(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
8993

94+
#define BCH_ECC_MAX_WORDS DIV_ROUND_UP(BCH_MAX_M * BCH_MAX_T, 32)
95+
#define BCH_ECC_MAX_BYTES DIV_ROUND_UP(BCH_MAX_M * BCH_MAX_T, 8)
96+
9097
#ifndef dbg
9198
#define dbg(_fmt, args...) do {} while (0)
9299
#endif
@@ -187,7 +194,8 @@ void encode_bch(struct bch_control *bch, const uint8_t *data,
187194
const unsigned int l = BCH_ECC_WORDS(bch)-1;
188195
unsigned int i, mlen;
189196
unsigned long m;
190-
uint32_t w, r[l+1];
197+
uint32_t w, r[BCH_ECC_MAX_WORDS];
198+
const size_t r_bytes = BCH_ECC_WORDS(bch) * sizeof(*r);
191199
const uint32_t * const tab0 = bch->mod8_tab;
192200
const uint32_t * const tab1 = tab0 + 256*(l+1);
193201
const uint32_t * const tab2 = tab1 + 256*(l+1);
@@ -198,7 +206,7 @@ void encode_bch(struct bch_control *bch, const uint8_t *data,
198206
/* load ecc parity bytes into internal 32-bit buffer */
199207
load_ecc8(bch, bch->ecc_buf, ecc);
200208
} else {
201-
memset(bch->ecc_buf, 0, sizeof(r));
209+
memset(bch->ecc_buf, 0, r_bytes);
202210
}
203211

204212
/* process first unaligned data bytes */
@@ -215,7 +223,7 @@ void encode_bch(struct bch_control *bch, const uint8_t *data,
215223
mlen = len/4;
216224
data += 4*mlen;
217225
len -= 4*mlen;
218-
memcpy(r, bch->ecc_buf, sizeof(r));
226+
memcpy(r, bch->ecc_buf, r_bytes);
219227

220228
/*
221229
* split each 32-bit word into 4 polynomials of weight 8 as follows:
@@ -241,7 +249,7 @@ void encode_bch(struct bch_control *bch, const uint8_t *data,
241249

242250
r[l] = p0[l]^p1[l]^p2[l]^p3[l];
243251
}
244-
memcpy(bch->ecc_buf, r, sizeof(r));
252+
memcpy(bch->ecc_buf, r, r_bytes);
245253

246254
/* process last unaligned bytes */
247255
if (len)
@@ -434,7 +442,7 @@ static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
434442
{
435443
const int m = GF_M(bch);
436444
unsigned int tmp, mask;
437-
int rem, c, r, p, k, param[m];
445+
int rem, c, r, p, k, param[BCH_MAX_M];
438446

439447
k = 0;
440448
mask = 1 << m;
@@ -1114,7 +1122,7 @@ static int build_deg2_base(struct bch_control *bch)
11141122
{
11151123
const int m = GF_M(bch);
11161124
int i, j, r;
1117-
unsigned int sum, x, y, remaining, ak = 0, xi[m];
1125+
unsigned int sum, x, y, remaining, ak = 0, xi[BCH_MAX_M];
11181126

11191127
/* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
11201128
for (i = 0; i < m; i++) {
@@ -1254,7 +1262,6 @@ struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
12541262
struct bch_control *bch = NULL;
12551263

12561264
const int min_m = 5;
1257-
const int max_m = 15;
12581265

12591266
/* default primitive polynomials */
12601267
static const unsigned int prim_poly_tab[] = {
@@ -1270,7 +1277,7 @@ struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
12701277
goto fail;
12711278
}
12721279
#endif
1273-
if ((m < min_m) || (m > max_m))
1280+
if ((m < min_m) || (m > BCH_MAX_M))
12741281
/*
12751282
* values of m greater than 15 are not currently supported;
12761283
* supporting m > 15 would require changing table base type

0 commit comments

Comments
 (0)