From: Herbert Xu herbert@gondor.apana.org.au
mainline inclusion from mainline-v5.9-rc1 commit f3c802a1f30013f8f723b62d7fa49eb9e991da23 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I992IL CVE: NA
Reference: https://github.com/torvalds/linux/commit/f3c802a1f30013f8f723b62d7fa49eb9e99...
--------------------------------
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 Conflicts: include/crypto/if_alg.h Signed-off-by: GUO Zihua guozihua@huawei.com --- crypto/af_alg.c | 11 ++++++++--- crypto/algif_aead.c | 4 ++-- crypto/algif_skcipher.c | 4 ++-- include/crypto/if_alg.h | 4 +++- 4 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 2b8f690130c5..4a116f8ca842 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -648,6 +648,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);
@@ -749,9 +750,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); @@ -769,7 +771,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; @@ -860,7 +864,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; } @@ -871,6 +875,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 3f20d3e4acfb..43a861a79209 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -110,8 +110,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 94aeb8b946b0..c5813e14e905 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -65,8 +65,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 ba9828506aab..9ff2826cdd48 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -140,6 +140,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. * @inflight: Non-zero when AIO requests are in flight. */ @@ -157,6 +158,7 @@ struct af_alg_ctx { bool more; bool merge; bool enc; + bool init;
unsigned int len;
@@ -240,7 +242,7 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst, void af_alg_free_areq_sgls(struct af_alg_async_req *areq); int af_alg_wait_for_wmem(struct sock *sk, unsigned int flags); 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); void af_alg_data_wakeup(struct sock *sk); int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, unsigned int ivsize);