Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: x86/aegis - Fix sleeping when disallowed on PREEMPT_RT

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>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Eric Biggers and committed by
Herbert Xu
c7f49dad c963ff0e

+6 -2
+6 -2
arch/x86/crypto/aegis128-aesni-glue.c
··· 119 119 walk->dst.virt.addr, 120 120 round_down(walk->nbytes, 121 121 AEGIS128_BLOCK_SIZE)); 122 + kernel_fpu_end(); 122 123 skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); 124 + kernel_fpu_begin(); 123 125 } 124 126 125 127 if (walk->nbytes) { ··· 133 131 aegis128_aesni_dec_tail(state, walk->src.virt.addr, 134 132 walk->dst.virt.addr, 135 133 walk->nbytes); 134 + kernel_fpu_end(); 136 135 skcipher_walk_done(walk, 0); 136 + kernel_fpu_begin(); 137 137 } 138 138 } 139 139 ··· 180 176 struct aegis_state state; 181 177 182 178 if (enc) 183 - skcipher_walk_aead_encrypt(&walk, req, true); 179 + skcipher_walk_aead_encrypt(&walk, req, false); 184 180 else 185 - skcipher_walk_aead_decrypt(&walk, req, true); 181 + skcipher_walk_aead_decrypt(&walk, req, false); 186 182 187 183 kernel_fpu_begin(); 188 184