| From: Rabin Vincent <rabin.vincent@axis.com> |
| Date: Fri, 19 Dec 2014 13:36:08 +0100 |
| Subject: crypto: af_alg - fix backlog handling |
| |
| commit 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e upstream. |
| |
| If a request is backlogged, it's complete() handler will get called |
| twice: once with -EINPROGRESS, and once with the final error code. |
| |
| af_alg's complete handler, unlike other users, does not handle the |
| -EINPROGRESS but instead always completes the completion that recvmsg() |
| is waiting on. This can lead to a return to user space while the |
| request is still pending in the driver. If userspace closes the sockets |
| before the requests are handled by the driver, this will lead to |
| use-after-frees (and potential crashes) in the kernel due to the tfm |
| having been freed. |
| |
| The crashes can be easily reproduced (for example) by reducing the max |
| queue length in cryptod.c and running the following (from |
| http://www.chronox.de/libkcapi.html) on AES-NI capable hardware: |
| |
| $ while true; do kcapi -x 1 -e -c '__ecb-aes-aesni' \ |
| -k 00000000000000000000000000000000 \ |
| -p 00000000000000000000000000000000 >/dev/null & done |
| |
| Signed-off-by: Rabin Vincent <rabin.vincent@axis.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| crypto/af_alg.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/crypto/af_alg.c |
| +++ b/crypto/af_alg.c |
| @@ -449,6 +449,9 @@ void af_alg_complete(struct crypto_async |
| { |
| struct af_alg_completion *completion = req->data; |
| |
| + if (err == -EINPROGRESS) |
| + return; |
| + |
| completion->err = err; |
| complete(&completion->completion); |
| } |