crypto: algif_aead - Only wake up when ctx->more is zero
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 29 May 2020 14:23:49 +0000 (00:23 +1000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 18 Jun 2020 07:19:44 +0000 (17:19 +1000)
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: 2d97591ef43d ("crypto: af_alg - consolidation of...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/af_alg.c
crypto/algif_aead.c
crypto/algif_skcipher.c
include/crypto/if_alg.h

index 28fc323..9fcb91e 100644 (file)
@@ -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) {
index 0ae000a..d48d215 100644 (file)
@@ -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;
        }
index ec5567c..a51ba22 100644 (file)
@@ -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;
        }
index 088c1de..ee64123 100644 (file)
@@ -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,