| From 8ac18e4281d2e8e094e23f5d48db10def368397b Mon Sep 17 00:00:00 2001 |
| From: Arnd Bergmann <arnd@arndb.de> |
| Date: Mon, 17 Jun 2019 15:25:17 +0200 |
| Subject: [PATCH] crypto: sun4i-ss - reduce stack usage |
| |
| commit 8d3bcb9900ca5a193088c1f2d20c92865482368b upstream. |
| |
| After the latest addition, the stack usage of sun4i_ss_cipher_poll |
| grew beyond the warning limit when KASAN is enabled: |
| |
| drivers/crypto/sunxi-ss/sun4i-ss-cipher.c:118:12: error: stack frame size of 1152 bytes in function 'sun4i_ss_cipher_poll' [-Werror,-Wframe-larger-than=] |
| static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| |
| Reduce it in three ways: |
| |
| - split out the new code into a separate function so its stack |
| usage can overlap that of the sun4i_ss_opti_poll() code path |
| - mark both special cases as noinline_for_stack, which should |
| ideally result in a tail call that frees the rest of the |
| stack |
| - move the buf and obuf variables into the code blocks in |
| which they are used. |
| |
| The three separate functions now use 144, 640 and 304 bytes of kernel |
| stack, respectively. |
| |
| Fixes: 0ae1f46c55f8 ("crypto: sun4i-ss - fallback when length is not multiple of blocksize") |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| Tested-by: Corentin LABBE <clabbe.montjoie@gmail.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c |
| index ef674fefb0b5..e74ba066d002 100644 |
| --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c |
| +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c |
| @@ -12,7 +12,7 @@ |
| */ |
| #include "sun4i-ss.h" |
| |
| -static int sun4i_ss_opti_poll(struct skcipher_request *areq) |
| +static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) |
| { |
| struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); |
| struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); |
| @@ -116,6 +116,29 @@ static int sun4i_ss_opti_poll(struct skcipher_request *areq) |
| return err; |
| } |
| |
| + |
| +static int noinline_for_stack sun4i_ss_cipher_poll_fallback(struct skcipher_request *areq) |
| +{ |
| + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); |
| + struct sun4i_tfm_ctx *op = crypto_skcipher_ctx(tfm); |
| + struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); |
| + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, op->fallback_tfm); |
| + int err; |
| + |
| + skcipher_request_set_sync_tfm(subreq, op->fallback_tfm); |
| + skcipher_request_set_callback(subreq, areq->base.flags, NULL, |
| + NULL); |
| + skcipher_request_set_crypt(subreq, areq->src, areq->dst, |
| + areq->cryptlen, areq->iv); |
| + if (ctx->mode & SS_DECRYPTION) |
| + err = crypto_skcipher_decrypt(subreq); |
| + else |
| + err = crypto_skcipher_encrypt(subreq); |
| + skcipher_request_zero(subreq); |
| + |
| + return err; |
| +} |
| + |
| /* Generic function that support SG with size not multiple of 4 */ |
| static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| { |
| @@ -142,8 +165,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| unsigned int todo; |
| struct sg_mapping_iter mi, mo; |
| unsigned int oi, oo; /* offset for in and out */ |
| - char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ |
| - char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ |
| unsigned int ob = 0; /* offset in buf */ |
| unsigned int obo = 0; /* offset in bufo*/ |
| unsigned int obl = 0; /* length of data in bufo */ |
| @@ -180,20 +201,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| if (no_chunk == 1 && !need_fallback) |
| return sun4i_ss_opti_poll(areq); |
| |
| - if (need_fallback) { |
| - SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, op->fallback_tfm); |
| - skcipher_request_set_sync_tfm(subreq, op->fallback_tfm); |
| - skcipher_request_set_callback(subreq, areq->base.flags, NULL, |
| - NULL); |
| - skcipher_request_set_crypt(subreq, areq->src, areq->dst, |
| - areq->cryptlen, areq->iv); |
| - if (ctx->mode & SS_DECRYPTION) |
| - err = crypto_skcipher_decrypt(subreq); |
| - else |
| - err = crypto_skcipher_encrypt(subreq); |
| - skcipher_request_zero(subreq); |
| - return err; |
| - } |
| + if (need_fallback) |
| + return sun4i_ss_cipher_poll_fallback(areq); |
| |
| spin_lock_irqsave(&ss->slock, flags); |
| |
| @@ -226,6 +235,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| |
| while (oleft) { |
| if (ileft) { |
| + char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ |
| + |
| /* |
| * todo is the number of consecutive 4byte word that we |
| * can read from current SG |
| @@ -286,6 +297,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) |
| oo = 0; |
| } |
| } else { |
| + char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ |
| + |
| /* |
| * read obl bytes in bufo, we read at maximum for |
| * emptying the device |
| -- |
| 2.27.0 |
| |