| From f3c802a1f30013f8f723b62d7fa49eb9e991da23 Mon Sep 17 00:00:00 2001 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Sat, 30 May 2020 00:23:49 +1000 |
| Subject: [PATCH] crypto: algif_aead - Only wake up when ctx->more is zero |
| |
| commit f3c802a1f30013f8f723b62d7fa49eb9e991da23 upstream. |
| |
| AEAD does not support partial requests so we must not wake up |
| while ctx->more is set. In order to distinguish between the |
| case of no data sent yet and a zero-length request, a new init |
| flag has been added to ctx. |
| |
| SKCIPHER has also been modified to ensure that at least a block |
| of data is available if there is more data to come. |
| |
| Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of...") |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| |
| diff --git a/crypto/af_alg.c b/crypto/af_alg.c |
| index 28fc323e3fe3..9fcb91ea10c4 100644 |
| --- a/crypto/af_alg.c |
| +++ b/crypto/af_alg.c |
| @@ -635,6 +635,7 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst, |
| |
| if (!ctx->used) |
| ctx->merge = 0; |
| + ctx->init = ctx->more; |
| } |
| EXPORT_SYMBOL_GPL(af_alg_pull_tsgl); |
| |
| @@ -734,9 +735,10 @@ EXPORT_SYMBOL_GPL(af_alg_wmem_wakeup); |
| * |
| * @sk socket of connection to user space |
| * @flags If MSG_DONTWAIT is set, then only report if function would sleep |
| + * @min Set to minimum request size if partial requests are allowed. |
| * @return 0 when writable memory is available, < 0 upon error |
| */ |
| -int af_alg_wait_for_data(struct sock *sk, unsigned flags) |
| +int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min) |
| { |
| DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| struct alg_sock *ask = alg_sk(sk); |
| @@ -754,7 +756,9 @@ int af_alg_wait_for_data(struct sock *sk, unsigned flags) |
| if (signal_pending(current)) |
| break; |
| timeout = MAX_SCHEDULE_TIMEOUT; |
| - if (sk_wait_event(sk, &timeout, (ctx->used || !ctx->more), |
| + if (sk_wait_event(sk, &timeout, |
| + ctx->init && (!ctx->more || |
| + (min && ctx->used >= min)), |
| &wait)) { |
| err = 0; |
| break; |
| @@ -843,7 +847,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, |
| } |
| |
| lock_sock(sk); |
| - if (!ctx->more && ctx->used) { |
| + if (ctx->init && (init || !ctx->more)) { |
| err = -EINVAL; |
| goto unlock; |
| } |
| @@ -854,6 +858,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, |
| memcpy(ctx->iv, con.iv->iv, ivsize); |
| |
| ctx->aead_assoclen = con.aead_assoclen; |
| + ctx->init = true; |
| } |
| |
| while (size) { |
| diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c |
| index 0ae000a61c7f..d48d2156e621 100644 |
| --- a/crypto/algif_aead.c |
| +++ b/crypto/algif_aead.c |
| @@ -106,8 +106,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, |
| size_t usedpages = 0; /* [in] RX bufs to be used from user */ |
| size_t processed = 0; /* [in] TX bufs to be consumed */ |
| |
| - if (!ctx->used) { |
| - err = af_alg_wait_for_data(sk, flags); |
| + if (!ctx->init || ctx->more) { |
| + err = af_alg_wait_for_data(sk, flags, 0); |
| if (err) |
| return err; |
| } |
| diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c |
| index ec5567c87a6d..a51ba22fef58 100644 |
| --- a/crypto/algif_skcipher.c |
| +++ b/crypto/algif_skcipher.c |
| @@ -61,8 +61,8 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, |
| int err = 0; |
| size_t len = 0; |
| |
| - if (!ctx->used) { |
| - err = af_alg_wait_for_data(sk, flags); |
| + if (!ctx->init || (ctx->more && ctx->used < bs)) { |
| + err = af_alg_wait_for_data(sk, flags, bs); |
| if (err) |
| return err; |
| } |
| diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h |
| index 088c1ded2714..ee6412314f8f 100644 |
| --- a/include/crypto/if_alg.h |
| +++ b/include/crypto/if_alg.h |
| @@ -135,6 +135,7 @@ struct af_alg_async_req { |
| * SG? |
| * @enc: Cryptographic operation to be performed when |
| * recvmsg is invoked. |
| + * @init: True if metadata has been sent. |
| * @len: Length of memory allocated for this data structure. |
| */ |
| struct af_alg_ctx { |
| @@ -151,6 +152,7 @@ struct af_alg_ctx { |
| bool more; |
| bool merge; |
| bool enc; |
| + bool init; |
| |
| unsigned int len; |
| }; |
| @@ -226,7 +228,7 @@ unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset); |
| void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst, |
| size_t dst_offset); |
| void af_alg_wmem_wakeup(struct sock *sk); |
| -int af_alg_wait_for_data(struct sock *sk, unsigned flags); |
| +int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min); |
| int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, |
| unsigned int ivsize); |
| ssize_t af_alg_sendpage(struct socket *sock, struct page *page, |
| -- |
| 2.27.0 |
| |