Commit f3c802a1 authored by Herbert Xu's avatar Herbert Xu

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
...@@ -635,6 +635,7 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst, ...@@ -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); ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment