mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 10:10:33 +02:00 
			
		
		
		
	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: 2d97591ef4 ("crypto: af_alg - consolidation of...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
			
			
This commit is contained in:
		
							parent
							
								
									1532e31f50
								
							
						
					
					
						commit
						f3c802a1f3
					
				
					 4 changed files with 15 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue