Commit e162d78d authored by Herbert Xu's avatar Herbert Xu Committed by GUO Zihua
Browse files

crypto: algif_aead - Only wake up when ctx->more is zero

mainline inclusion
from mainline-v5.9-rc1
commit f3c802a1
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I992IL
CVE: NA

Reference: https://github.com/torvalds/linux/commit/f3c802a1f30013f8f723b62d7fa49eb9e991da23



--------------------------------

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: 2d97591e ("crypto: af_alg - consolidation of...")
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Conflicts:
	include/crypto/if_alg.h
Signed-off-by: default avatarGUO Zihua <guozihua@huawei.com>
parent 8e3c9317
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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) {
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+3 −1
Original line number Diff line number Diff line
@@ -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);