forked from mirrors/linux
		
	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) | 	if (!ctx->used) | ||||||
| 		ctx->merge = 0; | 		ctx->merge = 0; | ||||||
|  | 	ctx->init = ctx->more; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(af_alg_pull_tsgl); | 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 |  * @sk socket of connection to user space | ||||||
|  * @flags If MSG_DONTWAIT is set, then only report if function would sleep |  * @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 |  * @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); | 	DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||||||
| 	struct alg_sock *ask = alg_sk(sk); | 	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)) | 		if (signal_pending(current)) | ||||||
| 			break; | 			break; | ||||||
| 		timeout = MAX_SCHEDULE_TIMEOUT; | 		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)) { | 				  &wait)) { | ||||||
| 			err = 0; | 			err = 0; | ||||||
| 			break; | 			break; | ||||||
|  | @ -843,7 +847,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
| 	if (!ctx->more && ctx->used) { | 	if (ctx->init && (init || !ctx->more)) { | ||||||
| 		err = -EINVAL; | 		err = -EINVAL; | ||||||
| 		goto unlock; | 		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); | 			memcpy(ctx->iv, con.iv->iv, ivsize); | ||||||
| 
 | 
 | ||||||
| 		ctx->aead_assoclen = con.aead_assoclen; | 		ctx->aead_assoclen = con.aead_assoclen; | ||||||
|  | 		ctx->init = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	while (size) { | 	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 usedpages = 0;		/* [in]  RX bufs to be used from user */ | ||||||
| 	size_t processed = 0;		/* [in]  TX bufs to be consumed */ | 	size_t processed = 0;		/* [in]  TX bufs to be consumed */ | ||||||
| 
 | 
 | ||||||
| 	if (!ctx->used) { | 	if (!ctx->init || ctx->more) { | ||||||
| 		err = af_alg_wait_for_data(sk, flags); | 		err = af_alg_wait_for_data(sk, flags, 0); | ||||||
| 		if (err) | 		if (err) | ||||||
| 			return err; | 			return err; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -61,8 +61,8 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, | ||||||
| 	int err = 0; | 	int err = 0; | ||||||
| 	size_t len = 0; | 	size_t len = 0; | ||||||
| 
 | 
 | ||||||
| 	if (!ctx->used) { | 	if (!ctx->init || (ctx->more && ctx->used < bs)) { | ||||||
| 		err = af_alg_wait_for_data(sk, flags); | 		err = af_alg_wait_for_data(sk, flags, bs); | ||||||
| 		if (err) | 		if (err) | ||||||
| 			return err; | 			return err; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -135,6 +135,7 @@ struct af_alg_async_req { | ||||||
|  *			SG? |  *			SG? | ||||||
|  * @enc:		Cryptographic operation to be performed when |  * @enc:		Cryptographic operation to be performed when | ||||||
|  *			recvmsg is invoked. |  *			recvmsg is invoked. | ||||||
|  |  * @init:		True if metadata has been sent. | ||||||
|  * @len:		Length of memory allocated for this data structure. |  * @len:		Length of memory allocated for this data structure. | ||||||
|  */ |  */ | ||||||
| struct af_alg_ctx { | struct af_alg_ctx { | ||||||
|  | @ -151,6 +152,7 @@ struct af_alg_ctx { | ||||||
| 	bool more; | 	bool more; | ||||||
| 	bool merge; | 	bool merge; | ||||||
| 	bool enc; | 	bool enc; | ||||||
|  | 	bool init; | ||||||
| 
 | 
 | ||||||
| 	unsigned int len; | 	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, | void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst, | ||||||
| 		      size_t dst_offset); | 		      size_t dst_offset); | ||||||
| void af_alg_wmem_wakeup(struct sock *sk); | 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, | int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 		   unsigned int ivsize); | 		   unsigned int ivsize); | ||||||
| ssize_t af_alg_sendpage(struct socket *sock, struct page *page, | ssize_t af_alg_sendpage(struct socket *sock, struct page *page, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Herbert Xu
						Herbert Xu