Somewhere along the line the cap on the SG list length for receive
was lost. This patch restores it and removes the subsequent test
which is now redundant.
Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of...")
Cc: <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index e2c8ab408bed..4c3bdffe0c3a 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -74,14 +74,10 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
return PTR_ERR(areq);
/* convert iovecs of output buffers into RX SGL */
- err = af_alg_get_rsgl(sk, msg, flags, areq, -1, &len);
+ err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
if (err)
goto free;
- /* Process only as much RX buffers for which we have TX data */
- if (len > ctx->used)
- len = ctx->used;
-
/*
* If more buffers are to be expected to be processed, process only
* full block size buffers.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Am Freitag, 29. Mai 2020, 06:54:43 CEST schrieb Herbert Xu:
Hi Herbert,
> Somewhere along the line the cap on the SG list length for receive
> was lost. This patch restores it and removes the subsequent test
> which is now redundant.
>
> Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of...")
> Cc: <[email protected]>
> Signed-off-by: Herbert Xu <[email protected]>
Reviewed-by: Stephan Mueller <[email protected]>
Thanks
Ciao
Stephan
If a read(2) of less than a full block size is attempted we will
end up doing a zero-length operation. This patch makes that return
-EINVAL instead, which is what we did originally.
Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory...")
Signed-off-by: Herbert Xu <[email protected]>
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 4c3bdffe0c3a5..24dd2fc2431cc 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -85,6 +85,10 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
if (ctx->more || len < ctx->used)
len -= len % bs;
+ err = -EINVAL;
+ if (!len)
+ goto free;
+
/*
* Create a per request TX SGL for this request which tracks the
* SG entries from the global TX SGL.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
AEAD does not support partial requests so we must not wake up
while ctx->more is set. While we're fixing this also change
algif_skcipher to only wake up when at least a block is available
as otherwise we'd just fail straight away with -EINVAL.
Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of...")
Signed-off-by: Herbert Xu <[email protected]>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index b1cd3535c5256..474a9511f0ed4 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -738,9 +738,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);
@@ -758,7 +759,8 @@ 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,
+ (min && ctx->used >= min) || !ctx->more,
&wait)) {
err = 0;
break;
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index eb1910b6d434c..efea00046be65 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -107,7 +107,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
size_t processed = 0; /* [in] TX bufs to be consumed */
if (!ctx->used) {
- err = af_alg_wait_for_data(sk, flags);
+ err = af_alg_wait_for_data(sk, flags, 0);
if (err)
return err;
}
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 24dd2fc2431cc..5b334fd9432c0 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -62,7 +62,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
size_t len = 0;
if (!ctx->used) {
- err = af_alg_wait_for_data(sk, flags);
+ err = af_alg_wait_for_data(sk, flags, bs);
if (err)
return err;
}
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 56527c85d1222..e1e5525473e4c 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -226,7 +226,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,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
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 <[email protected]>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index b1cd3535c5256..3366a3173e733 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -639,6 +639,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);
@@ -738,9 +739,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);
@@ -758,7 +760,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;
@@ -847,7 +851,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;
}
@@ -858,6 +862,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) {
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index eb1910b6d434c..857e9598e4dc0 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -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;
}
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 24dd2fc2431cc..a2a588c71bdab 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -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;
}
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 56527c85d1222..98fb5b3158f2a 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -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,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt