Commit f3c802a1 authored by Herbert Xu's avatar Herbert Xu
Browse files

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



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>
parent 1532e31f
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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) {
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+3 −1
Original line number Diff line number Diff line
@@ -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,