skcipher_walk_done() can call kfree(), which takes a spinlock, which makes it incorrect to call while preemption is disabled on PREEMPT_RT. Therefore, end the kernel-mode FPU section before calling skcipher_walk_done(), and restart it afterwards.
Moreover, pass atomic=false to skcipher_walk_aead_encrypt() instead of atomic=true. The point of atomic=true was to make skcipher_walk_done() safe to call while in a kernel-mode FPU section, but that does not actually work. So just use the usual atomic=false.
Fixes: 1d373d4e8e15 ("crypto: x86 - Add optimized AEGIS implementations") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers ebiggers@kernel.org --- arch/x86/crypto/aegis128-aesni-glue.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/x86/crypto/aegis128-aesni-glue.c b/arch/x86/crypto/aegis128-aesni-glue.c index f1b6d40154e35..3cb5c193038bb 100644 --- a/arch/x86/crypto/aegis128-aesni-glue.c +++ b/arch/x86/crypto/aegis128-aesni-glue.c @@ -117,11 +117,13 @@ crypto_aegis128_aesni_process_crypt(struct aegis_state *state, else aegis128_aesni_dec(state, walk->src.virt.addr, walk->dst.virt.addr, round_down(walk->nbytes, AEGIS128_BLOCK_SIZE)); + kernel_fpu_end(); skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); + kernel_fpu_begin(); }
if (walk->nbytes) { if (enc) aegis128_aesni_enc_tail(state, walk->src.virt.addr, @@ -129,11 +131,13 @@ crypto_aegis128_aesni_process_crypt(struct aegis_state *state, walk->nbytes); else aegis128_aesni_dec_tail(state, walk->src.virt.addr, walk->dst.virt.addr, walk->nbytes); + kernel_fpu_end(); skcipher_walk_done(walk, 0); + kernel_fpu_begin(); } }
static struct aegis_ctx *crypto_aegis128_aesni_ctx(struct crypto_aead *aead) { @@ -174,13 +178,13 @@ crypto_aegis128_aesni_crypt(struct aead_request *req, struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm); struct skcipher_walk walk; struct aegis_state state;
if (enc) - skcipher_walk_aead_encrypt(&walk, req, true); + skcipher_walk_aead_encrypt(&walk, req, false); else - skcipher_walk_aead_decrypt(&walk, req, true); + skcipher_walk_aead_decrypt(&walk, req, false);
kernel_fpu_begin();
aegis128_aesni_init(&state, &ctx->key, req->iv); crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen);
linux-stable-mirror@lists.linaro.org